2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
80 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
81 static gpointer mono_class_get_exception_data (const MonoClass *klass);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
112 static MonoNativeTlsKey setup_fields_tls_id;
117 mono_locks_os_acquire (&classes_mutex, ClassesLock);
121 classes_unlock (void)
123 mono_locks_os_release (&classes_mutex, ClassesLock);
127 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
130 enable_gclass_recording (void)
132 ++record_gclass_instantiation;
136 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
139 disable_gclass_recording (gclass_record_func func, void *user_data)
141 GSList **head = &gclass_recorded_list;
143 g_assert (record_gclass_instantiation > 0);
144 --record_gclass_instantiation;
147 GSList *node = *head;
148 if (func ((MonoClass*)node->data, user_data)) {
150 g_slist_free_1 (node);
156 /* We automatically discard all recorded gclasses when disabled. */
157 if (!record_gclass_instantiation && gclass_recorded_list) {
158 g_slist_free (gclass_recorded_list);
159 gclass_recorded_list = NULL;
164 * mono_class_from_typeref:
165 * @image: a MonoImage
166 * @type_token: a TypeRef token
168 * Creates the MonoClass* structure representing the type defined by
169 * the typeref token valid inside @image.
170 * Returns: The MonoClass* representing the typeref token, NULL ifcould
174 mono_class_from_typeref (MonoImage *image, guint32 type_token)
177 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
178 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
183 * mono_class_from_typeref_checked:
184 * @image: a MonoImage
185 * @type_token: a TypeRef token
186 * @error: error return code, if any.
188 * Creates the MonoClass* structure representing the type defined by
189 * the typeref token valid inside @image.
191 * Returns: The MonoClass* representing the typeref token, NULL if it could
192 * not be loaded with the @error value filled with the information about the
196 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
198 guint32 cols [MONO_TYPEREF_SIZE];
199 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
201 const char *name, *nspace;
202 MonoClass *res = NULL;
205 mono_error_init (error);
207 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
210 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
212 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
213 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
215 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
216 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
217 case MONO_RESOLUTION_SCOPE_MODULE:
219 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
220 This is not the observed behavior of existing implementations.
221 The defacto behavior is that it's just a typedef in disguise.
223 /* a typedef in disguise */
224 res = mono_class_from_name_checked (image, nspace, name, error);
227 case MONO_RESOLUTION_SCOPE_MODULEREF:
228 module = mono_image_load_module_checked (image, idx, error);
230 res = mono_class_from_name_checked (module, nspace, name, error);
233 case MONO_RESOLUTION_SCOPE_TYPEREF: {
234 MonoClass *enclosing;
237 if (idx == mono_metadata_token_index (type_token)) {
238 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
242 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
243 return_val_if_nok (error, NULL);
245 if (enclosing->nested_classes_inited && enclosing->ext) {
246 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
247 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
248 res = (MonoClass *)tmp->data;
249 if (strcmp (res->name, name) == 0)
253 /* Don't call mono_class_init as we might've been called by it recursively */
254 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
256 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
257 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
258 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
260 if (strcmp (nname, name) == 0)
261 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
263 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
266 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
269 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
273 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
274 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
278 if (!image->references || !image->references [idx - 1])
279 mono_assembly_load_reference (image, idx - 1);
280 g_assert (image->references [idx - 1]);
282 /* If the assembly did not load, register this as a type load exception */
283 if (image->references [idx - 1] == REFERENCE_MISSING){
284 MonoAssemblyName aname;
287 mono_assembly_get_assemblyref (image, idx - 1, &aname);
288 human_name = mono_stringify_assembly_name (&aname);
289 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
293 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
296 /* Generic case, should be avoided for when a better error is possible. */
297 if (!res && mono_error_ok (error)) {
298 char *name = mono_class_name_from_token (image, type_token);
299 char *assembly = mono_assembly_name_from_token (image, type_token);
300 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
307 mono_image_memdup (MonoImage *image, void *data, guint size)
309 void *res = mono_image_alloc (image, size);
310 memcpy (res, data, size);
314 /* Copy everything mono_metadata_free_array free. */
316 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
319 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
321 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
323 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
325 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
327 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
329 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
334 /* Copy everything mono_metadata_free_method_signature free. */
336 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
340 sig = mono_metadata_signature_dup_full (image, sig);
342 sig->ret = mono_metadata_type_dup (image, sig->ret);
343 for (i = 0; i < sig->param_count; ++i)
344 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
350 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
352 MonoAssembly *ta = klass->image->assembly;
355 name = mono_stringify_assembly_name (&ta->aname);
356 g_string_append_printf (str, ", %s", name);
361 mono_type_name_check_byref (MonoType *type, GString *str)
364 g_string_append_c (str, '&');
368 * mono_identifier_escape_type_name_chars:
369 * @str: a destination string
370 * @identifier: an IDENTIFIER in internal form
374 * The displayed form of the identifier is appended to str.
376 * The displayed form of an identifier has the characters ,+&*[]\
377 * that have special meaning in type names escaped with a preceeding
378 * backslash (\) character.
381 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
387 // reserve space for common case: there will be no escaped characters.
388 g_string_set_size(str, n + strlen(identifier));
389 g_string_set_size(str, n);
391 for (const char* s = identifier; *s != 0 ; s++) {
400 g_string_append_c (str, '\\');
401 g_string_append_c (str, *s);
404 g_string_append_c (str, *s);
412 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
413 MonoTypeNameFormat format)
417 switch (type->type) {
418 case MONO_TYPE_ARRAY: {
419 int i, rank = type->data.array->rank;
420 MonoTypeNameFormat nested_format;
422 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
423 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
425 mono_type_get_name_recurse (
426 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
427 g_string_append_c (str, '[');
429 g_string_append_c (str, '*');
430 for (i = 1; i < rank; i++)
431 g_string_append_c (str, ',');
432 g_string_append_c (str, ']');
434 mono_type_name_check_byref (type, str);
436 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
437 _mono_type_get_assembly_name (type->data.array->eklass, str);
440 case MONO_TYPE_SZARRAY: {
441 MonoTypeNameFormat nested_format;
443 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
444 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
446 mono_type_get_name_recurse (
447 &type->data.klass->byval_arg, str, FALSE, nested_format);
448 g_string_append (str, "[]");
450 mono_type_name_check_byref (type, str);
452 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
453 _mono_type_get_assembly_name (type->data.klass, str);
456 case MONO_TYPE_PTR: {
457 MonoTypeNameFormat nested_format;
459 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
460 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
462 mono_type_get_name_recurse (
463 type->data.type, str, FALSE, nested_format);
464 g_string_append_c (str, '*');
466 mono_type_name_check_byref (type, str);
468 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
469 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
474 if (!mono_generic_param_info (type->data.generic_param))
475 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
477 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
479 mono_type_name_check_byref (type, str);
483 klass = mono_class_from_mono_type (type);
484 if (klass->nested_in) {
485 mono_type_get_name_recurse (
486 &klass->nested_in->byval_arg, str, TRUE, format);
487 if (format == MONO_TYPE_NAME_FORMAT_IL)
488 g_string_append_c (str, '.');
490 g_string_append_c (str, '+');
491 } else if (*klass->name_space) {
492 if (format == MONO_TYPE_NAME_FORMAT_IL)
493 g_string_append (str, klass->name_space);
495 mono_identifier_escape_type_name_chars (str, klass->name_space);
496 g_string_append_c (str, '.');
498 if (format == MONO_TYPE_NAME_FORMAT_IL) {
499 char *s = strchr (klass->name, '`');
500 int len = s ? s - klass->name : strlen (klass->name);
501 g_string_append_len (str, klass->name, len);
503 mono_identifier_escape_type_name_chars (str, klass->name);
507 if (klass->generic_class) {
508 MonoGenericClass *gclass = klass->generic_class;
509 MonoGenericInst *inst = gclass->context.class_inst;
510 MonoTypeNameFormat nested_format;
513 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
514 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
516 if (format == MONO_TYPE_NAME_FORMAT_IL)
517 g_string_append_c (str, '<');
519 g_string_append_c (str, '[');
520 for (i = 0; i < inst->type_argc; i++) {
521 MonoType *t = inst->type_argv [i];
524 g_string_append_c (str, ',');
525 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
526 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
527 g_string_append_c (str, '[');
528 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
529 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531 g_string_append_c (str, ']');
533 if (format == MONO_TYPE_NAME_FORMAT_IL)
534 g_string_append_c (str, '>');
536 g_string_append_c (str, ']');
537 } else if (klass->generic_container &&
538 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
539 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
542 if (format == MONO_TYPE_NAME_FORMAT_IL)
543 g_string_append_c (str, '<');
545 g_string_append_c (str, '[');
546 for (i = 0; i < klass->generic_container->type_argc; i++) {
548 g_string_append_c (str, ',');
549 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
551 if (format == MONO_TYPE_NAME_FORMAT_IL)
552 g_string_append_c (str, '>');
554 g_string_append_c (str, ']');
557 mono_type_name_check_byref (type, str);
559 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
560 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
561 _mono_type_get_assembly_name (klass, str);
567 * mono_type_get_name_full:
569 * @format: the format for the return string.
572 * Returns: The string representation in a number of formats:
574 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
575 * returned in the formatrequired by System.Reflection, this is the
576 * inverse of mono_reflection_parse_type ().
578 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
579 * be used by the IL assembler.
581 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
583 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
586 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
590 result = g_string_new ("");
592 mono_type_get_name_recurse (type, result, FALSE, format);
594 return g_string_free (result, FALSE);
598 * mono_type_get_full_name:
601 * Returns: The string representation for type as required by System.Reflection.
602 * The inverse of mono_reflection_parse_type ().
605 mono_type_get_full_name (MonoClass *klass)
607 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
611 * mono_type_get_name:
614 * Returns: The string representation for type as it would be represented in IL code.
617 mono_type_get_name (MonoType *type)
619 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
623 * mono_type_get_underlying_type:
626 * Returns: The MonoType for the underlying integer type if @type
627 * is an enum and byref is false, otherwise the type itself.
630 mono_type_get_underlying_type (MonoType *type)
632 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
633 return mono_class_enum_basetype (type->data.klass);
634 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
635 return mono_class_enum_basetype (type->data.generic_class->container_class);
640 * mono_class_is_open_constructed_type:
643 * Returns: TRUE if type represents a generics open constructed type.
644 * IOW, not all type parameters required for the instantiation have
645 * been provided or it's a generic type definition.
647 * An open constructed type means it's a non realizable type. Not to
648 * be mixed up with an abstract type - we can't cast or dispatch to
649 * an open type, for example.
652 mono_class_is_open_constructed_type (MonoType *t)
658 case MONO_TYPE_SZARRAY:
659 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
660 case MONO_TYPE_ARRAY:
661 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
663 return mono_class_is_open_constructed_type (t->data.type);
664 case MONO_TYPE_GENERICINST:
665 return t->data.generic_class->context.class_inst->is_open;
666 case MONO_TYPE_CLASS:
667 case MONO_TYPE_VALUETYPE:
668 return t->data.klass->generic_container != NULL;
675 This is a simple function to catch the most common bad instances of generic types.
676 Specially those that might lead to further failures in the runtime.
679 is_valid_generic_argument (MonoType *type)
681 switch (type->type) {
683 //case MONO_TYPE_TYPEDBYREF:
691 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
693 mono_error_init (error);
695 switch (type->type) {
696 case MONO_TYPE_MVAR: {
698 int num = mono_type_get_generic_param_num (type);
699 MonoGenericInst *inst = context->method_inst;
702 if (num >= inst->type_argc) {
703 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
704 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
705 num, info ? info->name : "", inst->type_argc);
709 if (!is_valid_generic_argument (inst->type_argv [num])) {
710 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
711 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
712 num, info ? info->name : "", inst->type_argv [num]->type);
716 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
717 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
718 * ->byref and ->attrs from @type are propagated to the returned type.
720 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
721 nt->byref = type->byref;
722 nt->attrs = type->attrs;
725 case MONO_TYPE_VAR: {
727 int num = mono_type_get_generic_param_num (type);
728 MonoGenericInst *inst = context->class_inst;
731 if (num >= inst->type_argc) {
732 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
733 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
734 num, info ? info->name : "", inst->type_argc);
737 if (!is_valid_generic_argument (inst->type_argv [num])) {
738 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
739 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
740 num, info ? info->name : "", inst->type_argv [num]->type);
743 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
744 nt->byref = type->byref;
745 nt->attrs = type->attrs;
748 case MONO_TYPE_SZARRAY: {
749 MonoClass *eclass = type->data.klass;
750 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
751 if (!inflated || !mono_error_ok (error))
753 nt = mono_metadata_type_dup (image, type);
754 nt->data.klass = mono_class_from_mono_type (inflated);
755 mono_metadata_free_type (inflated);
758 case MONO_TYPE_ARRAY: {
759 MonoClass *eclass = type->data.array->eklass;
760 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
761 if (!inflated || !mono_error_ok (error))
763 nt = mono_metadata_type_dup (image, type);
764 nt->data.array->eklass = mono_class_from_mono_type (inflated);
765 mono_metadata_free_type (inflated);
768 case MONO_TYPE_GENERICINST: {
769 MonoGenericClass *gclass = type->data.generic_class;
770 MonoGenericInst *inst;
772 if (!gclass->context.class_inst->is_open)
775 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
776 return_val_if_nok (error, NULL);
778 if (inst != gclass->context.class_inst)
779 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
781 if (gclass == type->data.generic_class)
784 nt = mono_metadata_type_dup (image, type);
785 nt->data.generic_class = gclass;
788 case MONO_TYPE_CLASS:
789 case MONO_TYPE_VALUETYPE: {
790 MonoClass *klass = type->data.klass;
791 MonoGenericContainer *container = klass->generic_container;
792 MonoGenericInst *inst;
793 MonoGenericClass *gclass = NULL;
799 /* We can't use context->class_inst directly, since it can have more elements */
800 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
801 return_val_if_nok (error, NULL);
803 if (inst == container->context.class_inst)
806 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
808 nt = mono_metadata_type_dup (image, type);
809 nt->type = MONO_TYPE_GENERICINST;
810 nt->data.generic_class = gclass;
820 mono_generic_class_get_context (MonoGenericClass *gclass)
822 return &gclass->context;
826 mono_class_get_context (MonoClass *klass)
828 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
832 * mono_class_get_generic_container:
834 * Return the generic container of KLASS which should be a generic type definition.
836 MonoGenericContainer*
837 mono_class_get_generic_container (MonoClass *klass)
839 g_assert (klass->is_generic);
841 return klass->generic_container;
845 * mono_class_get_generic_class:
847 * Return the MonoGenericClass of KLASS, which should be a generic instance.
850 mono_class_get_generic_class (MonoClass *klass)
852 g_assert (klass->is_inflated);
854 return klass->generic_class;
858 * mono_class_inflate_generic_type_with_mempool:
859 * @mempool: a mempool
861 * @context: a generics context
862 * @error: error context
864 * The same as mono_class_inflate_generic_type, but allocates the MonoType
865 * from mempool if it is non-NULL. If it is NULL, the MonoType is
866 * allocated on the heap and is owned by the caller.
867 * The returned type can potentially be the same as TYPE, so it should not be
868 * modified by the caller, and it should be freed using mono_metadata_free_type ().
871 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
873 MonoType *inflated = NULL;
874 mono_error_init (error);
877 inflated = inflate_generic_type (image, type, context, error);
878 return_val_if_nok (error, NULL);
881 MonoType *shared = mono_metadata_get_shared_type (type);
886 return mono_metadata_type_dup (image, type);
890 mono_stats.inflated_type_count++;
895 * mono_class_inflate_generic_type:
897 * @context: a generics context
899 * If @type is a generic type and @context is not NULL, instantiate it using the
900 * generics context @context.
902 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
903 * on the heap and is owned by the caller. Returns NULL on error.
905 * @deprecated Please use mono_class_inflate_generic_type_checked instead
908 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
912 result = mono_class_inflate_generic_type_checked (type, context, &error);
913 mono_error_cleanup (&error);
918 * mono_class_inflate_generic_type:
920 * @context: a generics context
921 * @error: error context to use
923 * If @type is a generic type and @context is not NULL, instantiate it using the
924 * generics context @context.
926 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
927 * on the heap and is owned by the caller.
930 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
932 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
936 * mono_class_inflate_generic_type_no_copy:
938 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
942 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
944 MonoType *inflated = NULL;
946 mono_error_init (error);
948 inflated = inflate_generic_type (image, type, context, error);
949 return_val_if_nok (error, NULL);
955 mono_stats.inflated_type_count++;
960 * mono_class_inflate_generic_class:
962 * Inflate the class @gklass with @context. Set @error on failure.
965 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
970 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
971 return_val_if_nok (error, NULL);
973 res = mono_class_from_mono_type (inflated);
974 mono_metadata_free_type (inflated);
979 static MonoGenericContext
980 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
982 MonoGenericInst *class_inst = NULL;
983 MonoGenericInst *method_inst = NULL;
984 MonoGenericContext res = { NULL, NULL };
986 mono_error_init (error);
988 if (context->class_inst) {
989 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
990 if (!mono_error_ok (error))
994 if (context->method_inst) {
995 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
996 if (!mono_error_ok (error))
1000 res.class_inst = class_inst;
1001 res.method_inst = method_inst;
1007 * mono_class_inflate_generic_method:
1008 * @method: a generic method
1009 * @context: a generics context
1011 * Instantiate the generic method @method using the generics context @context.
1013 * Returns: The new instantiated method
1016 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1018 return mono_class_inflate_generic_method_full (method, NULL, context);
1022 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1024 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1028 * mono_class_inflate_generic_method_full:
1030 * Instantiate method @method with the generic context @context.
1031 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1032 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1035 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1038 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1039 if (!mono_error_ok (&error))
1040 /*FIXME do proper error handling - on this case, kill this function. */
1041 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1047 * mono_class_inflate_generic_method_full_checked:
1048 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1051 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1054 MonoMethodInflated *iresult, *cached;
1055 MonoMethodSignature *sig;
1056 MonoGenericContext tmp_context;
1058 mono_error_init (error);
1060 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1061 while (method->is_inflated) {
1062 MonoGenericContext *method_context = mono_method_get_context (method);
1063 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1065 tmp_context = inflate_generic_context (method_context, context, error);
1066 return_val_if_nok (error, NULL);
1068 context = &tmp_context;
1070 if (mono_metadata_generic_context_equal (method_context, context))
1073 method = imethod->declaring;
1077 * A method only needs to be inflated if the context has argument for which it is
1080 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1081 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1084 if (!((method->is_generic && context->method_inst) ||
1085 (method->klass->generic_container && context->class_inst)))
1088 iresult = g_new0 (MonoMethodInflated, 1);
1089 iresult->context = *context;
1090 iresult->declaring = method;
1092 if (!context->method_inst && method->is_generic)
1093 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1095 if (!context->class_inst) {
1096 g_assert (!iresult->declaring->klass->generic_class);
1097 if (iresult->declaring->klass->generic_container)
1098 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1099 else if (iresult->declaring->klass->generic_class)
1100 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1102 /* This can happen with some callers like mono_object_get_virtual_method () */
1103 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1104 iresult->context.class_inst = NULL;
1106 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1109 mono_image_set_lock (set);
1110 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1111 mono_image_set_unlock (set);
1115 return (MonoMethod*)cached;
1118 mono_stats.inflated_method_count++;
1120 inflated_methods_size += sizeof (MonoMethodInflated);
1122 sig = mono_method_signature (method);
1124 char *name = mono_type_get_full_name (method->klass);
1125 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1131 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1133 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1136 result = (MonoMethod *) iresult;
1137 result->is_inflated = TRUE;
1138 result->is_generic = FALSE;
1139 result->sre_method = FALSE;
1140 result->signature = NULL;
1142 if (method->wrapper_type) {
1143 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1144 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1145 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1147 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1148 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1151 if (iresult->context.method_inst) {
1152 /* Set the generic_container of the result to the generic_container of method */
1153 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1155 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1156 result->is_generic = 1;
1157 mono_method_set_generic_container (result, generic_container);
1161 if (!klass_hint || !klass_hint->generic_class ||
1162 klass_hint->generic_class->container_class != method->klass ||
1163 klass_hint->generic_class->context.class_inst != context->class_inst)
1166 if (method->klass->generic_container)
1167 result->klass = klass_hint;
1169 if (!result->klass) {
1170 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1171 if (!mono_error_ok (error))
1174 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1176 mono_metadata_free_type (inflated);
1180 * FIXME: This should hold, but it doesn't:
1182 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1183 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1184 * g_assert (result->is_generic);
1187 * Fixing this here causes other things to break, hence a very
1188 * ugly hack in mini-trampolines.c - see
1189 * is_generic_method_definition().
1193 mono_image_set_lock (set);
1194 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1196 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1197 iresult->owner = set;
1200 mono_image_set_unlock (set);
1202 return (MonoMethod*)cached;
1210 * mono_get_inflated_method:
1212 * Obsolete. We keep it around since it's mentioned in the public API.
1215 mono_get_inflated_method (MonoMethod *method)
1221 * mono_method_get_context_general:
1223 * @uninflated: handle uninflated methods?
1225 * Returns the generic context of a method or NULL if it doesn't have
1226 * one. For an inflated method that's the context stored in the
1227 * method. Otherwise it's in the method's generic container or in the
1228 * generic container of the method's class.
1231 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1233 if (method->is_inflated) {
1234 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1235 return &imethod->context;
1239 if (method->is_generic)
1240 return &(mono_method_get_generic_container (method)->context);
1241 if (method->klass->generic_container)
1242 return &method->klass->generic_container->context;
1247 * mono_method_get_context:
1250 * Returns the generic context for method if it's inflated, otherwise
1254 mono_method_get_context (MonoMethod *method)
1256 return mono_method_get_context_general (method, FALSE);
1260 * mono_method_get_generic_container:
1262 * Returns the generic container of METHOD, which should be a generic method definition.
1263 * Returns NULL if METHOD is not a generic method definition.
1264 * LOCKING: Acquires the loader lock.
1266 MonoGenericContainer*
1267 mono_method_get_generic_container (MonoMethod *method)
1269 MonoGenericContainer *container;
1271 if (!method->is_generic)
1274 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1275 g_assert (container);
1281 * mono_method_set_generic_container:
1283 * Sets the generic container of METHOD to CONTAINER.
1284 * LOCKING: Acquires the image lock.
1287 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1289 g_assert (method->is_generic);
1291 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1295 * mono_class_find_enum_basetype:
1296 * @class: The enum class
1298 * Determine the basetype of an enum by iterating through its fields. We do this
1299 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1302 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1304 MonoGenericContainer *container = NULL;
1305 MonoImage *m = klass->image;
1306 const int top = klass->field.count;
1309 g_assert (klass->enumtype);
1311 mono_error_init (error);
1313 if (klass->generic_container)
1314 container = klass->generic_container;
1315 else if (klass->generic_class) {
1316 MonoClass *gklass = klass->generic_class->container_class;
1318 container = gklass->generic_container;
1319 g_assert (container);
1323 * Fetch all the field information.
1325 for (i = 0; i < top; i++){
1327 guint32 cols [MONO_FIELD_SIZE];
1328 int idx = klass->field.first + i;
1331 /* klass->field.first and idx points into the fieldptr table */
1332 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1334 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1337 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1338 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1342 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1343 mono_metadata_decode_value (sig, &sig);
1344 /* FIELD signature == 0x06 */
1346 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1350 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1354 if (klass->generic_class) {
1355 //FIXME do we leak here?
1356 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1357 if (!mono_error_ok (error))
1359 ftype->attrs = cols [MONO_FIELD_FLAGS];
1364 mono_error_set_type_load_class (error, klass, "Could not find base type");
1371 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1374 mono_type_has_exceptions (MonoType *type)
1376 switch (type->type) {
1377 case MONO_TYPE_CLASS:
1378 case MONO_TYPE_VALUETYPE:
1379 case MONO_TYPE_SZARRAY:
1380 return mono_class_has_failure (type->data.klass);
1381 case MONO_TYPE_ARRAY:
1382 return mono_class_has_failure (type->data.array->eklass);
1383 case MONO_TYPE_GENERICINST:
1384 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1391 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1393 g_assert (mono_class_has_failure (klass));
1394 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1395 mono_error_set_from_boxed (oerror, box);
1402 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1406 mono_class_alloc (MonoClass *klass, int size)
1408 if (klass->generic_class)
1409 return mono_image_set_alloc (klass->generic_class->owner, size);
1411 return mono_image_alloc (klass->image, size);
1415 mono_class_alloc0 (MonoClass *klass, int size)
1419 res = mono_class_alloc (klass, size);
1420 memset (res, 0, size);
1424 #define mono_class_new0(klass,struct_type, n_structs) \
1425 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1428 * mono_class_setup_basic_field_info:
1429 * @class: The class to initialize
1431 * Initializes the following fields in MonoClass:
1432 * * klass->fields (only field->parent and field->name)
1433 * * klass->field.count
1434 * * klass->field.first
1435 * LOCKING: Acquires the loader lock
1438 mono_class_setup_basic_field_info (MonoClass *klass)
1440 MonoClassField *field;
1441 MonoClassField *fields;
1449 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1450 image = klass->image;
1452 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1454 * This happens when a generic instance of an unfinished generic typebuilder
1455 * is used as an element type for creating an array type. We can't initialize
1456 * the fields of this class using the fields of gklass, since gklass is not
1457 * finished yet, fields could be added to it later.
1463 mono_class_setup_basic_field_info (gtd);
1465 mono_loader_lock ();
1466 klass->field.first = gtd->field.first;
1467 klass->field.count = gtd->field.count;
1468 mono_loader_unlock ();
1471 top = klass->field.count;
1473 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1476 * Fetch all the field information.
1478 for (i = 0; i < top; i++){
1479 field = &fields [i];
1480 field->parent = klass;
1483 field->name = mono_field_get_name (>d->fields [i]);
1485 int idx = klass->field.first + i;
1486 /* klass->field.first and idx points into the fieldptr table */
1487 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1488 /* The name is needed for fieldrefs */
1489 field->name = mono_metadata_string_heap (image, name_idx);
1493 mono_memory_barrier ();
1495 mono_loader_lock ();
1497 klass->fields = fields;
1498 mono_loader_unlock ();
1502 * mono_class_set_failure_causedby_class:
1503 * @klass: the class that is failing
1504 * @caused_by: the class that caused the failure
1505 * @msg: Why @klass is failing.
1507 * If @caused_by has a failure, sets a TypeLoadException failure on
1508 * @klass with message "@msg, due to: {@caused_by message}".
1510 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1513 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1515 if (mono_class_has_failure (caused_by)) {
1516 MonoError cause_error;
1517 mono_error_init (&cause_error);
1518 mono_error_set_for_class_failure (&cause_error, caused_by);
1519 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1520 mono_error_cleanup (&cause_error);
1529 * mono_class_setup_fields:
1530 * @klass: The class to initialize
1532 * Initializes klass->fields, computes class layout and sizes.
1533 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1534 * Sets the following fields in @klass:
1538 * - has_references (if the class contains instance references firled or structs that contain references)
1539 * - has_static_refs (same, but for static fields)
1540 * - instance_size (size of the object in memory)
1541 * - class_size (size needed for the static fields)
1542 * - size_inited (flag set when the instance_size is set)
1543 * - element_class/cast_class (for enums)
1546 * LOCKING: Acquires the loader lock.
1549 mono_class_setup_fields (MonoClass *klass)
1552 MonoImage *m = klass->image;
1554 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1556 guint32 real_size = 0;
1557 guint32 packing_size = 0;
1559 gboolean explicit_size;
1560 MonoClassField *field;
1563 if (klass->fields_inited)
1566 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1568 * This happens when a generic instance of an unfinished generic typebuilder
1569 * is used as an element type for creating an array type. We can't initialize
1570 * the fields of this class using the fields of gklass, since gklass is not
1571 * finished yet, fields could be added to it later.
1576 mono_class_setup_basic_field_info (klass);
1577 top = klass->field.count;
1579 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1581 mono_class_setup_fields (gtd);
1582 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1587 if (klass->parent) {
1588 /* For generic instances, klass->parent might not have been initialized */
1589 mono_class_init (klass->parent);
1590 mono_class_setup_fields (klass->parent);
1591 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1593 instance_size = klass->parent->instance_size;
1595 instance_size = sizeof (MonoObject);
1598 /* Get the real size */
1599 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1601 instance_size += real_size;
1604 * This function can recursively call itself.
1605 * Prevent infinite recursion by using a list in TLS.
1607 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1608 if (g_slist_find (init_list, klass))
1610 init_list = g_slist_prepend (init_list, klass);
1611 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1614 * Fetch all the field information.
1616 for (i = 0; i < top; i++) {
1617 int idx = klass->field.first + i;
1618 field = &klass->fields [i];
1621 mono_field_resolve_type (field, &error);
1622 if (!mono_error_ok (&error)) {
1623 /*mono_field_resolve_type already failed class*/
1624 mono_error_cleanup (&error);
1628 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1629 g_assert (field->type);
1632 if (mono_field_is_deleted (field))
1634 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1636 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1637 int offset = uoffset;
1639 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1640 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1643 if (offset < -1) { /*-1 is used to encode special static fields */
1644 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1647 if (klass->generic_container) {
1648 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1652 if (mono_type_has_exceptions (field->type)) {
1653 char *class_name = mono_type_get_full_name (klass);
1654 char *type_name = mono_type_full_name (field->type);
1656 mono_class_set_type_load_failure (klass, "");
1657 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1658 g_free (class_name);
1662 /* The def_value of fields is compute lazily during vtable creation */
1665 if (!mono_class_has_failure (klass))
1666 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1668 init_list = g_slist_remove (init_list, klass);
1669 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1673 * mono_class_has_references:
1675 * Returns whenever @klass->has_references is set, initializing it if needed.
1676 * Aquires the loader lock.
1679 mono_class_has_references (MonoClass *klass)
1681 if (klass->init_pending) {
1682 /* Be conservative */
1685 mono_class_init (klass);
1687 return klass->has_references;
1692 * mono_type_get_basic_type_from_generic:
1695 * Returns a closed type corresponding to the possibly open type
1699 mono_type_get_basic_type_from_generic (MonoType *type)
1701 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1702 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1703 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1704 return &mono_defaults.object_class->byval_arg;
1709 type_has_references (MonoClass *klass, MonoType *ftype)
1711 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)))))
1713 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1714 MonoGenericParam *gparam = ftype->data.generic_param;
1716 if (gparam->gshared_constraint)
1717 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1723 * mono_class_layout_fields:
1725 * @base_instance_size: base instance size
1728 * This contains the common code for computing the layout of classes and sizes.
1729 * This should only be called from mono_class_setup_fields () and
1730 * typebuilder_setup_fields ().
1732 * LOCKING: Acquires the loader lock
1735 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1738 const int top = klass->field.count;
1739 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1740 guint32 pass, passes, real_size;
1741 gboolean gc_aware_layout = FALSE;
1742 gboolean has_static_fields = FALSE;
1743 gboolean has_references = FALSE;
1744 gboolean has_static_refs = FALSE;
1745 MonoClassField *field;
1747 int instance_size = base_instance_size;
1748 int class_size, min_align;
1752 * We want to avoid doing complicated work inside locks, so we compute all the required
1753 * information and write it to @klass inside a lock.
1755 if (klass->fields_inited)
1758 if ((packing_size & 0xffffff00) != 0) {
1759 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1763 if (klass->parent) {
1764 min_align = klass->parent->min_align;
1765 /* we use | since it may have been set already */
1766 has_references = klass->has_references | klass->parent->has_references;
1770 /* We can't really enable 16 bytes alignment until the GC supports it.
1771 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1772 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1773 Bug #506144 is an example of this issue.
1775 if (klass->simd_type)
1780 * When we do generic sharing we need to have layout
1781 * information for open generic classes (either with a generic
1782 * context containing type variables or with a generic
1783 * container), so we don't return in that case anymore.
1786 if (klass->enumtype) {
1787 for (i = 0; i < top; i++) {
1788 field = &klass->fields [i];
1789 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1790 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1795 if (!mono_class_enum_basetype (klass)) {
1796 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1802 * Enable GC aware auto layout: in this mode, reference
1803 * fields are grouped together inside objects, increasing collector
1805 * Requires that all classes whose layout is known to native code be annotated
1806 * with [StructLayout (LayoutKind.Sequential)]
1807 * Value types have gc_aware_layout disabled by default, as per
1808 * what the default is for other runtimes.
1810 /* corlib is missing [StructLayout] directives in many places */
1811 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1812 if (!klass->valuetype)
1813 gc_aware_layout = TRUE;
1816 /* Compute klass->blittable */
1819 blittable = klass->parent->blittable;
1820 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1822 for (i = 0; i < top; i++) {
1823 field = &klass->fields [i];
1825 if (mono_field_is_deleted (field))
1827 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1830 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1833 MonoClass *field_class = mono_class_from_mono_type (field->type);
1835 mono_class_setup_fields (field_class);
1836 if (mono_class_has_failure (field_class)) {
1837 MonoError field_error;
1838 mono_error_init (&field_error);
1839 mono_error_set_for_class_failure (&field_error, field_class);
1840 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1841 mono_error_cleanup (&field_error);
1845 if (!field_class || !field_class->blittable)
1849 if (klass->enumtype)
1850 blittable = klass->element_class->blittable;
1852 if (mono_class_has_failure (klass))
1854 if (klass == mono_defaults.string_class)
1857 /* Compute klass->has_references */
1859 * Process non-static fields first, since static fields might recursively
1860 * refer to the class itself.
1862 for (i = 0; i < top; i++) {
1865 field = &klass->fields [i];
1867 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1868 ftype = mono_type_get_underlying_type (field->type);
1869 ftype = mono_type_get_basic_type_from_generic (ftype);
1870 if (type_has_references (klass, ftype))
1871 has_references = TRUE;
1876 * Compute field layout and total size (not considering static fields)
1878 field_offsets = g_new0 (int, top);
1880 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1881 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1882 if (gc_aware_layout)
1887 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1890 if (klass->parent) {
1891 mono_class_setup_fields (klass->parent);
1892 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1894 real_size = klass->parent->instance_size;
1896 real_size = sizeof (MonoObject);
1899 for (pass = 0; pass < passes; ++pass) {
1900 for (i = 0; i < top; i++){
1905 field = &klass->fields [i];
1907 if (mono_field_is_deleted (field))
1909 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1912 ftype = mono_type_get_underlying_type (field->type);
1913 ftype = mono_type_get_basic_type_from_generic (ftype);
1914 if (gc_aware_layout) {
1915 if (type_has_references (klass, ftype)) {
1924 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1925 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1926 /* This field is a hack inserted by MCS to empty structures */
1930 size = mono_type_size (field->type, &align);
1932 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1933 align = packing_size ? MIN (packing_size, align): align;
1934 /* if the field has managed references, we need to force-align it
1937 if (type_has_references (klass, ftype))
1938 align = MAX (align, sizeof (gpointer));
1940 min_align = MAX (align, min_align);
1941 field_offsets [i] = real_size;
1943 field_offsets [i] += align - 1;
1944 field_offsets [i] &= ~(align - 1);
1946 /*TypeBuilders produce all sort of weird things*/
1947 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1948 real_size = field_offsets [i] + size;
1951 instance_size = MAX (real_size, instance_size);
1953 if (instance_size & (min_align - 1)) {
1954 instance_size += min_align - 1;
1955 instance_size &= ~(min_align - 1);
1959 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1963 for (i = 0; i < top; i++) {
1968 field = &klass->fields [i];
1971 * There must be info about all the fields in a type if it
1972 * uses explicit layout.
1974 if (mono_field_is_deleted (field))
1976 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1979 size = mono_type_size (field->type, &align);
1980 align = packing_size ? MIN (packing_size, align): align;
1981 min_align = MAX (align, min_align);
1984 /* Already set by typebuilder_setup_fields () */
1985 field_offsets [i] = field->offset + sizeof (MonoObject);
1987 int idx = klass->field.first + i;
1989 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
1990 field_offsets [i] = offset + sizeof (MonoObject);
1992 ftype = mono_type_get_underlying_type (field->type);
1993 ftype = mono_type_get_basic_type_from_generic (ftype);
1994 if (type_has_references (klass, ftype)) {
1995 if (field_offsets [i] % sizeof (gpointer)) {
1996 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2003 real_size = MAX (real_size, size + field_offsets [i]);
2006 if (klass->has_references) {
2007 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2009 /* Check for overlapping reference and non-reference fields */
2010 for (i = 0; i < top; i++) {
2013 field = &klass->fields [i];
2015 if (mono_field_is_deleted (field))
2017 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2019 ftype = mono_type_get_underlying_type (field->type);
2020 if (MONO_TYPE_IS_REFERENCE (ftype))
2021 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2023 for (i = 0; i < top; i++) {
2024 field = &klass->fields [i];
2026 if (mono_field_is_deleted (field))
2028 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2031 // FIXME: Too much code does this
2033 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2034 mono_class_set_type_load_failure (klass, "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_offsets [i]);
2038 g_free (ref_bitmap);
2041 instance_size = MAX (real_size, instance_size);
2042 if (instance_size & (min_align - 1)) {
2043 instance_size += min_align - 1;
2044 instance_size &= ~(min_align - 1);
2050 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2052 * This leads to all kinds of problems with nested structs, so only
2053 * enable it when a MONO_DEBUG property is set.
2055 * For small structs, set min_align to at least the struct size to improve
2056 * performance, and since the JIT memset/memcpy code assumes this and generates
2057 * unaligned accesses otherwise. See #78990 for a testcase.
2059 if (mono_align_small_structs && top) {
2060 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2061 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2065 /* Publish the data */
2066 mono_loader_lock ();
2067 if (klass->instance_size && !klass->image->dynamic && top) {
2068 /* Might be already set using cached info */
2069 g_assert (klass->instance_size == instance_size);
2071 klass->instance_size = instance_size;
2073 klass->blittable = blittable;
2074 klass->has_references = has_references;
2075 klass->packing_size = packing_size;
2076 klass->min_align = min_align;
2077 for (i = 0; i < top; ++i) {
2078 field = &klass->fields [i];
2079 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2080 klass->fields [i].offset = field_offsets [i];
2083 mono_memory_barrier ();
2084 klass->size_inited = 1;
2085 mono_loader_unlock ();
2088 * Compute static field layout and size
2089 * Static fields can reference the class itself, so this has to be
2090 * done after instance_size etc. are initialized.
2093 for (i = 0; i < top; i++) {
2097 field = &klass->fields [i];
2099 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2101 if (mono_field_is_deleted (field))
2104 if (mono_type_has_exceptions (field->type)) {
2105 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2109 has_static_fields = TRUE;
2111 size = mono_type_size (field->type, &align);
2112 field_offsets [i] = class_size;
2113 /*align is always non-zero here*/
2114 field_offsets [i] += align - 1;
2115 field_offsets [i] &= ~(align - 1);
2116 class_size = field_offsets [i] + size;
2119 if (has_static_fields && class_size == 0)
2120 /* Simplify code which depends on class_size != 0 if the class has static fields */
2123 /* Compute klass->has_static_refs */
2124 has_static_refs = FALSE;
2125 for (i = 0; i < top; i++) {
2128 field = &klass->fields [i];
2130 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2131 ftype = mono_type_get_underlying_type (field->type);
2132 ftype = mono_type_get_basic_type_from_generic (ftype);
2133 if (type_has_references (klass, ftype))
2134 has_static_refs = TRUE;
2138 /*valuetypes can't be neither bigger than 1Mb or empty. */
2139 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2140 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2142 /* Publish the data */
2143 mono_loader_lock ();
2145 klass->sizes.class_size = class_size;
2146 klass->has_static_refs = has_static_refs;
2147 for (i = 0; i < top; ++i) {
2148 field = &klass->fields [i];
2150 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2151 field->offset = field_offsets [i];
2154 mono_memory_barrier ();
2155 klass->fields_inited = 1;
2156 mono_loader_unlock ();
2158 g_free (field_offsets);
2162 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2166 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2167 method->klass = klass;
2168 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2169 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2170 method->signature = sig;
2171 method->name = name;
2174 if (name [0] == '.') {
2175 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2177 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2183 * mono_class_setup_methods:
2186 * Initializes the 'methods' array in CLASS.
2187 * Calling this method should be avoided if possible since it allocates a lot
2188 * of long-living MonoMethod structures.
2189 * Methods belonging to an interface are assigned a sequential slot starting
2192 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2195 mono_class_setup_methods (MonoClass *klass)
2198 MonoMethod **methods;
2203 if (klass->generic_class) {
2205 MonoClass *gklass = klass->generic_class->container_class;
2207 mono_class_init (gklass);
2208 if (!mono_class_has_failure (gklass))
2209 mono_class_setup_methods (gklass);
2210 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2213 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2214 count = gklass->method.count;
2215 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2217 for (i = 0; i < count; i++) {
2218 methods [i] = mono_class_inflate_generic_method_full_checked (
2219 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2220 if (!mono_error_ok (&error)) {
2221 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2222 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2225 mono_error_cleanup (&error);
2229 } else if (klass->rank) {
2231 MonoMethod *amethod;
2232 MonoMethodSignature *sig;
2233 int count_generic = 0, first_generic = 0;
2235 gboolean jagged_ctor = FALSE;
2237 count = 3 + (klass->rank > 1? 2: 1);
2239 mono_class_setup_interfaces (klass, &error);
2240 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2242 if (klass->rank == 1 && klass->element_class->rank) {
2244 klass->method.count ++;
2247 if (klass->interface_count) {
2248 count_generic = generic_array_methods (klass);
2249 first_generic = count;
2250 count += klass->interface_count * count_generic;
2253 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2255 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2256 sig->ret = &mono_defaults.void_class->byval_arg;
2257 sig->pinvoke = TRUE;
2258 sig->hasthis = TRUE;
2259 for (i = 0; i < klass->rank; ++i)
2260 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2262 amethod = create_array_method (klass, ".ctor", sig);
2263 methods [method_num++] = amethod;
2264 if (klass->rank > 1) {
2265 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2266 sig->ret = &mono_defaults.void_class->byval_arg;
2267 sig->pinvoke = TRUE;
2268 sig->hasthis = TRUE;
2269 for (i = 0; i < klass->rank * 2; ++i)
2270 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2272 amethod = create_array_method (klass, ".ctor", sig);
2273 methods [method_num++] = amethod;
2277 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2278 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2279 sig->ret = &mono_defaults.void_class->byval_arg;
2280 sig->pinvoke = TRUE;
2281 sig->hasthis = TRUE;
2282 for (i = 0; i < klass->rank + 1; ++i)
2283 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2284 amethod = create_array_method (klass, ".ctor", sig);
2285 methods [method_num++] = amethod;
2288 /* element Get (idx11, [idx2, ...]) */
2289 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2290 sig->ret = &klass->element_class->byval_arg;
2291 sig->pinvoke = TRUE;
2292 sig->hasthis = TRUE;
2293 for (i = 0; i < klass->rank; ++i)
2294 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2295 amethod = create_array_method (klass, "Get", sig);
2296 methods [method_num++] = amethod;
2297 /* element& Address (idx11, [idx2, ...]) */
2298 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2299 sig->ret = &klass->element_class->this_arg;
2300 sig->pinvoke = TRUE;
2301 sig->hasthis = TRUE;
2302 for (i = 0; i < klass->rank; ++i)
2303 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2304 amethod = create_array_method (klass, "Address", sig);
2305 methods [method_num++] = amethod;
2306 /* void Set (idx11, [idx2, ...], element) */
2307 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2308 sig->ret = &mono_defaults.void_class->byval_arg;
2309 sig->pinvoke = TRUE;
2310 sig->hasthis = TRUE;
2311 for (i = 0; i < klass->rank; ++i)
2312 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2313 sig->params [i] = &klass->element_class->byval_arg;
2314 amethod = create_array_method (klass, "Set", sig);
2315 methods [method_num++] = amethod;
2317 for (i = 0; i < klass->interface_count; i++)
2318 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2322 count = klass->method.count;
2323 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2324 for (i = 0; i < count; ++i) {
2325 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2326 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2328 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2329 mono_error_cleanup (&error);
2334 if (MONO_CLASS_IS_INTERFACE (klass)) {
2336 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2337 for (i = 0; i < count; ++i) {
2338 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2339 methods [i]->slot = slot++;
2343 mono_image_lock (klass->image);
2345 if (!klass->methods) {
2346 klass->method.count = count;
2348 /* Needed because of the double-checking locking pattern */
2349 mono_memory_barrier ();
2351 klass->methods = methods;
2354 mono_image_unlock (klass->image);
2358 * mono_class_get_method_by_index:
2360 * Returns klass->methods [index], initializing klass->methods if neccesary.
2362 * LOCKING: Acquires the loader lock.
2365 mono_class_get_method_by_index (MonoClass *klass, int index)
2368 /* Avoid calling setup_methods () if possible */
2369 if (klass->generic_class && !klass->methods) {
2370 MonoClass *gklass = klass->generic_class->container_class;
2373 m = mono_class_inflate_generic_method_full_checked (
2374 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2375 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2377 * If setup_methods () is called later for this class, no duplicates are created,
2378 * since inflate_generic_method guarantees that only one instance of a method
2379 * is created for each context.
2382 mono_class_setup_methods (klass);
2383 g_assert (m == klass->methods [index]);
2387 mono_class_setup_methods (klass);
2388 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2390 g_assert (index >= 0 && index < klass->method.count);
2391 return klass->methods [index];
2396 * mono_class_get_inflated_method:
2398 * Given an inflated class CLASS and a method METHOD which should be a method of
2399 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2402 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2404 MonoClass *gklass = klass->generic_class->container_class;
2407 g_assert (method->klass == gklass);
2409 mono_class_setup_methods (gklass);
2410 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2412 for (i = 0; i < gklass->method.count; ++i) {
2413 if (gklass->methods [i] == method) {
2414 if (klass->methods) {
2415 return klass->methods [i];
2418 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2419 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2429 * mono_class_get_vtable_entry:
2431 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2432 * LOCKING: Acquires the loader lock.
2435 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2439 if (klass->rank == 1) {
2441 * szarrays do not overwrite any methods of Array, so we can avoid
2442 * initializing their vtables in some cases.
2444 mono_class_setup_vtable (klass->parent);
2445 if (offset < klass->parent->vtable_size)
2446 return klass->parent->vtable [offset];
2449 if (klass->generic_class) {
2451 MonoClass *gklass = klass->generic_class->container_class;
2452 mono_class_setup_vtable (gklass);
2453 m = gklass->vtable [offset];
2455 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2456 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2458 mono_class_setup_vtable (klass);
2459 if (mono_class_has_failure (klass))
2461 m = klass->vtable [offset];
2468 * mono_class_get_vtable_size:
2470 * Return the vtable size for KLASS.
2473 mono_class_get_vtable_size (MonoClass *klass)
2475 mono_class_setup_vtable (klass);
2477 return klass->vtable_size;
2481 * mono_class_setup_properties:
2483 * Initialize klass->ext.property and klass->ext.properties.
2485 * This method can fail the class.
2488 mono_class_setup_properties (MonoClass *klass)
2490 guint startm, endm, i, j;
2491 guint32 cols [MONO_PROPERTY_SIZE];
2492 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2493 MonoProperty *properties;
2497 if (klass->ext && klass->ext->properties)
2500 if (klass->generic_class) {
2501 MonoClass *gklass = klass->generic_class->container_class;
2503 mono_class_init (gklass);
2504 mono_class_setup_properties (gklass);
2505 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2508 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2510 for (i = 0; i < gklass->ext->property.count; i++) {
2512 MonoProperty *prop = &properties [i];
2514 *prop = gklass->ext->properties [i];
2517 prop->get = mono_class_inflate_generic_method_full_checked (
2518 prop->get, klass, mono_class_get_context (klass), &error);
2520 prop->set = mono_class_inflate_generic_method_full_checked (
2521 prop->set, klass, mono_class_get_context (klass), &error);
2523 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2524 prop->parent = klass;
2527 first = gklass->ext->property.first;
2528 count = gklass->ext->property.count;
2530 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2531 count = last - first;
2534 mono_class_setup_methods (klass);
2535 if (mono_class_has_failure (klass))
2539 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2540 for (i = first; i < last; ++i) {
2541 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2542 properties [i - first].parent = klass;
2543 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2544 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2546 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2547 for (j = startm; j < endm; ++j) {
2550 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2552 if (klass->image->uncompressed_metadata) {
2554 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2555 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2556 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2558 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2561 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2562 case METHOD_SEMANTIC_SETTER:
2563 properties [i - first].set = method;
2565 case METHOD_SEMANTIC_GETTER:
2566 properties [i - first].get = method;
2575 mono_class_alloc_ext (klass);
2577 mono_image_lock (klass->image);
2579 if (klass->ext->properties) {
2580 /* We leak 'properties' which was allocated from the image mempool */
2581 mono_image_unlock (klass->image);
2585 klass->ext->property.first = first;
2586 klass->ext->property.count = count;
2588 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2589 mono_memory_barrier ();
2591 /* Leave this assignment as the last op in the function */
2592 klass->ext->properties = properties;
2594 mono_image_unlock (klass->image);
2598 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2600 MonoMethod **om, **retval;
2603 for (om = methods, count = 0; *om; ++om, ++count)
2606 retval = g_new0 (MonoMethod*, count + 1);
2608 for (om = methods, count = 0; *om; ++om, ++count) {
2610 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2611 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2617 /*This method can fail the class.*/
2619 mono_class_setup_events (MonoClass *klass)
2622 guint startm, endm, i, j;
2623 guint32 cols [MONO_EVENT_SIZE];
2624 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2628 if (klass->ext && klass->ext->events)
2631 if (klass->generic_class) {
2632 MonoClass *gklass = klass->generic_class->container_class;
2633 MonoGenericContext *context = NULL;
2635 mono_class_setup_events (gklass);
2636 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2639 first = gklass->ext->event.first;
2640 count = gklass->ext->event.count;
2642 events = mono_class_new0 (klass, MonoEvent, count);
2645 context = mono_class_get_context (klass);
2647 for (i = 0; i < count; i++) {
2649 MonoEvent *event = &events [i];
2650 MonoEvent *gevent = &gklass->ext->events [i];
2652 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2654 event->parent = klass;
2655 event->name = gevent->name;
2656 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2657 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2658 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2659 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2660 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2661 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2663 #ifndef MONO_SMALL_CONFIG
2664 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2666 event->attrs = gevent->attrs;
2669 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2670 count = last - first;
2673 mono_class_setup_methods (klass);
2674 if (mono_class_has_failure (klass)) {
2679 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2680 for (i = first; i < last; ++i) {
2681 MonoEvent *event = &events [i - first];
2683 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2684 event->parent = klass;
2685 event->attrs = cols [MONO_EVENT_FLAGS];
2686 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2688 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2689 for (j = startm; j < endm; ++j) {
2692 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2694 if (klass->image->uncompressed_metadata) {
2696 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2697 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2698 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2700 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2703 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2704 case METHOD_SEMANTIC_ADD_ON:
2705 event->add = method;
2707 case METHOD_SEMANTIC_REMOVE_ON:
2708 event->remove = method;
2710 case METHOD_SEMANTIC_FIRE:
2711 event->raise = method;
2713 case METHOD_SEMANTIC_OTHER: {
2714 #ifndef MONO_SMALL_CONFIG
2717 if (event->other == NULL) {
2718 event->other = g_new0 (MonoMethod*, 2);
2720 while (event->other [n])
2722 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2724 event->other [n] = method;
2725 /* NULL terminated */
2726 event->other [n + 1] = NULL;
2737 mono_class_alloc_ext (klass);
2739 mono_image_lock (klass->image);
2741 if (klass->ext->events) {
2742 mono_image_unlock (klass->image);
2746 klass->ext->event.first = first;
2747 klass->ext->event.count = count;
2749 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2750 mono_memory_barrier ();
2752 /* Leave this assignment as the last op in the function */
2753 klass->ext->events = events;
2755 mono_image_unlock (klass->image);
2759 * Global pool of interface IDs, represented as a bitset.
2760 * LOCKING: Protected by the classes lock.
2762 static MonoBitSet *global_interface_bitset = NULL;
2765 * mono_unload_interface_ids:
2766 * @bitset: bit set of interface IDs
2768 * When an image is unloaded, the interface IDs associated with
2769 * the image are put back in the global pool of IDs so the numbers
2773 mono_unload_interface_ids (MonoBitSet *bitset)
2776 mono_bitset_sub (global_interface_bitset, bitset);
2781 mono_unload_interface_id (MonoClass *klass)
2783 if (global_interface_bitset && klass->interface_id) {
2785 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2791 * mono_get_unique_iid:
2794 * Assign a unique integer ID to the interface represented by @class.
2795 * The ID will positive and as small as possible.
2796 * LOCKING: Acquires the classes lock.
2797 * Returns: The new ID.
2800 mono_get_unique_iid (MonoClass *klass)
2804 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2808 if (!global_interface_bitset) {
2809 global_interface_bitset = mono_bitset_new (128, 0);
2812 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2814 int old_size = mono_bitset_size (global_interface_bitset);
2815 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2816 mono_bitset_free (global_interface_bitset);
2817 global_interface_bitset = new_set;
2820 mono_bitset_set (global_interface_bitset, iid);
2821 /* set the bit also in the per-image set */
2822 if (!klass->generic_class) {
2823 if (klass->image->interface_bitset) {
2824 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2825 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2826 mono_bitset_free (klass->image->interface_bitset);
2827 klass->image->interface_bitset = new_set;
2830 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2832 mono_bitset_set (klass->image->interface_bitset, iid);
2837 #ifndef MONO_SMALL_CONFIG
2838 if (mono_print_vtable) {
2840 char *type_name = mono_type_full_name (&klass->byval_arg);
2841 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2842 generic_id = klass->generic_class->context.class_inst->id;
2843 g_assert (generic_id != 0);
2847 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2852 g_assert (iid <= 65535);
2857 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2862 mono_class_setup_interfaces (klass, error);
2863 return_if_nok (error);
2865 for (i = 0; i < klass->interface_count; i++) {
2866 ic = klass->interfaces [i];
2869 *res = g_ptr_array_new ();
2870 g_ptr_array_add (*res, ic);
2871 mono_class_init (ic);
2872 if (mono_class_has_failure (ic)) {
2873 mono_error_set_type_load_class (error, ic, "Error Loading class");
2877 collect_implemented_interfaces_aux (ic, res, error);
2878 return_if_nok (error);
2883 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2885 GPtrArray *res = NULL;
2887 collect_implemented_interfaces_aux (klass, &res, error);
2888 if (!mono_error_ok (error)) {
2890 g_ptr_array_free (res, TRUE);
2897 compare_interface_ids (const void *p_key, const void *p_element) {
2898 const MonoClass *key = (const MonoClass *)p_key;
2899 const MonoClass *element = *(const MonoClass **)p_element;
2901 return (key->interface_id - element->interface_id);
2904 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2906 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2907 MonoClass **result = (MonoClass **)mono_binary_search (
2909 klass->interfaces_packed,
2910 klass->interface_offsets_count,
2911 sizeof (MonoClass *),
2912 compare_interface_ids);
2914 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2921 * mono_class_interface_offset_with_variance:
2923 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2924 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2926 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2928 * FIXME figure out MS disambiguation rules and fix this function.
2931 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2932 int i = mono_class_interface_offset (klass, itf);
2933 *non_exact_match = FALSE;
2937 if (!mono_class_has_variant_generic_params (itf))
2940 for (i = 0; i < klass->interface_offsets_count; i++) {
2941 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2942 *non_exact_match = TRUE;
2943 return klass->interface_offsets_packed [i];
2951 print_implemented_interfaces (MonoClass *klass) {
2954 GPtrArray *ifaces = NULL;
2956 int ancestor_level = 0;
2958 name = mono_type_get_full_name (klass);
2959 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2962 for (i = 0; i < klass->interface_offsets_count; i++)
2963 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2964 klass->interfaces_packed [i]->interface_id,
2965 klass->interface_offsets_packed [i],
2966 klass->interfaces_packed [i]->method.count,
2967 klass->interfaces_packed [i]->name_space,
2968 klass->interfaces_packed [i]->name );
2969 printf ("Interface flags: ");
2970 for (i = 0; i <= klass->max_interface_id; i++)
2971 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2972 printf ("(%d,T)", i);
2974 printf ("(%d,F)", i);
2976 printf ("Dump interface flags:");
2977 #ifdef COMPRESSED_INTERFACE_BITMAP
2979 const uint8_t* p = klass->interface_bitmap;
2980 i = klass->max_interface_id;
2982 printf (" %d x 00 %02X", p [0], p [1]);
2988 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2989 printf (" %02X", klass->interface_bitmap [i]);
2992 while (klass != NULL) {
2993 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2994 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2995 if (!mono_error_ok (&error)) {
2996 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2997 mono_error_cleanup (&error);
2998 } else if (ifaces) {
2999 for (i = 0; i < ifaces->len; i++) {
3000 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3001 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3002 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3004 mono_class_interface_offset (klass, ic),
3009 g_ptr_array_free (ifaces, TRUE);
3012 klass = klass->parent;
3017 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3020 args [0] = &arg0->byval_arg;
3022 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3026 array_class_get_if_rank (MonoClass *klass, guint rank)
3028 return rank ? mono_array_class_get (klass, rank) : klass;
3032 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3034 valuetype_types [0] = eclass;
3035 if (eclass == mono_defaults.int16_class)
3036 valuetype_types [1] = mono_defaults.uint16_class;
3037 else if (eclass == mono_defaults.uint16_class)
3038 valuetype_types [1] = mono_defaults.int16_class;
3039 else if (eclass == mono_defaults.int32_class)
3040 valuetype_types [1] = mono_defaults.uint32_class;
3041 else if (eclass == mono_defaults.uint32_class)
3042 valuetype_types [1] = mono_defaults.int32_class;
3043 else if (eclass == mono_defaults.int64_class)
3044 valuetype_types [1] = mono_defaults.uint64_class;
3045 else if (eclass == mono_defaults.uint64_class)
3046 valuetype_types [1] = mono_defaults.int64_class;
3047 else if (eclass == mono_defaults.byte_class)
3048 valuetype_types [1] = mono_defaults.sbyte_class;
3049 else if (eclass == mono_defaults.sbyte_class)
3050 valuetype_types [1] = mono_defaults.byte_class;
3051 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3052 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3055 /* this won't be needed once bug #325495 is completely fixed
3056 * though we'll need something similar to know which interfaces to allow
3057 * in arrays when they'll be lazyly created
3059 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3060 * MS returns diferrent types based on which instance is called. For example:
3061 * object obj = new byte[10][];
3062 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3063 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3066 * Fixing this should kill quite some code, save some bits and improve compatibility.
3069 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3071 MonoClass *eclass = klass->element_class;
3072 static MonoClass* generic_icollection_class = NULL;
3073 static MonoClass* generic_ienumerable_class = NULL;
3074 static MonoClass* generic_ienumerator_class = NULL;
3075 static MonoClass* generic_ireadonlylist_class = NULL;
3076 static MonoClass* generic_ireadonlycollection_class = NULL;
3077 MonoClass *valuetype_types[2] = { NULL, NULL };
3078 MonoClass **interfaces = NULL;
3079 int i, nifaces, interface_count, real_count, original_rank;
3081 gboolean internal_enumerator;
3082 gboolean eclass_is_valuetype;
3084 if (!mono_defaults.generic_ilist_class) {
3088 internal_enumerator = FALSE;
3089 eclass_is_valuetype = FALSE;
3090 original_rank = eclass->rank;
3091 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3092 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3094 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3096 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3097 original_rank = eclass->rank;
3099 eclass = eclass->element_class;
3100 internal_enumerator = TRUE;
3101 *is_enumerator = TRUE;
3109 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3110 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3112 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3114 if (!generic_icollection_class) {
3115 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3116 "System.Collections.Generic", "ICollection`1");
3117 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3118 "System.Collections.Generic", "IEnumerable`1");
3119 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3120 "System.Collections.Generic", "IEnumerator`1");
3121 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3122 "System.Collections.Generic", "IReadOnlyList`1");
3123 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3124 "System.Collections.Generic", "IReadOnlyCollection`1");
3127 mono_class_init (eclass);
3130 * Arrays in 2.0 need to implement a number of generic interfaces
3131 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3132 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3133 * We collect the types needed to build the
3134 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3135 * the generic interfaces needed to implement.
3137 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3138 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3140 if (eclass->valuetype) {
3141 nifaces = generic_ireadonlylist_class ? 5 : 3;
3142 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3144 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3145 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3146 if (internal_enumerator) {
3148 if (valuetype_types [1])
3152 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3153 interfaces [0] = valuetype_types [0];
3154 if (valuetype_types [1])
3155 interfaces [nifaces] = valuetype_types [1];
3157 eclass_is_valuetype = TRUE;
3160 int idepth = eclass->idepth;
3161 if (!internal_enumerator)
3163 nifaces = generic_ireadonlylist_class ? 2 : 3;
3165 // FIXME: This doesn't seem to work/required for generic params
3166 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3167 mono_class_setup_interface_offsets (eclass);
3169 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3170 /* we add object for interfaces and the supertypes for the other
3171 * types. The last of the supertypes is the element class itself which we
3172 * already created the explicit interfaces for (so we include it for IEnumerator
3173 * and exclude it for arrays).
3175 if (MONO_CLASS_IS_INTERFACE (eclass))
3178 interface_count += idepth;
3179 if (eclass->rank && eclass->element_class->valuetype) {
3180 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3181 if (valuetype_types [1])
3184 /* IList, ICollection, IEnumerable, IReadOnlyList */
3185 interface_count *= nifaces;
3186 real_count = interface_count;
3187 if (internal_enumerator) {
3188 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3189 if (valuetype_types [1])
3192 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3193 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3194 interfaces [0] = mono_defaults.object_class;
3198 for (i = 0; i < idepth; i++) {
3199 mono_class_init (eclass->supertypes [i]);
3200 interfaces [j] = eclass->supertypes [i];
3204 if (all_interfaces) {
3205 for (i = 0; i < eclass->interface_offsets_count; i++) {
3206 interfaces [j] = eclass->interfaces_packed [i];
3210 for (i = 0; i < eclass->interface_count; i++) {
3211 interfaces [j] = eclass->interfaces [i];
3215 if (valuetype_types [1]) {
3216 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3221 /* instantiate the generic interfaces */
3222 for (i = 0; i < interface_count; i += nifaces) {
3223 MonoClass *iface = interfaces [i];
3225 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3226 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3228 if (eclass->valuetype) {
3229 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3230 if (generic_ireadonlylist_class) {
3231 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3232 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3235 if (!generic_ireadonlylist_class)
3236 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3239 if (internal_enumerator) {
3241 /* instantiate IEnumerator<iface> */
3242 for (i = 0; i < interface_count; i++) {
3243 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3245 j = interface_count;
3246 if (!eclass_is_valuetype) {
3247 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3248 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3251 for (i = 0; i < eclass->idepth; i++) {
3252 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3256 for (i = 0; i < eclass->interface_offsets_count; i++) {
3257 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3261 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3263 if (valuetype_types [1])
3264 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3268 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3269 for (i = 0; i < real_count; ++i) {
3270 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3271 g_print ("%s implements %s\n", type_name, name);
3282 find_array_interface (MonoClass *klass, const char *name)
3285 for (i = 0; i < klass->interface_count; ++i) {
3286 if (strcmp (klass->interfaces [i]->name, name) == 0)
3293 * Return the number of virtual methods.
3294 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3295 * Return -1 on failure.
3296 * FIXME It would be nice if this information could be cached somewhere.
3299 count_virtual_methods (MonoClass *klass)
3303 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3305 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3306 mono_class_setup_methods (klass);
3307 if (mono_class_has_failure (klass))
3310 for (i = 0; i < klass->method.count; ++i) {
3311 flags = klass->methods [i]->flags;
3312 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3316 for (i = 0; i < klass->method.count; ++i) {
3317 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3319 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3327 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3335 m = (l + num_ifaces) / 2;
3336 if (interfaces_full [m] == ic)
3338 if (l == num_ifaces)
3340 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3349 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3351 int i = find_interface (num_ifaces, interfaces_full, ic);
3353 return interface_offsets_full [i];
3358 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3360 int i = find_interface (num_ifaces, interfaces_full, ic);
3364 interface_offsets_full [i] = offset;
3367 for (i = 0; i < num_ifaces; ++i) {
3368 if (interfaces_full [i]) {
3370 if (interfaces_full [i]->interface_id < ic->interface_id)
3373 while (end < num_ifaces && interfaces_full [end]) end++;
3374 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3375 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3377 interfaces_full [i] = ic;
3378 interface_offsets_full [i] = offset;
3384 #ifdef COMPRESSED_INTERFACE_BITMAP
3387 * Compressed interface bitmap design.
3389 * Interface bitmaps take a large amount of memory, because their size is
3390 * linear with the maximum interface id assigned in the process (each interface
3391 * is assigned a unique id as it is loaded). The number of interface classes
3392 * is high because of the many implicit interfaces implemented by arrays (we'll
3393 * need to lazy-load them in the future).
3394 * Most classes implement a very small number of interfaces, so the bitmap is
3395 * sparse. This bitmap needs to be checked by interface casts, so access to the
3396 * needed bit must be fast and doable with few jit instructions.
3398 * The current compression format is as follows:
3399 * *) it is a sequence of one or more two-byte elements
3400 * *) the first byte in the element is the count of empty bitmap bytes
3401 * at the current bitmap position
3402 * *) the second byte in the element is an actual bitmap byte at the current
3405 * As an example, the following compressed bitmap bytes:
3406 * 0x07 0x01 0x00 0x7
3407 * correspond to the following bitmap:
3408 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3410 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3411 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3412 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3416 * mono_compress_bitmap:
3417 * @dest: destination buffer
3418 * @bitmap: bitmap buffer
3419 * @size: size of @bitmap in bytes
3421 * This is a mono internal function.
3422 * The @bitmap data is compressed into a format that is small but
3423 * still searchable in few instructions by the JIT and runtime.
3424 * The compressed data is stored in the buffer pointed to by the
3425 * @dest array. Passing a #NULL value for @dest allows to just compute
3426 * the size of the buffer.
3427 * This compression algorithm assumes the bits set in the bitmap are
3428 * few and far between, like in interface bitmaps.
3429 * Returns: The size of the compressed bitmap in bytes.
3432 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3436 const uint8_t *end = bitmap + size;
3437 while (bitmap < end) {
3438 if (*bitmap || numz == 255) {
3462 * mono_class_interface_match:
3463 * @bitmap: a compressed bitmap buffer
3464 * @id: the index to check in the bitmap
3466 * This is a mono internal function.
3467 * Checks if a bit is set in a compressed interface bitmap. @id must
3468 * be already checked for being smaller than the maximum id encoded in the
3471 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3475 mono_class_interface_match (const uint8_t *bitmap, int id)
3478 id -= bitmap [0] * 8;
3482 return bitmap [1] & (1 << id);
3491 * LOCKING: this is supposed to be called with the loader lock held.
3492 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3495 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3499 int i, j, max_iid, num_ifaces;
3500 MonoClass **interfaces_full = NULL;
3501 int *interface_offsets_full = NULL;
3503 GPtrArray **ifaces_array = NULL;
3504 int interface_offsets_count;
3505 MonoClass **array_interfaces = NULL;
3506 int num_array_interfaces;
3507 int is_enumerator = FALSE;
3509 mono_class_setup_supertypes (klass);
3511 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3512 * implicit interfaces have the property that they are assigned the same slot in the
3513 * vtables for compatible interfaces
3515 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3517 /* compute maximum number of slots and maximum interface id */
3519 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3520 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3521 for (j = 0; j < klass->idepth; j++) {
3522 k = klass->supertypes [j];
3523 num_ifaces += k->interface_count;
3524 for (i = 0; i < k->interface_count; i++) {
3525 ic = k->interfaces [i];
3528 mono_class_init (ic);
3530 if (max_iid < ic->interface_id)
3531 max_iid = ic->interface_id;
3533 ifaces = mono_class_get_implemented_interfaces (k, &error);
3534 if (!mono_error_ok (&error)) {
3535 char *name = mono_type_get_full_name (k);
3536 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3538 mono_error_cleanup (&error);
3543 num_ifaces += ifaces->len;
3544 for (i = 0; i < ifaces->len; ++i) {
3545 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3546 if (max_iid < ic->interface_id)
3547 max_iid = ic->interface_id;
3549 ifaces_array [j] = ifaces;
3553 for (i = 0; i < num_array_interfaces; ++i) {
3554 ic = array_interfaces [i];
3555 mono_class_init (ic);
3556 if (max_iid < ic->interface_id)
3557 max_iid = ic->interface_id;
3560 if (MONO_CLASS_IS_INTERFACE (klass)) {
3562 if (max_iid < klass->interface_id)
3563 max_iid = klass->interface_id;
3565 klass->max_interface_id = max_iid;
3566 /* compute vtable offset for interfaces */
3567 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3568 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3570 for (i = 0; i < num_ifaces; i++) {
3571 interface_offsets_full [i] = -1;
3574 /* skip the current class */
3575 for (j = 0; j < klass->idepth - 1; j++) {
3576 k = klass->supertypes [j];
3577 ifaces = ifaces_array [j];
3580 for (i = 0; i < ifaces->len; ++i) {
3582 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3584 /*Force the sharing of interface offsets between parent and subtypes.*/
3585 io = mono_class_interface_offset (k, ic);
3587 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3592 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3593 ifaces = ifaces_array [klass->idepth - 1];
3595 for (i = 0; i < ifaces->len; ++i) {
3597 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3598 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3600 count = count_virtual_methods (ic);
3602 char *name = mono_type_get_full_name (ic);
3603 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3612 if (MONO_CLASS_IS_INTERFACE (klass))
3613 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3615 if (num_array_interfaces) {
3616 if (is_enumerator) {
3617 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3618 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3619 g_assert (ienumerator_offset >= 0);
3620 for (i = 0; i < num_array_interfaces; ++i) {
3621 ic = array_interfaces [i];
3622 if (strcmp (ic->name, "IEnumerator`1") == 0)
3623 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3625 g_assert_not_reached ();
3626 /*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);*/
3629 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3630 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3631 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3632 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3633 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3634 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3635 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3636 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3637 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3638 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3639 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3640 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3641 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3642 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3643 for (i = 0; i < num_array_interfaces; ++i) {
3645 ic = array_interfaces [i];
3646 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3647 offset = ilist_offset;
3648 else if (strcmp (ic->name, "ICollection`1") == 0)
3649 offset = icollection_offset;
3650 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3651 offset = ienumerable_offset;
3652 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3653 offset = ireadonlylist_offset;
3654 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3655 offset = ireadonlycollection_offset;
3657 g_assert_not_reached ();
3658 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3659 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3664 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3665 if (interface_offsets_full [i] != -1) {
3666 interface_offsets_count ++;
3671 * We might get called multiple times:
3672 * - mono_class_init ()
3673 * - mono_class_setup_vtable ().
3674 * - mono_class_setup_interface_offsets ().
3675 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3676 * means we have to overwrite those when called from other places (#4440).
3678 if (klass->interfaces_packed) {
3680 g_assert (klass->interface_offsets_count == interface_offsets_count);
3684 klass->interface_offsets_count = interface_offsets_count;
3685 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3686 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3687 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3688 #ifdef COMPRESSED_INTERFACE_BITMAP
3689 bitmap = g_malloc0 (bsize);
3691 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3693 for (i = 0; i < interface_offsets_count; i++) {
3694 int id = interfaces_full [i]->interface_id;
3695 bitmap [id >> 3] |= (1 << (id & 7));
3696 klass->interfaces_packed [i] = interfaces_full [i];
3697 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3698 /*if (num_array_interfaces)
3699 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]);*/
3701 #ifdef COMPRESSED_INTERFACE_BITMAP
3702 i = mono_compress_bitmap (NULL, bitmap, bsize);
3703 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3704 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3707 klass->interface_bitmap = bitmap;
3712 g_free (interfaces_full);
3713 g_free (interface_offsets_full);
3714 g_free (array_interfaces);
3715 for (i = 0; i < klass->idepth; i++) {
3716 ifaces = ifaces_array [i];
3718 g_ptr_array_free (ifaces, TRUE);
3720 g_free (ifaces_array);
3722 //printf ("JUST DONE: ");
3723 //print_implemented_interfaces (klass);
3729 * Setup interface offsets for interfaces.
3731 * - klass->max_interface_id
3732 * - klass->interface_offsets_count
3733 * - klass->interfaces_packed
3734 * - klass->interface_offsets_packed
3735 * - klass->interface_bitmap
3737 * This function can fail @class.
3740 mono_class_setup_interface_offsets (MonoClass *klass)
3742 mono_loader_lock ();
3744 setup_interface_offsets (klass, 0, FALSE);
3746 mono_loader_unlock ();
3749 /*Checks if @klass has @parent as one of it's parents type gtd
3753 * Bar<T> : Foo<Bar<Bar<T>>>
3757 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3759 klass = mono_class_get_generic_type_definition (klass);
3760 parent = mono_class_get_generic_type_definition (parent);
3761 mono_class_setup_supertypes (klass);
3762 mono_class_setup_supertypes (parent);
3764 return klass->idepth >= parent->idepth &&
3765 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3769 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3771 MonoGenericInst *ginst;
3773 if (!klass->generic_class) {
3774 mono_class_setup_vtable_full (klass, in_setup);
3775 return !mono_class_has_failure (klass);
3778 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3779 if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
3782 ginst = klass->generic_class->context.class_inst;
3783 for (i = 0; i < ginst->type_argc; ++i) {
3785 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3787 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3788 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3789 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3791 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3792 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3800 * mono_class_setup_vtable:
3802 * Creates the generic vtable of CLASS.
3803 * Initializes the following fields in MonoClass:
3806 * Plus all the fields initialized by setup_interface_offsets ().
3807 * If there is an error during vtable construction, klass->has_failure
3808 * is set and details are stored in a MonoErrorBoxed.
3810 * LOCKING: Acquires the loader lock.
3813 mono_class_setup_vtable (MonoClass *klass)
3815 mono_class_setup_vtable_full (klass, NULL);
3819 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3822 MonoMethod **overrides;
3823 MonoGenericContext *context;
3831 if (MONO_CLASS_IS_INTERFACE (klass)) {
3832 /* This sets method->slot for all methods if this is an interface */
3833 mono_class_setup_methods (klass);
3837 if (mono_class_has_failure (klass))
3840 if (g_list_find (in_setup, klass))
3843 mono_loader_lock ();
3845 if (klass->vtable) {
3846 mono_loader_unlock ();
3850 mono_stats.generic_vtable_count ++;
3851 in_setup = g_list_prepend (in_setup, klass);
3853 if (klass->generic_class) {
3854 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3855 mono_loader_unlock ();
3856 g_list_remove (in_setup, klass);
3860 context = mono_class_get_context (klass);
3861 type_token = klass->generic_class->container_class->type_token;
3863 context = (MonoGenericContext *) klass->generic_container;
3864 type_token = klass->type_token;
3867 if (image_is_dynamic (klass->image)) {
3868 /* Generic instances can have zero method overrides without causing any harm.
3869 * This is true since we don't do layout all over again for them, we simply inflate
3870 * the layout of the parent.
3872 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3873 if (!is_ok (&error)) {
3874 mono_loader_unlock ();
3875 g_list_remove (in_setup, klass);
3876 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3877 mono_error_cleanup (&error);
3881 /* The following call fails if there are missing methods in the type */
3882 /* FIXME it's probably a good idea to avoid this for generic instances. */
3883 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3887 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3889 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3893 mono_loader_unlock ();
3894 g_list_remove (in_setup, klass);
3899 #define DEBUG_INTERFACE_VTABLE_CODE 0
3900 #define TRACE_INTERFACE_VTABLE_CODE 0
3901 #define VERIFY_INTERFACE_VTABLE_CODE 0
3902 #define VTABLE_SELECTOR (1)
3904 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3905 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3906 if (!(VTABLE_SELECTOR)) break; \
3910 #define DEBUG_INTERFACE_VTABLE(stmt)
3913 #if TRACE_INTERFACE_VTABLE_CODE
3914 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3915 if (!(VTABLE_SELECTOR)) break; \
3919 #define TRACE_INTERFACE_VTABLE(stmt)
3922 #if VERIFY_INTERFACE_VTABLE_CODE
3923 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3924 if (!(VTABLE_SELECTOR)) break; \
3928 #define VERIFY_INTERFACE_VTABLE(stmt)
3932 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3934 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3938 GString *res = g_string_new ("");
3940 g_string_append_c (res, '(');
3941 for (i = 0; i < sig->param_count; ++i) {
3943 g_string_append_c (res, ',');
3944 mono_type_get_desc (res, sig->params [i], include_namespace);
3946 g_string_append (res, ")=>");
3947 if (sig->ret != NULL) {
3948 mono_type_get_desc (res, sig->ret, include_namespace);
3950 g_string_append (res, "NULL");
3953 g_string_free (res, FALSE);
3957 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3958 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3959 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3960 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3968 is_wcf_hack_disabled (void)
3970 static gboolean disabled;
3971 static gboolean inited = FALSE;
3973 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3980 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3982 MonoMethodSignature *cmsig, *imsig;
3983 if (strcmp (im->name, cm->name) == 0) {
3984 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3985 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3988 if (! slot_is_empty) {
3989 if (require_newslot) {
3990 if (! interface_is_explicitly_implemented_by_class) {
3991 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3994 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3995 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3999 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4002 cmsig = mono_method_signature (cm);
4003 imsig = mono_method_signature (im);
4004 if (!cmsig || !imsig) {
4005 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4009 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4010 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4011 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4012 TRACE_INTERFACE_VTABLE (printf ("]"));
4015 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4016 if (mono_security_core_clr_enabled ())
4017 mono_security_core_clr_check_override (klass, cm, im);
4019 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4020 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4021 char *body_name = mono_method_full_name (cm, TRUE);
4022 char *decl_name = mono_method_full_name (im, TRUE);
4023 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4031 MonoClass *ic = im->klass;
4032 const char *ic_name_space = ic->name_space;
4033 const char *ic_name = ic->name;
4036 if (! require_newslot) {
4037 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4040 if (cm->klass->rank == 0) {
4041 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4044 cmsig = mono_method_signature (cm);
4045 imsig = mono_method_signature (im);
4046 if (!cmsig || !imsig) {
4047 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4051 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4052 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4053 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4054 TRACE_INTERFACE_VTABLE (printf ("]"));
4057 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4058 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4061 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4062 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4065 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))) {
4066 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4070 subname = strstr (cm->name, ic_name_space);
4071 if (subname != cm->name) {
4072 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4075 subname += strlen (ic_name_space);
4076 if (subname [0] != '.') {
4077 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4081 if (strstr (subname, ic_name) != subname) {
4082 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4085 subname += strlen (ic_name);
4086 if (subname [0] != '.') {
4087 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4091 if (strcmp (subname, im->name) != 0) {
4092 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4096 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4097 if (mono_security_core_clr_enabled ())
4098 mono_security_core_clr_check_override (klass, cm, im);
4100 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4101 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4102 char *body_name = mono_method_full_name (cm, TRUE);
4103 char *decl_name = mono_method_full_name (im, TRUE);
4104 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4114 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4116 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4117 MonoMethod *method = key;
4118 MonoMethod *override = value;
4119 MonoClass *method_class = mono_method_get_class (method);
4120 MonoClass *override_class = mono_method_get_class (override);
4122 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4123 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4124 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4127 print_overrides (GHashTable *override_map, const char *message) {
4129 printf ("Override map \"%s\" START:\n", message);
4130 g_hash_table_foreach (override_map, foreach_override, NULL);
4131 printf ("Override map \"%s\" END.\n", message);
4133 printf ("Override map \"%s\" EMPTY.\n", message);
4137 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4138 char *full_name = mono_type_full_name (&klass->byval_arg);
4142 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4144 if (print_interfaces) {
4145 print_implemented_interfaces (klass);
4146 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4149 if (klass->parent) {
4150 parent_size = klass->parent->vtable_size;
4154 for (i = 0; i < size; ++i) {
4155 MonoMethod *cm = vtable [i];
4156 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4157 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4159 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4167 #if VERIFY_INTERFACE_VTABLE_CODE
4169 mono_method_try_get_vtable_index (MonoMethod *method)
4171 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4172 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4173 if (imethod->declaring->is_generic)
4174 return imethod->declaring->slot;
4176 return method->slot;
4180 mono_class_verify_vtable (MonoClass *klass)
4183 char *full_name = mono_type_full_name (&klass->byval_arg);
4185 printf ("*** Verifying VTable of class '%s' \n", full_name);
4189 if (!klass->methods)
4192 for (i = 0; i < klass->method.count; ++i) {
4193 MonoMethod *cm = klass->methods [i];
4196 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4200 full_name = mono_method_full_name (cm, TRUE);
4202 slot = mono_method_try_get_vtable_index (cm);
4204 if (slot >= klass->vtable_size) {
4205 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4209 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4210 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4211 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4212 g_free (other_name);
4215 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4222 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4224 char *method_signature;
4227 for (index = 0; index < onum; ++index) {
4228 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4229 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4231 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4232 type_name = mono_type_full_name (&klass->byval_arg);
4233 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4234 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4235 g_free (method_signature);
4237 mono_class_setup_methods (klass);
4238 if (mono_class_has_failure (klass)) {
4239 char *name = mono_type_get_full_name (klass);
4240 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4244 for (index = 0; index < klass->method.count; ++index) {
4245 MonoMethod *cm = klass->methods [index];
4246 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4248 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4249 g_free (method_signature);
4254 mono_method_get_method_definition (MonoMethod *method)
4256 while (method->is_inflated)
4257 method = ((MonoMethodInflated*)method)->declaring;
4262 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4266 for (i = 0; i < onum; ++i) {
4267 MonoMethod *decl = overrides [i * 2];
4268 MonoMethod *body = overrides [i * 2 + 1];
4270 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4271 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4275 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4276 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4277 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4279 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4283 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4284 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4285 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4287 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4291 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4292 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4296 body = mono_method_get_method_definition (body);
4297 decl = mono_method_get_method_definition (decl);
4299 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4300 char *body_name = mono_method_full_name (body, TRUE);
4301 char *decl_name = mono_method_full_name (decl, TRUE);
4302 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4312 mono_class_need_stelemref_method (MonoClass *klass)
4314 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4318 * LOCKING: this is supposed to be called with the loader lock held.
4321 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4325 MonoMethod **vtable;
4326 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4327 GPtrArray *ifaces = NULL;
4328 GHashTable *override_map = NULL;
4330 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4331 int first_non_interface_slot;
4333 GSList *virt_methods = NULL, *l;
4334 int stelemref_slot = 0;
4339 if (overrides && !verify_class_overrides (klass, overrides, onum))
4342 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4343 if (!mono_error_ok (&error)) {
4344 char *name = mono_type_get_full_name (klass);
4345 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4347 mono_error_cleanup (&error);
4349 } else if (ifaces) {
4350 for (i = 0; i < ifaces->len; i++) {
4351 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4352 max_vtsize += ic->method.count;
4354 g_ptr_array_free (ifaces, TRUE);
4358 if (klass->parent) {
4359 mono_class_init (klass->parent);
4360 mono_class_setup_vtable_full (klass->parent, in_setup);
4362 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4365 max_vtsize += klass->parent->vtable_size;
4366 cur_slot = klass->parent->vtable_size;
4369 max_vtsize += klass->method.count;
4371 /*Array have a slot for stelemref*/
4372 if (mono_class_need_stelemref_method (klass)) {
4373 stelemref_slot = cur_slot;
4378 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4379 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4381 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4383 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4384 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4387 max_iid = klass->max_interface_id;
4388 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4390 /* Optimized version for generic instances */
4391 if (klass->generic_class) {
4393 MonoClass *gklass = klass->generic_class->container_class;
4396 mono_class_setup_vtable_full (gklass, in_setup);
4397 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4400 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4401 klass->vtable_size = gklass->vtable_size;
4402 for (i = 0; i < gklass->vtable_size; ++i)
4403 if (gklass->vtable [i]) {
4404 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4405 if (!mono_error_ok (&error)) {
4406 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4407 mono_error_cleanup (&error);
4411 tmp [i]->slot = gklass->vtable [i]->slot;
4413 mono_memory_barrier ();
4414 klass->vtable = tmp;
4416 /* Have to set method->slot for abstract virtual methods */
4417 if (klass->methods && gklass->methods) {
4418 for (i = 0; i < klass->method.count; ++i)
4419 if (klass->methods [i]->slot == -1)
4420 klass->methods [i]->slot = gklass->methods [i]->slot;
4426 if (klass->parent && klass->parent->vtable_size) {
4427 MonoClass *parent = klass->parent;
4430 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4432 // Also inherit parent interface vtables, just as a starting point.
4433 // This is needed otherwise bug-77127.exe fails when the property methods
4434 // have different names in the iterface and the class, because for child
4435 // classes the ".override" information is not used anymore.
4436 for (i = 0; i < parent->interface_offsets_count; i++) {
4437 MonoClass *parent_interface = parent->interfaces_packed [i];
4438 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4439 /*FIXME this is now dead code as this condition will never hold true.
4440 Since interface offsets are inherited then the offset of an interface implemented
4441 by a parent will never be the out of it's vtable boundary.
4443 if (interface_offset >= parent->vtable_size) {
4444 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4447 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4448 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4449 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4450 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4451 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4452 parent_interface_offset + j, parent_interface_offset, j,
4453 interface_offset + j, interface_offset, j));
4460 /*Array have a slot for stelemref*/
4461 if (mono_class_need_stelemref_method (klass)) {
4462 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4464 method->slot = stelemref_slot;
4466 g_assert (method->slot == stelemref_slot);
4468 vtable [stelemref_slot] = method;
4471 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4472 /* override interface methods */
4473 for (i = 0; i < onum; i++) {
4474 MonoMethod *decl = overrides [i*2];
4475 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4477 dslot = mono_method_get_vtable_slot (decl);
4479 mono_class_set_type_load_failure (klass, "");
4483 dslot += mono_class_interface_offset (klass, decl->klass);
4484 vtable [dslot] = overrides [i*2 + 1];
4485 vtable [dslot]->slot = dslot;
4487 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4489 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4491 if (mono_security_core_clr_enabled ())
4492 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4495 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4496 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4499 * Create a list of virtual methods to avoid calling
4500 * mono_class_get_virtual_methods () which is slow because of the metadata
4504 gpointer iter = NULL;
4507 virt_methods = NULL;
4508 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4509 virt_methods = g_slist_prepend (virt_methods, cm);
4511 if (mono_class_has_failure (klass))
4515 // Loop on all implemented interfaces...
4516 for (i = 0; i < klass->interface_offsets_count; i++) {
4517 MonoClass *parent = klass->parent;
4519 gboolean interface_is_explicitly_implemented_by_class;
4522 ic = klass->interfaces_packed [i];
4523 ic_offset = mono_class_interface_offset (klass, ic);
4525 mono_class_setup_methods (ic);
4526 if (mono_class_has_failure (ic))
4529 // Check if this interface is explicitly implemented (instead of just inherited)
4530 if (parent != NULL) {
4531 int implemented_interfaces_index;
4532 interface_is_explicitly_implemented_by_class = FALSE;
4533 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4534 if (ic == klass->interfaces [implemented_interfaces_index]) {
4535 interface_is_explicitly_implemented_by_class = TRUE;
4540 interface_is_explicitly_implemented_by_class = TRUE;
4543 // Loop on all interface methods...
4544 for (im_index = 0; im_index < ic->method.count; im_index++) {
4545 MonoMethod *im = ic->methods [im_index];
4546 int im_slot = ic_offset + im->slot;
4547 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4549 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4552 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4554 // If there is an explicit implementation, just use it right away,
4555 // otherwise look for a matching method
4556 if (override_im == NULL) {
4560 // First look for a suitable method among the class methods
4561 for (l = virt_methods; l; l = l->next) {
4562 cm = (MonoMethod *)l->data;
4563 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)));
4564 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4565 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4566 vtable [im_slot] = cm;
4567 /* Why do we need this? */
4572 TRACE_INTERFACE_VTABLE (printf ("\n"));
4573 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4577 // If the slot is still empty, look in all the inherited virtual methods...
4578 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4579 MonoClass *parent = klass->parent;
4580 // Reverse order, so that last added methods are preferred
4581 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4582 MonoMethod *cm = parent->vtable [cm_index];
4584 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));
4585 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4586 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4587 vtable [im_slot] = cm;
4588 /* Why do we need this? */
4594 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4596 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4600 g_assert (vtable [im_slot] == override_im);
4605 // If the class is not abstract, check that all its interface slots are full.
4606 // The check is done here and not directly at the end of the loop above because
4607 // it can happen (for injected generic array interfaces) that the same slot is
4608 // processed multiple times (those interfaces have overlapping slots), and it
4609 // will not always be the first pass the one that fills the slot.
4610 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4611 for (i = 0; i < klass->interface_offsets_count; i++) {
4615 ic = klass->interfaces_packed [i];
4616 ic_offset = mono_class_interface_offset (klass, ic);
4618 for (im_index = 0; im_index < ic->method.count; im_index++) {
4619 MonoMethod *im = ic->methods [im_index];
4620 int im_slot = ic_offset + im->slot;
4622 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4625 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4626 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4627 if (vtable [im_slot] == NULL) {
4628 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4635 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4636 for (l = virt_methods; l; l = l->next) {
4637 cm = (MonoMethod *)l->data;
4639 * If the method is REUSE_SLOT, we must check in the
4640 * base class for a method to override.
4642 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4644 for (k = klass->parent; k ; k = k->parent) {
4649 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4650 MonoMethodSignature *cmsig, *m1sig;
4652 cmsig = mono_method_signature (cm);
4653 m1sig = mono_method_signature (m1);
4655 if (!cmsig || !m1sig) {
4656 /* FIXME proper error message */
4657 mono_class_set_type_load_failure (klass, "");
4661 if (!strcmp(cm->name, m1->name) &&
4662 mono_metadata_signature_equal (cmsig, m1sig)) {
4664 if (mono_security_core_clr_enabled ())
4665 mono_security_core_clr_check_override (klass, cm, m1);
4667 slot = mono_method_get_vtable_slot (m1);
4671 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4672 char *body_name = mono_method_full_name (cm, TRUE);
4673 char *decl_name = mono_method_full_name (m1, TRUE);
4674 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4680 g_assert (cm->slot < max_vtsize);
4682 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4683 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4684 mono_method_full_name (m1, 1), m1,
4685 mono_method_full_name (cm, 1), cm));
4686 g_hash_table_insert (override_map, m1, cm);
4690 if (mono_class_has_failure (k))
4700 /*Non final newslot methods must be given a non-interface vtable slot*/
4701 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4705 cm->slot = cur_slot++;
4707 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4708 vtable [cm->slot] = cm;
4711 /* override non interface methods */
4712 for (i = 0; i < onum; i++) {
4713 MonoMethod *decl = overrides [i*2];
4714 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4715 g_assert (decl->slot != -1);
4716 vtable [decl->slot] = overrides [i*2 + 1];
4717 overrides [i * 2 + 1]->slot = decl->slot;
4719 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4720 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4721 mono_method_full_name (decl, 1), decl,
4722 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4723 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4725 if (mono_security_core_clr_enabled ())
4726 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4731 * If a method occupies more than one place in the vtable, and it is
4732 * overriden, then change the other occurances too.
4737 for (i = 0; i < max_vtsize; ++i)
4739 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4741 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4746 g_hash_table_destroy (override_map);
4747 override_map = NULL;
4750 g_slist_free (virt_methods);
4751 virt_methods = NULL;
4753 /* Ensure that all vtable slots are filled with concrete instance methods */
4754 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4755 for (i = 0; i < cur_slot; ++i) {
4756 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4757 char *type_name = mono_type_get_full_name (klass);
4758 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4759 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4761 g_free (method_name);
4767 if (klass->generic_class) {
4768 MonoClass *gklass = klass->generic_class->container_class;
4770 mono_class_init (gklass);
4772 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4774 /* Check that the vtable_size value computed in mono_class_init () is correct */
4775 if (klass->vtable_size)
4776 g_assert (cur_slot == klass->vtable_size);
4777 klass->vtable_size = cur_slot;
4780 /* Try to share the vtable with our parent. */
4781 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4782 mono_memory_barrier ();
4783 klass->vtable = klass->parent->vtable;
4785 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4786 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4787 mono_memory_barrier ();
4788 klass->vtable = tmp;
4791 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4792 if (mono_print_vtable) {
4795 print_implemented_interfaces (klass);
4797 for (i = 0; i <= max_iid; i++)
4798 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4801 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4802 klass->vtable_size, icount);
4804 for (i = 0; i < cur_slot; ++i) {
4809 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4810 mono_method_full_name (cm, TRUE));
4816 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4817 klass->name, max_iid);
4819 for (i = 0; i < klass->interface_count; i++) {
4820 ic = klass->interfaces [i];
4821 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4822 mono_class_interface_offset (klass, ic),
4823 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4826 for (k = klass->parent; k ; k = k->parent) {
4827 for (i = 0; i < k->interface_count; i++) {
4828 ic = k->interfaces [i];
4829 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4830 mono_class_interface_offset (klass, ic),
4831 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4837 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4842 char *name = mono_type_get_full_name (klass);
4843 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4846 g_hash_table_destroy (override_map);
4848 g_slist_free (virt_methods);
4853 * mono_method_get_vtable_slot:
4855 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4856 * LOCKING: Acquires the loader lock.
4858 * FIXME Use proper MonoError machinery here.
4861 mono_method_get_vtable_slot (MonoMethod *method)
4863 if (method->slot == -1) {
4864 mono_class_setup_vtable (method->klass);
4865 if (mono_class_has_failure (method->klass))
4867 if (method->slot == -1) {
4871 if (!method->klass->generic_class) {
4872 g_assert (method->is_inflated);
4873 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4876 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4877 g_assert (method->klass->generic_class);
4878 gklass = method->klass->generic_class->container_class;
4879 mono_class_setup_methods (method->klass);
4880 g_assert (method->klass->methods);
4881 for (i = 0; i < method->klass->method.count; ++i) {
4882 if (method->klass->methods [i] == method)
4885 g_assert (i < method->klass->method.count);
4886 g_assert (gklass->methods);
4887 method->slot = gklass->methods [i]->slot;
4889 g_assert (method->slot != -1);
4891 return method->slot;
4895 * mono_method_get_vtable_index:
4898 * Returns the index into the runtime vtable to access the method or,
4899 * in the case of a virtual generic method, the virtual generic method
4900 * thunk. Returns -1 on failure.
4902 * FIXME Use proper MonoError machinery here.
4905 mono_method_get_vtable_index (MonoMethod *method)
4907 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4908 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4909 if (imethod->declaring->is_generic)
4910 return mono_method_get_vtable_slot (imethod->declaring);
4912 return mono_method_get_vtable_slot (method);
4915 static MonoMethod *default_ghc = NULL;
4916 static MonoMethod *default_finalize = NULL;
4917 static int finalize_slot = -1;
4918 static int ghc_slot = -1;
4921 initialize_object_slots (MonoClass *klass)
4926 if (klass == mono_defaults.object_class) {
4927 mono_class_setup_vtable (klass);
4928 for (i = 0; i < klass->vtable_size; ++i) {
4929 MonoMethod *cm = klass->vtable [i];
4931 if (!strcmp (cm->name, "GetHashCode"))
4933 else if (!strcmp (cm->name, "Finalize"))
4937 g_assert (ghc_slot > 0);
4938 default_ghc = klass->vtable [ghc_slot];
4940 g_assert (finalize_slot > 0);
4941 default_finalize = klass->vtable [finalize_slot];
4946 MonoMethod *array_method;
4948 } GenericArrayMethodInfo;
4950 static int generic_array_method_num = 0;
4951 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4954 generic_array_methods (MonoClass *klass)
4956 int i, count_generic = 0;
4957 GList *list = NULL, *tmp;
4958 if (generic_array_method_num)
4959 return generic_array_method_num;
4960 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4961 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4962 for (i = 0; i < klass->parent->method.count; i++) {
4963 MonoMethod *m = klass->parent->methods [i];
4964 if (!strncmp (m->name, "InternalArray__", 15)) {
4966 list = g_list_prepend (list, m);
4969 list = g_list_reverse (list);
4970 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4972 for (tmp = list; tmp; tmp = tmp->next) {
4973 const char *mname, *iname;
4975 MonoMethod *m = (MonoMethod *)tmp->data;
4976 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4977 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4979 generic_array_method_info [i].array_method = m;
4980 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4981 iname = "System.Collections.Generic.ICollection`1.";
4982 mname = m->name + 27;
4983 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4984 iname = "System.Collections.Generic.IEnumerable`1.";
4985 mname = m->name + 27;
4986 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4987 iname = "System.Collections.Generic.IReadOnlyList`1.";
4988 mname = m->name + strlen (ireadonlylist_prefix);
4989 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4990 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4991 mname = m->name + strlen (ireadonlycollection_prefix);
4992 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4993 iname = "System.Collections.Generic.IList`1.";
4994 mname = m->name + 15;
4996 g_assert_not_reached ();
4999 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5000 strcpy (name, iname);
5001 strcpy (name + strlen (iname), mname);
5002 generic_array_method_info [i].name = name;
5005 /*g_print ("array generic methods: %d\n", count_generic);*/
5007 generic_array_method_num = count_generic;
5009 return generic_array_method_num;
5013 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5015 MonoGenericContext tmp_context;
5018 tmp_context.class_inst = NULL;
5019 tmp_context.method_inst = iface->generic_class->context.class_inst;
5020 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5022 for (i = 0; i < generic_array_method_num; i++) {
5024 MonoMethod *m = generic_array_method_info [i].array_method;
5025 MonoMethod *inflated;
5027 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5028 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5029 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5034 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5036 int null_length = strlen ("(null)");
5037 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5038 char *s = (char *)mono_image_alloc (image, len);
5041 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5042 g_assert (result == len - 1);
5049 * @class: the class to initialize
5051 * Compute the instance_size, class_size and other infos that cannot be
5052 * computed at mono_class_get() time. Also compute vtable_size if possible.
5053 * Returns TRUE on success or FALSE if there was a problem in loading
5054 * the type (incorrect assemblies, missing assemblies, methods, etc).
5056 * LOCKING: Acquires the loader lock.
5059 mono_class_init (MonoClass *klass)
5062 MonoCachedClassInfo cached_info;
5063 gboolean has_cached_info;
5067 /* Double-checking locking pattern */
5068 if (klass->inited || mono_class_has_failure (klass))
5069 return !mono_class_has_failure (klass);
5071 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5073 /* We do everything inside the lock to prevent races */
5074 mono_loader_lock ();
5076 if (klass->inited || mono_class_has_failure (klass)) {
5077 mono_loader_unlock ();
5078 /* Somebody might have gotten in before us */
5079 return !mono_class_has_failure (klass);
5082 if (klass->init_pending) {
5083 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5087 klass->init_pending = 1;
5089 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5090 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5095 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5096 MonoClass *element_class = klass->element_class;
5097 if (!element_class->inited)
5098 mono_class_init (element_class);
5099 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5103 mono_stats.initialized_class_count++;
5105 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5106 MonoClass *gklass = klass->generic_class->container_class;
5108 mono_stats.generic_class_count++;
5110 klass->method = gklass->method;
5111 klass->field = gklass->field;
5113 mono_class_init (gklass);
5114 // FIXME: Why is this needed ?
5115 if (!mono_class_has_failure (gklass))
5116 mono_class_setup_methods (gklass);
5117 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5120 if (MONO_CLASS_IS_INTERFACE (klass))
5121 klass->interface_id = mono_get_unique_iid (klass);
5124 if (klass->parent && !klass->parent->inited)
5125 mono_class_init (klass->parent);
5127 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5129 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5130 klass->nested_classes_inited = TRUE;
5133 * Computes the size used by the fields, and their locations
5135 if (has_cached_info) {
5136 klass->instance_size = cached_info.instance_size;
5137 klass->sizes.class_size = cached_info.class_size;
5138 klass->packing_size = cached_info.packing_size;
5139 klass->min_align = cached_info.min_align;
5140 klass->blittable = cached_info.blittable;
5141 klass->has_references = cached_info.has_references;
5142 klass->has_static_refs = cached_info.has_static_refs;
5143 klass->no_special_static_fields = cached_info.no_special_static_fields;
5146 if (!klass->size_inited){
5147 mono_class_setup_fields (klass);
5148 if (mono_class_has_failure (klass))
5152 /* Initialize arrays */
5154 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5156 if (klass->interface_count) {
5157 int count_generic = generic_array_methods (klass);
5158 klass->method.count += klass->interface_count * count_generic;
5162 mono_class_setup_supertypes (klass);
5165 initialize_object_slots (klass);
5168 * Initialize the rest of the data without creating a generic vtable if possible.
5169 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5170 * also avoid computing a generic vtable.
5172 if (has_cached_info) {
5174 klass->vtable_size = cached_info.vtable_size;
5175 klass->has_finalize = cached_info.has_finalize;
5176 klass->has_finalize_inited = TRUE;
5177 klass->ghcimpl = cached_info.ghcimpl;
5178 klass->has_cctor = cached_info.has_cctor;
5179 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5180 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5181 * The first slot if for array with.
5183 static int szarray_vtable_size[2] = { 0 };
5185 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5188 if (!szarray_vtable_size [slot]) {
5189 mono_class_setup_vtable (klass);
5190 szarray_vtable_size [slot] = klass->vtable_size;
5192 klass->vtable_size = szarray_vtable_size[slot];
5194 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5195 MonoClass *gklass = klass->generic_class->container_class;
5197 /* Generic instance case */
5198 klass->ghcimpl = gklass->ghcimpl;
5199 klass->has_cctor = gklass->has_cctor;
5201 mono_class_setup_vtable (gklass);
5202 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5205 klass->vtable_size = gklass->vtable_size;
5209 /* ghcimpl is not currently used
5211 if (klass->parent) {
5212 MonoMethod *cmethod = klass->vtable [ghc_slot];
5213 if (cmethod->is_inflated)
5214 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5215 if (cmethod == default_ghc) {
5221 /* C# doesn't allow interfaces to have cctors */
5222 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5223 MonoMethod *cmethod = NULL;
5225 if (klass->type_token && !image_is_dynamic(klass->image)) {
5226 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5227 /* The find_method function ignores the 'flags' argument */
5228 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5229 klass->has_cctor = 1;
5231 mono_class_setup_methods (klass);
5232 if (mono_class_has_failure (klass))
5235 for (i = 0; i < klass->method.count; ++i) {
5236 MonoMethod *method = klass->methods [i];
5237 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5238 (strcmp (".cctor", method->name) == 0)) {
5239 klass->has_cctor = 1;
5247 if (klass->parent) {
5248 MonoError parent_error;
5249 mono_error_init (&parent_error);
5250 int first_iface_slot;
5251 /* This will compute klass->parent->vtable_size for some classes */
5252 mono_class_init (klass->parent);
5253 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to initialize")) {
5256 if (!klass->parent->vtable_size) {
5257 /* FIXME: Get rid of this somehow */
5258 mono_class_setup_vtable (klass->parent);
5259 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) {
5263 first_iface_slot = klass->parent->vtable_size;
5264 if (mono_class_need_stelemref_method (klass))
5266 setup_interface_offsets (klass, first_iface_slot, TRUE);
5268 setup_interface_offsets (klass, 0, TRUE);
5271 if (mono_security_core_clr_enabled ())
5272 mono_security_core_clr_check_inheritance (klass);
5274 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5275 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5280 /* Because of the double-checking locking pattern */
5281 mono_memory_barrier ();
5283 klass->init_pending = 0;
5285 mono_loader_unlock ();
5287 return !mono_class_has_failure (klass);
5291 * mono_class_has_finalizer:
5293 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5297 mono_class_has_finalizer (MonoClass *klass)
5299 gboolean has_finalize = FALSE;
5301 if (klass->has_finalize_inited)
5302 return klass->has_finalize;
5304 /* Interfaces and valuetypes are not supposed to have finalizers */
5305 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5306 MonoMethod *cmethod = NULL;
5308 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5309 } else if (klass->generic_class) {
5310 MonoClass *gklass = klass->generic_class->container_class;
5312 has_finalize = mono_class_has_finalizer (gklass);
5313 } else if (klass->parent && klass->parent->has_finalize) {
5314 has_finalize = TRUE;
5316 if (klass->parent) {
5318 * Can't search in metadata for a method named Finalize, because that
5319 * ignores overrides.
5321 mono_class_setup_vtable (klass);
5322 if (mono_class_has_failure (klass))
5325 cmethod = klass->vtable [finalize_slot];
5329 g_assert (klass->vtable_size > finalize_slot);
5331 if (klass->parent) {
5332 if (cmethod->is_inflated)
5333 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5334 if (cmethod != default_finalize)
5335 has_finalize = TRUE;
5341 mono_image_lock (klass->image);
5343 if (!klass->has_finalize_inited) {
5344 klass->has_finalize = has_finalize ? 1 : 0;
5346 mono_memory_barrier ();
5347 klass->has_finalize_inited = TRUE;
5350 mono_image_unlock (klass->image);
5352 return klass->has_finalize;
5356 mono_is_corlib_image (MonoImage *image)
5358 return image == mono_defaults.corlib;
5362 * LOCKING: this assumes the loader lock is held
5365 mono_class_setup_mono_type (MonoClass *klass)
5367 const char *name = klass->name;
5368 const char *nspace = klass->name_space;
5369 gboolean is_corlib = mono_is_corlib_image (klass->image);
5371 klass->this_arg.byref = 1;
5372 klass->this_arg.data.klass = klass;
5373 klass->this_arg.type = MONO_TYPE_CLASS;
5374 klass->byval_arg.data.klass = klass;
5375 klass->byval_arg.type = MONO_TYPE_CLASS;
5377 if (is_corlib && !strcmp (nspace, "System")) {
5378 if (!strcmp (name, "ValueType")) {
5380 * do not set the valuetype bit for System.ValueType.
5381 * klass->valuetype = 1;
5383 klass->blittable = TRUE;
5384 } else if (!strcmp (name, "Enum")) {
5386 * do not set the valuetype bit for System.Enum.
5387 * klass->valuetype = 1;
5389 klass->valuetype = 0;
5390 klass->enumtype = 0;
5391 } else if (!strcmp (name, "Object")) {
5392 klass->byval_arg.type = MONO_TYPE_OBJECT;
5393 klass->this_arg.type = MONO_TYPE_OBJECT;
5394 } else if (!strcmp (name, "String")) {
5395 klass->byval_arg.type = MONO_TYPE_STRING;
5396 klass->this_arg.type = MONO_TYPE_STRING;
5397 } else if (!strcmp (name, "TypedReference")) {
5398 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5399 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5403 if (klass->valuetype) {
5404 int t = MONO_TYPE_VALUETYPE;
5406 if (is_corlib && !strcmp (nspace, "System")) {
5409 if (!strcmp (name, "Boolean")) {
5410 t = MONO_TYPE_BOOLEAN;
5411 } else if (!strcmp(name, "Byte")) {
5413 klass->blittable = TRUE;
5417 if (!strcmp (name, "Char")) {
5422 if (!strcmp (name, "Double")) {
5424 klass->blittable = TRUE;
5428 if (!strcmp (name, "Int32")) {
5430 klass->blittable = TRUE;
5431 } else if (!strcmp(name, "Int16")) {
5433 klass->blittable = TRUE;
5434 } else if (!strcmp(name, "Int64")) {
5436 klass->blittable = TRUE;
5437 } else if (!strcmp(name, "IntPtr")) {
5439 klass->blittable = TRUE;
5443 if (!strcmp (name, "Single")) {
5445 klass->blittable = TRUE;
5446 } else if (!strcmp(name, "SByte")) {
5448 klass->blittable = TRUE;
5452 if (!strcmp (name, "UInt32")) {
5454 klass->blittable = TRUE;
5455 } else if (!strcmp(name, "UInt16")) {
5457 klass->blittable = TRUE;
5458 } else if (!strcmp(name, "UInt64")) {
5460 klass->blittable = TRUE;
5461 } else if (!strcmp(name, "UIntPtr")) {
5463 klass->blittable = TRUE;
5467 if (!strcmp (name, "TypedReference")) {
5468 t = MONO_TYPE_TYPEDBYREF;
5469 klass->blittable = TRUE;
5473 if (!strcmp (name, "Void")) {
5481 klass->byval_arg.type = (MonoTypeEnum)t;
5482 klass->this_arg.type = (MonoTypeEnum)t;
5485 if (MONO_CLASS_IS_INTERFACE (klass))
5486 klass->interface_id = mono_get_unique_iid (klass);
5492 * COM initialization is delayed until needed.
5493 * However when a [ComImport] attribute is present on a type it will trigger
5494 * the initialization. This is not a problem unless the BCL being executed
5495 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5498 init_com_from_comimport (MonoClass *klass)
5500 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5501 if (mono_security_core_clr_enabled ()) {
5502 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5503 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5504 /* but it can not be made available for application (i.e. user code) since all COM calls
5505 * are considered native calls. In this case we fail with a TypeLoadException (just like
5506 * Silverlight 2 does */
5507 mono_class_set_type_load_failure (klass, "");
5512 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5514 #endif /*DISABLE_COM*/
5517 * LOCKING: this assumes the loader lock is held
5520 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5522 gboolean system_namespace;
5523 gboolean is_corlib = mono_is_corlib_image (klass->image);
5525 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5527 /* if root of the hierarchy */
5528 if (system_namespace && !strcmp (klass->name, "Object")) {
5529 klass->parent = NULL;
5530 klass->instance_size = sizeof (MonoObject);
5533 if (!strcmp (klass->name, "<Module>")) {
5534 klass->parent = NULL;
5535 klass->instance_size = 0;
5539 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5540 /* Imported COM Objects always derive from __ComObject. */
5542 if (MONO_CLASS_IS_IMPORT (klass)) {
5543 init_com_from_comimport (klass);
5544 if (parent == mono_defaults.object_class)
5545 parent = mono_class_get_com_object_class ();
5549 /* set the parent to something useful and safe, but mark the type as broken */
5550 parent = mono_defaults.object_class;
5551 mono_class_set_type_load_failure (klass, "");
5554 klass->parent = parent;
5556 if (parent->generic_class && !parent->name) {
5558 * If the parent is a generic instance, we may get
5559 * called before it is fully initialized, especially
5560 * before it has its name.
5565 #ifndef DISABLE_REMOTING
5566 klass->marshalbyref = parent->marshalbyref;
5567 klass->contextbound = parent->contextbound;
5570 klass->delegate = parent->delegate;
5572 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5573 mono_class_set_is_com_object (klass);
5575 if (system_namespace) {
5576 #ifndef DISABLE_REMOTING
5577 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5578 klass->marshalbyref = 1;
5580 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5581 klass->contextbound = 1;
5583 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5584 klass->delegate = 1;
5587 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5588 (strcmp (klass->parent->name_space, "System") == 0)))
5589 klass->valuetype = 1;
5590 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5591 klass->valuetype = klass->enumtype = 1;
5593 /*klass->enumtype = klass->parent->enumtype; */
5595 /* initialize com types if COM interfaces are present */
5597 if (MONO_CLASS_IS_IMPORT (klass))
5598 init_com_from_comimport (klass);
5600 klass->parent = NULL;
5606 * mono_class_setup_supertypes:
5609 * Build the data structure needed to make fast type checks work.
5610 * This currently sets two fields in @class:
5611 * - idepth: distance between @class and System.Object in the type
5613 * - supertypes: array of classes: each element has a class in the hierarchy
5614 * starting from @class up to System.Object
5616 * LOCKING: This function is atomic, in case of contention we waste memory.
5619 mono_class_setup_supertypes (MonoClass *klass)
5622 MonoClass **supertypes;
5624 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5628 if (klass->parent && !klass->parent->supertypes)
5629 mono_class_setup_supertypes (klass->parent);
5631 klass->idepth = klass->parent->idepth + 1;
5635 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5636 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5638 if (klass->parent) {
5639 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5642 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5643 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5645 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5648 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5652 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5654 MonoClass *gtd = (MonoClass*)user_data;
5655 /* Only try to fix generic instances of @gtd */
5656 if (gclass->generic_class->container_class != gtd)
5659 /* Check if the generic instance has no parent. */
5660 if (gtd->parent && !gclass->parent)
5661 mono_generic_class_setup_parent (gclass, gtd);
5667 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5669 mono_class_set_type_load_failure (klass, "%s", msg);
5670 mono_error_set_type_load_class (error, klass, "%s", msg);
5674 * mono_class_create_from_typedef:
5675 * @image: image where the token is valid
5676 * @type_token: typedef token
5677 * @error: used to return any error found while creating the type
5679 * Create the MonoClass* representing the specified type token.
5680 * @type_token must be a TypeDef token.
5682 * FIXME: don't return NULL on failure, just the the caller figure it out.
5685 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5687 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5688 MonoClass *klass, *parent = NULL;
5689 guint32 cols [MONO_TYPEDEF_SIZE];
5690 guint32 cols_next [MONO_TYPEDEF_SIZE];
5691 guint tidx = mono_metadata_token_index (type_token);
5692 MonoGenericContext *context = NULL;
5693 const char *name, *nspace;
5695 MonoClass **interfaces;
5696 guint32 field_last, method_last;
5697 guint32 nesting_tokeen;
5699 mono_error_init (error);
5701 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5702 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5706 mono_loader_lock ();
5708 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5709 mono_loader_unlock ();
5713 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5715 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5716 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5718 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5721 klass->name_space = nspace;
5723 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5725 klass->image = image;
5726 klass->type_token = type_token;
5727 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5729 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5731 classes_size += sizeof (MonoClass);
5734 * Check whether we're a generic type definition.
5736 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5737 if (klass->generic_container) {
5738 klass->is_generic = 1;
5739 klass->generic_container->owner.klass = klass;
5740 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5741 context = &klass->generic_container->context;
5744 if (klass->generic_container)
5745 enable_gclass_recording ();
5747 if (cols [MONO_TYPEDEF_EXTENDS]) {
5749 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5751 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5752 /*WARNING: this must satisfy mono_metadata_type_hash*/
5753 klass->this_arg.byref = 1;
5754 klass->this_arg.data.klass = klass;
5755 klass->this_arg.type = MONO_TYPE_CLASS;
5756 klass->byval_arg.data.klass = klass;
5757 klass->byval_arg.type = MONO_TYPE_CLASS;
5759 parent = mono_class_get_checked (image, parent_token, error);
5760 if (parent && context) /* Always inflate */
5761 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5763 if (parent == NULL) {
5764 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5765 goto parent_failure;
5768 for (tmp = parent; tmp; tmp = tmp->parent) {
5770 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5771 goto parent_failure;
5773 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5774 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5775 goto parent_failure;
5780 mono_class_setup_parent (klass, parent);
5782 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5783 mono_class_setup_mono_type (klass);
5785 if (klass->generic_container)
5786 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5789 * This might access klass->byval_arg for recursion generated by generic constraints,
5790 * so it has to come after setup_mono_type ().
5792 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5793 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5794 if (!mono_error_ok (error)) {
5795 /*FIXME implement a mono_class_set_failure_from_mono_error */
5796 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5797 mono_loader_unlock ();
5798 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5803 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5807 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5811 klass->cast_class = klass->element_class = klass;
5813 if (!klass->enumtype) {
5814 if (!mono_metadata_interfaces_from_typedef_full (
5815 image, type_token, &interfaces, &icount, FALSE, context, error)){
5817 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5818 mono_loader_unlock ();
5819 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5823 klass->interfaces = interfaces;
5824 klass->interface_count = icount;
5825 klass->interfaces_inited = 1;
5828 /*g_print ("Load class %s\n", name);*/
5831 * Compute the field and method lists
5833 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5834 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5836 if (tt->rows > tidx){
5837 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5838 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5839 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5841 field_last = image->tables [MONO_TABLE_FIELD].rows;
5842 method_last = image->tables [MONO_TABLE_METHOD].rows;
5845 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5846 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5847 klass->field.count = field_last - klass->field.first;
5849 klass->field.count = 0;
5851 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5852 klass->method.count = method_last - klass->method.first;
5854 klass->method.count = 0;
5856 /* reserve space to store vector pointer in arrays */
5857 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5858 klass->instance_size += 2 * sizeof (gpointer);
5859 g_assert (klass->field.count == 0);
5862 if (klass->enumtype) {
5863 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5864 if (!enum_basetype) {
5865 /*set it to a default value as the whole runtime can't handle this to be null*/
5866 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5867 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5868 mono_loader_unlock ();
5869 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5872 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5876 * If we're a generic type definition, load the constraints.
5877 * We must do this after the class has been constructed to make certain recursive scenarios
5880 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5881 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5882 mono_loader_unlock ();
5883 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5887 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5888 if (!strncmp (name, "Vector", 6))
5889 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");
5892 mono_loader_unlock ();
5894 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5899 mono_class_setup_mono_type (klass);
5900 mono_loader_unlock ();
5901 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5905 /** Is klass a Nullable<T> ginst? */
5907 mono_class_is_nullable (MonoClass *klass)
5909 return klass->generic_class != NULL &&
5910 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5914 /** if klass is T? return T */
5916 mono_class_get_nullable_param (MonoClass *klass)
5918 g_assert (mono_class_is_nullable (klass));
5919 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5923 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5927 MonoGenericClass *gclass = klass->generic_class;
5929 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5930 if (!mono_error_ok (&error)) {
5931 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5932 klass->parent = mono_defaults.object_class;
5933 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5934 mono_error_cleanup (&error);
5938 mono_class_setup_parent (klass, klass->parent);
5940 if (klass->enumtype) {
5941 klass->cast_class = gtd->cast_class;
5942 klass->element_class = gtd->element_class;
5948 * Create the `MonoClass' for an instantiation of a generic type.
5949 * We only do this if we actually need it.
5952 mono_generic_class_get_class (MonoGenericClass *gclass)
5954 MonoClass *klass, *gklass;
5956 if (gclass->cached_class)
5957 return gclass->cached_class;
5959 mono_loader_lock ();
5960 if (gclass->cached_class) {
5961 mono_loader_unlock ();
5962 return gclass->cached_class;
5965 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5967 gklass = gclass->container_class;
5969 if (record_gclass_instantiation > 0)
5970 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5972 if (gklass->nested_in) {
5973 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5974 klass->nested_in = gklass->nested_in;
5977 klass->name = gklass->name;
5978 klass->name_space = gklass->name_space;
5980 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5982 klass->image = gklass->image;
5983 klass->flags = gklass->flags;
5984 klass->type_token = gklass->type_token;
5985 klass->field.count = gklass->field.count;
5987 klass->is_inflated = 1;
5988 klass->generic_class = gclass;
5990 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5991 klass->this_arg.type = klass->byval_arg.type;
5992 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5993 klass->this_arg.byref = TRUE;
5994 klass->enumtype = gklass->enumtype;
5995 klass->valuetype = gklass->valuetype;
5997 klass->cast_class = klass->element_class = klass;
5999 if (mono_class_is_nullable (klass))
6000 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6003 * We're not interested in the nested classes of a generic instance.
6004 * We use the generic type definition to look for nested classes.
6007 mono_generic_class_setup_parent (klass, gklass);
6009 if (gclass->is_dynamic) {
6011 * 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.
6012 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6013 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6015 if (!gklass->wastypebuilder)
6018 mono_class_setup_supertypes (klass);
6020 if (klass->enumtype) {
6022 * For enums, gklass->fields might not been set, but instance_size etc. is
6023 * already set in mono_reflection_create_internal_class (). For non-enums,
6024 * these will be computed normally in mono_class_layout_fields ().
6026 klass->instance_size = gklass->instance_size;
6027 klass->sizes.class_size = gklass->sizes.class_size;
6028 mono_memory_barrier ();
6029 klass->size_inited = 1;
6033 mono_memory_barrier ();
6034 gclass->cached_class = klass;
6036 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6038 inflated_classes ++;
6039 inflated_classes_size += sizeof (MonoClass);
6041 mono_loader_unlock ();
6047 get_image_for_container (MonoGenericContainer *container)
6050 if (container->is_anonymous) {
6051 result = container->owner.image;
6054 if (container->is_method) {
6055 MonoMethod *method = container->owner.method;
6056 g_assert_checked (method);
6057 klass = method->klass;
6059 klass = container->owner.klass;
6061 g_assert_checked (klass);
6062 result = klass->image;
6069 get_image_for_generic_param (MonoGenericParam *param)
6071 MonoGenericContainer *container = mono_generic_param_owner (param);
6072 g_assert_checked (container);
6073 return get_image_for_container (container);
6076 // Make a string in the designated image consisting of a single integer.
6077 #define INT_STRING_SIZE 16
6079 make_generic_name_string (MonoImage *image, int num)
6081 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6082 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6086 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6087 // pinfo is derived from param by the caller for us.
6089 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6091 MonoClass *klass, **ptr;
6093 MonoGenericContainer *container = mono_generic_param_owner (param);
6094 g_assert_checked (container);
6096 MonoImage *image = get_image_for_container (container);
6097 gboolean is_mvar = container->is_method;
6098 gboolean is_anonymous = container->is_anonymous;
6100 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6101 classes_size += sizeof (MonoClass);
6104 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6106 int n = mono_generic_param_num (param);
6107 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6111 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6112 } else if (is_mvar) {
6113 MonoMethod *omethod = container->owner.method;
6114 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6116 MonoClass *oklass = container->owner.klass;
6117 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6120 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6122 // Count non-NULL items in pinfo->constraints
6125 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6129 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6130 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6132 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6133 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6135 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6138 if (count - pos > 0) {
6139 klass->interface_count = count - pos;
6140 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6141 klass->interfaces_inited = TRUE;
6142 for (i = pos; i < count; i++)
6143 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6146 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6148 klass->inited = TRUE;
6149 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6150 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6151 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6153 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6154 klass->this_arg.type = klass->byval_arg.type;
6155 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6156 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6157 klass->this_arg.byref = TRUE;
6159 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6160 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6162 /*Init these fields to sane values*/
6163 klass->min_align = 1;
6165 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6166 * constrained to, the JIT depends on this.
6168 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6169 mono_memory_barrier ();
6170 klass->size_inited = 1;
6172 mono_class_setup_supertypes (klass);
6174 if (count - pos > 0) {
6175 mono_class_setup_vtable (klass->parent);
6176 if (mono_class_has_failure (klass->parent))
6177 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6179 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6185 #define FAST_CACHE_SIZE 16
6188 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6189 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6190 * we cache the MonoClasses.
6191 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6192 * LOCKING: Takes the image lock depending on @take_lock.
6195 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6197 int n = mono_generic_param_num (param);
6198 MonoImage *image = get_image_for_generic_param (param);
6199 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6200 MonoClass *klass = NULL;
6205 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6206 // For high numbers or constraints we have to use pointer hashes.
6207 if (param->gshared_constraint) {
6208 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6211 mono_image_lock (image);
6212 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6214 mono_image_unlock (image);
6219 if (n < FAST_CACHE_SIZE) {
6221 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6223 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6225 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6228 mono_image_lock (image);
6229 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6231 mono_image_unlock (image);
6238 * LOCKING: Image lock (param->image) must be held
6241 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6243 int n = mono_generic_param_num (param);
6244 MonoImage *image = get_image_for_generic_param (param);
6245 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6249 if (param->gshared_constraint) {
6250 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6252 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6253 mono_memory_barrier ();
6255 image->mvar_cache_constrained = ht;
6257 image->var_cache_constrained = ht;
6259 g_hash_table_insert (ht, param, klass);
6260 } else if (n < FAST_CACHE_SIZE) {
6262 /* Requires locking to avoid droping an already published class */
6263 if (!image->mvar_cache_fast)
6264 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6265 image->mvar_cache_fast [n] = klass;
6267 if (!image->var_cache_fast)
6268 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6269 image->var_cache_fast [n] = klass;
6272 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6274 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6276 ht = g_hash_table_new (NULL, NULL);
6277 mono_memory_barrier ();
6279 image->mvar_cache_slow = ht;
6281 image->var_cache_slow = ht;
6284 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6289 * LOCKING: Acquires the image lock (@image).
6292 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6294 MonoImage *image = get_image_for_generic_param (param);
6295 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6296 MonoClass *klass, *klass2;
6298 // If a klass already exists for this object and is cached, return it.
6299 if (pinfo) // Non-anonymous
6300 klass = pinfo->pklass;
6302 klass = get_anon_gparam_class (param, TRUE);
6307 // Create a new klass
6308 klass = make_generic_param_class (param, pinfo);
6310 // Now we need to cache the klass we created.
6311 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6312 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6313 // and allow our newly-created klass object to just leak.
6314 mono_memory_barrier ();
6316 mono_image_lock (image);
6318 // Here "klass2" refers to the klass potentially created by the other thread.
6319 if (pinfo) // Repeat check from above
6320 klass2 = pinfo->pklass;
6322 klass2 = get_anon_gparam_class (param, FALSE);
6329 pinfo->pklass = klass;
6331 set_anon_gparam_class (param, klass);
6333 mono_image_unlock (image);
6335 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6337 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6339 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6345 * mono_class_from_generic_parameter:
6346 * @param: Parameter to find/construct a class for.
6347 * @arg2: Is ignored.
6348 * @arg3: Is ignored.
6351 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6353 return mono_class_from_generic_parameter_internal (param);
6358 mono_ptr_class_get (MonoType *type)
6361 MonoClass *el_class;
6365 el_class = mono_class_from_mono_type (type);
6366 image = el_class->image;
6368 mono_image_lock (image);
6369 if (image->ptr_cache) {
6370 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6371 mono_image_unlock (image);
6375 mono_image_unlock (image);
6377 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6379 classes_size += sizeof (MonoClass);
6381 result->parent = NULL; /* no parent for PTR types */
6382 result->name_space = el_class->name_space;
6383 name = g_strdup_printf ("%s*", el_class->name);
6384 result->name = mono_image_strdup (image, name);
6387 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6389 result->image = el_class->image;
6390 result->inited = TRUE;
6391 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6392 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6393 result->cast_class = result->element_class = el_class;
6394 result->blittable = TRUE;
6396 result->byval_arg.type = MONO_TYPE_PTR;
6397 result->this_arg.type = result->byval_arg.type;
6398 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6399 result->this_arg.byref = TRUE;
6401 mono_class_setup_supertypes (result);
6403 mono_image_lock (image);
6404 if (image->ptr_cache) {
6406 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6407 mono_image_unlock (image);
6408 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6412 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6414 g_hash_table_insert (image->ptr_cache, el_class, result);
6415 mono_image_unlock (image);
6417 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6423 mono_fnptr_class_get (MonoMethodSignature *sig)
6426 static GHashTable *ptr_hash = NULL;
6428 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6430 mono_loader_lock ();
6433 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6435 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6436 mono_loader_unlock ();
6439 result = g_new0 (MonoClass, 1);
6441 result->parent = NULL; /* no parent for PTR types */
6442 result->name_space = "System";
6443 result->name = "MonoFNPtrFakeClass";
6445 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6447 result->image = mono_defaults.corlib; /* need to fix... */
6448 result->inited = TRUE;
6449 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6450 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6451 result->cast_class = result->element_class = result;
6452 result->blittable = TRUE;
6454 result->byval_arg.type = MONO_TYPE_FNPTR;
6455 result->this_arg.type = result->byval_arg.type;
6456 result->this_arg.data.method = result->byval_arg.data.method = sig;
6457 result->this_arg.byref = TRUE;
6458 result->blittable = TRUE;
6460 mono_class_setup_supertypes (result);
6462 g_hash_table_insert (ptr_hash, sig, result);
6464 mono_loader_unlock ();
6466 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6472 * mono_class_from_mono_type:
6473 * @type: describes the type to return
6475 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6478 mono_class_from_mono_type (MonoType *type)
6480 switch (type->type) {
6481 case MONO_TYPE_OBJECT:
6482 return type->data.klass? type->data.klass: mono_defaults.object_class;
6483 case MONO_TYPE_VOID:
6484 return type->data.klass? type->data.klass: mono_defaults.void_class;
6485 case MONO_TYPE_BOOLEAN:
6486 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6487 case MONO_TYPE_CHAR:
6488 return type->data.klass? type->data.klass: mono_defaults.char_class;
6490 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6492 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6494 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6496 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6498 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6500 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6502 return type->data.klass? type->data.klass: mono_defaults.int_class;
6504 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6506 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6508 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6510 return type->data.klass? type->data.klass: mono_defaults.single_class;
6512 return type->data.klass? type->data.klass: mono_defaults.double_class;
6513 case MONO_TYPE_STRING:
6514 return type->data.klass? type->data.klass: mono_defaults.string_class;
6515 case MONO_TYPE_TYPEDBYREF:
6516 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6517 case MONO_TYPE_ARRAY:
6518 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6520 return mono_ptr_class_get (type->data.type);
6521 case MONO_TYPE_FNPTR:
6522 return mono_fnptr_class_get (type->data.method);
6523 case MONO_TYPE_SZARRAY:
6524 return mono_array_class_get (type->data.klass, 1);
6525 case MONO_TYPE_CLASS:
6526 case MONO_TYPE_VALUETYPE:
6527 return type->data.klass;
6528 case MONO_TYPE_GENERICINST:
6529 return mono_generic_class_get_class (type->data.generic_class);
6530 case MONO_TYPE_MVAR:
6532 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6534 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6535 g_assert_not_reached ();
6538 // Yes, this returns NULL, even if it is documented as not doing so, but there
6539 // is no way for the code to make it this far, due to the assert above.
6544 * mono_type_retrieve_from_typespec
6545 * @image: context where the image is created
6546 * @type_spec: typespec token
6547 * @context: the generic context used to evaluate generic instantiations in
6550 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6552 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6554 *did_inflate = FALSE;
6559 if (context && (context->class_inst || context->method_inst)) {
6560 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6562 if (!mono_error_ok (error)) {
6568 *did_inflate = TRUE;
6575 * mono_class_create_from_typespec
6576 * @image: context where the image is created
6577 * @type_spec: typespec token
6578 * @context: the generic context used to evaluate generic instantiations in
6581 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6584 gboolean inflated = FALSE;
6585 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6586 return_val_if_nok (error, NULL);
6587 ret = mono_class_from_mono_type (t);
6589 mono_metadata_free_type (t);
6594 * mono_bounded_array_class_get:
6595 * @element_class: element class
6596 * @rank: the dimension of the array class
6597 * @bounded: whenever the array has non-zero bounds
6599 * Returns: A class object describing the array with element type @element_type and
6603 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6607 MonoClass *parent = NULL;
6608 GSList *list, *rootlist = NULL;
6612 g_assert (rank <= 255);
6615 /* bounded only matters for one-dimensional arrays */
6618 image = eclass->image;
6620 if (rank == 1 && !bounded) {
6622 * This case is very frequent not just during compilation because of calls
6623 * from mono_class_from_mono_type (), mono_array_new (),
6624 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6626 mono_os_mutex_lock (&image->szarray_cache_lock);
6627 if (!image->szarray_cache)
6628 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6629 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6630 mono_os_mutex_unlock (&image->szarray_cache_lock);
6634 mono_loader_lock ();
6636 mono_loader_lock ();
6638 if (!image->array_cache)
6639 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6641 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6642 for (; list; list = list->next) {
6643 klass = (MonoClass *)list->data;
6644 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6645 mono_loader_unlock ();
6652 parent = mono_defaults.array_class;
6653 if (!parent->inited)
6654 mono_class_init (parent);
6656 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6658 klass->image = image;
6659 klass->name_space = eclass->name_space;
6660 nsize = strlen (eclass->name);
6661 name = (char *)g_malloc (nsize + 2 + rank + 1);
6662 memcpy (name, eclass->name, nsize);
6665 memset (name + nsize + 1, ',', rank - 1);
6667 name [nsize + rank] = '*';
6668 name [nsize + rank + bounded] = ']';
6669 name [nsize + rank + bounded + 1] = 0;
6670 klass->name = mono_image_strdup (image, name);
6673 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6675 classes_size += sizeof (MonoClass);
6677 klass->type_token = 0;
6678 /* all arrays are marked serializable and sealed, bug #42779 */
6679 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6680 klass->parent = parent;
6681 klass->instance_size = mono_class_instance_size (klass->parent);
6683 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6684 /*Arrays of those two types are invalid.*/
6685 MonoError prepared_error;
6686 mono_error_init (&prepared_error);
6687 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6688 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6689 mono_error_cleanup (&prepared_error);
6690 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6691 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6692 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6693 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6695 /* element_size -1 is ok as this is not an instantitable type*/
6696 klass->sizes.element_size = -1;
6698 klass->sizes.element_size = mono_class_array_element_size (eclass);
6700 mono_class_setup_supertypes (klass);
6702 if (eclass->generic_class)
6703 mono_class_init (eclass);
6704 if (!eclass->size_inited)
6705 mono_class_setup_fields (eclass);
6706 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6707 /*FIXME we fail the array type, but we have to let other fields be set.*/
6709 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6713 if (eclass->enumtype)
6714 klass->cast_class = eclass->element_class;
6716 klass->cast_class = eclass;
6718 switch (klass->cast_class->byval_arg.type) {
6720 klass->cast_class = mono_defaults.byte_class;
6723 klass->cast_class = mono_defaults.int16_class;
6726 #if SIZEOF_VOID_P == 4
6730 klass->cast_class = mono_defaults.int32_class;
6733 #if SIZEOF_VOID_P == 8
6737 klass->cast_class = mono_defaults.int64_class;
6743 klass->element_class = eclass;
6745 if ((rank > 1) || bounded) {
6746 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6747 klass->byval_arg.type = MONO_TYPE_ARRAY;
6748 klass->byval_arg.data.array = at;
6749 at->eklass = eclass;
6751 /* FIXME: complete.... */
6753 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6754 klass->byval_arg.data.klass = eclass;
6756 klass->this_arg = klass->byval_arg;
6757 klass->this_arg.byref = 1;
6759 klass->generic_container = eclass->generic_container;
6761 if (rank == 1 && !bounded) {
6762 MonoClass *prev_class;
6764 mono_os_mutex_lock (&image->szarray_cache_lock);
6765 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6767 /* Someone got in before us */
6770 g_hash_table_insert (image->szarray_cache, eclass, klass);
6771 mono_os_mutex_unlock (&image->szarray_cache_lock);
6773 list = g_slist_append (rootlist, klass);
6774 g_hash_table_insert (image->array_cache, eclass, list);
6777 mono_loader_unlock ();
6779 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6785 * mono_array_class_get:
6786 * @element_class: element class
6787 * @rank: the dimension of the array class
6789 * Returns: A class object describing the array with element type @element_type and
6793 mono_array_class_get (MonoClass *eclass, guint32 rank)
6795 return mono_bounded_array_class_get (eclass, rank, FALSE);
6799 * mono_class_instance_size:
6802 * Use to get the size of a class in bytes.
6804 * Returns: The size of an object instance
6807 mono_class_instance_size (MonoClass *klass)
6809 if (!klass->size_inited)
6810 mono_class_init (klass);
6812 return klass->instance_size;
6816 * mono_class_min_align:
6819 * Use to get the computed minimum alignment requirements for the specified class.
6821 * Returns: minimm alignment requirements
6824 mono_class_min_align (MonoClass *klass)
6826 if (!klass->size_inited)
6827 mono_class_init (klass);
6829 return klass->min_align;
6833 * mono_class_value_size:
6836 * This function is used for value types, and return the
6837 * space and the alignment to store that kind of value object.
6839 * Returns: the size of a value of kind @klass
6842 mono_class_value_size (MonoClass *klass, guint32 *align)
6846 /* fixme: check disable, because we still have external revereces to
6847 * mscorlib and Dummy Objects
6849 /*g_assert (klass->valuetype);*/
6851 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6854 *align = klass->min_align;
6860 * mono_class_data_size:
6863 * Returns: The size of the static class data
6866 mono_class_data_size (MonoClass *klass)
6869 mono_class_init (klass);
6870 /* This can happen with dynamically created types */
6871 if (!klass->fields_inited)
6872 mono_class_setup_fields (klass);
6874 /* in arrays, sizes.class_size is unioned with element_size
6875 * and arrays have no static fields
6879 return klass->sizes.class_size;
6883 * Auxiliary routine to mono_class_get_field
6885 * Takes a field index instead of a field token.
6887 static MonoClassField *
6888 mono_class_get_field_idx (MonoClass *klass, int idx)
6890 mono_class_setup_fields (klass);
6891 if (mono_class_has_failure (klass))
6895 if (klass->image->uncompressed_metadata) {
6897 * klass->field.first points to the FieldPtr table, while idx points into the
6898 * Field table, so we have to do a search.
6900 /*FIXME this is broken for types with multiple fields with the same name.*/
6901 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6904 for (i = 0; i < klass->field.count; ++i)
6905 if (mono_field_get_name (&klass->fields [i]) == name)
6906 return &klass->fields [i];
6907 g_assert_not_reached ();
6909 if (klass->field.count) {
6910 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6911 return &klass->fields [idx - klass->field.first];
6915 klass = klass->parent;
6921 * mono_class_get_field:
6922 * @class: the class to lookup the field.
6923 * @field_token: the field token
6925 * Returns: A MonoClassField representing the type and offset of
6926 * the field, or a NULL value if the field does not belong to this
6930 mono_class_get_field (MonoClass *klass, guint32 field_token)
6932 int idx = mono_metadata_token_index (field_token);
6934 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6936 return mono_class_get_field_idx (klass, idx - 1);
6940 * mono_class_get_field_from_name:
6941 * @klass: the class to lookup the field.
6942 * @name: the field name
6944 * Search the class @klass and it's parents for a field with the name @name.
6946 * Returns: The MonoClassField pointer of the named field or NULL
6949 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6951 return mono_class_get_field_from_name_full (klass, name, NULL);
6955 * mono_class_get_field_from_name_full:
6956 * @klass: the class to lookup the field.
6957 * @name: the field name
6958 * @type: the type of the fields. This optional.
6960 * Search the class @klass and it's parents for a field with the name @name and type @type.
6962 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6963 * of its generic type definition.
6965 * Returns: The MonoClassField pointer of the named field or NULL
6968 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6972 mono_class_setup_fields (klass);
6973 if (mono_class_has_failure (klass))
6977 for (i = 0; i < klass->field.count; ++i) {
6978 MonoClassField *field = &klass->fields [i];
6980 if (strcmp (name, mono_field_get_name (field)) != 0)
6984 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6985 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6990 klass = klass->parent;
6996 * mono_class_get_field_token:
6997 * @field: the field we need the token of
6999 * Get the token of a field. Note that the tokesn is only valid for the image
7000 * the field was loaded from. Don't use this function for fields in dynamic types.
7002 * Returns: The token representing the field in the image it was loaded from.
7005 mono_class_get_field_token (MonoClassField *field)
7007 MonoClass *klass = field->parent;
7010 mono_class_setup_fields (klass);
7015 for (i = 0; i < klass->field.count; ++i) {
7016 if (&klass->fields [i] == field) {
7017 int idx = klass->field.first + i + 1;
7019 if (klass->image->uncompressed_metadata)
7020 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7021 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7024 klass = klass->parent;
7027 g_assert_not_reached ();
7032 mono_field_get_index (MonoClassField *field)
7034 int index = field - field->parent->fields;
7036 g_assert (index >= 0 && index < field->parent->field.count);
7042 * mono_class_get_field_default_value:
7044 * Return the default value of the field as a pointer into the metadata blob.
7047 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7050 guint32 constant_cols [MONO_CONSTANT_SIZE];
7052 MonoClass *klass = field->parent;
7054 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7056 if (!klass->ext || !klass->ext->field_def_values) {
7057 MonoFieldDefaultValue *def_values;
7059 mono_class_alloc_ext (klass);
7061 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7063 mono_image_lock (klass->image);
7064 mono_memory_barrier ();
7065 if (!klass->ext->field_def_values)
7066 klass->ext->field_def_values = def_values;
7067 mono_image_unlock (klass->image);
7070 field_index = mono_field_get_index (field);
7072 if (!klass->ext->field_def_values [field_index].data) {
7073 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7077 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7079 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7080 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7081 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7084 *def_type = klass->ext->field_def_values [field_index].def_type;
7085 return klass->ext->field_def_values [field_index].data;
7089 mono_property_get_index (MonoProperty *prop)
7091 int index = prop - prop->parent->ext->properties;
7093 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7099 * mono_class_get_property_default_value:
7101 * Return the default value of the field as a pointer into the metadata blob.
7104 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7107 guint32 constant_cols [MONO_CONSTANT_SIZE];
7108 MonoClass *klass = property->parent;
7110 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7112 * We don't cache here because it is not used by C# so it's quite rare, but
7113 * we still do the lookup in klass->ext because that is where the data
7114 * is stored for dynamic assemblies.
7117 if (image_is_dynamic (klass->image)) {
7118 int prop_index = mono_property_get_index (property);
7119 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7120 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7121 return klass->ext->prop_def_values [prop_index].data;
7125 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7129 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7130 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7131 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7135 mono_class_get_event_token (MonoEvent *event)
7137 MonoClass *klass = event->parent;
7142 for (i = 0; i < klass->ext->event.count; ++i) {
7143 if (&klass->ext->events [i] == event)
7144 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7147 klass = klass->parent;
7150 g_assert_not_reached ();
7155 * mono_class_get_property_from_name:
7157 * @name: name of the property to lookup in the specified class
7159 * Use this method to lookup a property in a class
7160 * Returns: the MonoProperty with the given name, or NULL if the property
7161 * does not exist on the @klass.
7164 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7168 gpointer iter = NULL;
7169 while ((p = mono_class_get_properties (klass, &iter))) {
7170 if (! strcmp (name, p->name))
7173 klass = klass->parent;
7179 * mono_class_get_property_token:
7180 * @prop: MonoProperty to query
7182 * Returns: The ECMA token for the specified property.
7185 mono_class_get_property_token (MonoProperty *prop)
7187 MonoClass *klass = prop->parent;
7191 gpointer iter = NULL;
7192 while ((p = mono_class_get_properties (klass, &iter))) {
7193 if (&klass->ext->properties [i] == prop)
7194 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7198 klass = klass->parent;
7201 g_assert_not_reached ();
7206 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7208 const char *name, *nspace;
7209 if (image_is_dynamic (image))
7210 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7212 switch (type_token & 0xff000000){
7213 case MONO_TOKEN_TYPE_DEF: {
7214 guint32 cols [MONO_TYPEDEF_SIZE];
7215 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7216 guint tidx = mono_metadata_token_index (type_token);
7218 if (tidx > tt->rows)
7219 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7221 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7222 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7223 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7224 if (strlen (nspace) == 0)
7225 return g_strdup_printf ("%s", name);
7227 return g_strdup_printf ("%s.%s", nspace, name);
7230 case MONO_TOKEN_TYPE_REF: {
7232 guint32 cols [MONO_TYPEREF_SIZE];
7233 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7234 guint tidx = mono_metadata_token_index (type_token);
7237 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7239 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7240 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7241 mono_error_cleanup (&error);
7245 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7246 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7247 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7248 if (strlen (nspace) == 0)
7249 return g_strdup_printf ("%s", name);
7251 return g_strdup_printf ("%s.%s", nspace, name);
7254 case MONO_TOKEN_TYPE_SPEC:
7255 return g_strdup_printf ("Typespec 0x%08x", type_token);
7257 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7262 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7264 if (image_is_dynamic (image))
7265 return g_strdup_printf ("DynamicAssembly %s", image->name);
7267 switch (type_token & 0xff000000){
7268 case MONO_TOKEN_TYPE_DEF:
7269 if (image->assembly)
7270 return mono_stringify_assembly_name (&image->assembly->aname);
7271 else if (image->assembly_name)
7272 return g_strdup (image->assembly_name);
7273 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7274 case MONO_TOKEN_TYPE_REF: {
7276 MonoAssemblyName aname;
7277 guint32 cols [MONO_TYPEREF_SIZE];
7278 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7279 guint32 idx = mono_metadata_token_index (type_token);
7282 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7284 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7285 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7286 mono_error_cleanup (&error);
7289 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7291 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7292 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7293 case MONO_RESOLUTION_SCOPE_MODULE:
7295 return g_strdup ("");
7296 case MONO_RESOLUTION_SCOPE_MODULEREF:
7298 return g_strdup ("");
7299 case MONO_RESOLUTION_SCOPE_TYPEREF:
7301 return g_strdup ("");
7302 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7303 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7304 return mono_stringify_assembly_name (&aname);
7306 g_assert_not_reached ();
7310 case MONO_TOKEN_TYPE_SPEC:
7312 return g_strdup ("");
7314 g_assert_not_reached ();
7321 * mono_class_get_full:
7322 * @image: the image where the class resides
7323 * @type_token: the token for the class
7324 * @context: the generic context used to evaluate generic instantiations in
7325 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7327 * Returns: The MonoClass that represents @type_token in @image
7330 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7334 klass = mono_class_get_checked (image, type_token, &error);
7336 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7337 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7339 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7345 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7349 mono_error_init (error);
7350 klass = mono_class_get_checked (image, type_token, error);
7352 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7353 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7358 * mono_class_get_checked:
7359 * @image: the image where the class resides
7360 * @type_token: the token for the class
7361 * @error: error object to return any error
7363 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7366 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7368 MonoClass *klass = NULL;
7370 mono_error_init (error);
7372 if (image_is_dynamic (image)) {
7373 int table = mono_metadata_token_table (type_token);
7375 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7376 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7379 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7383 switch (type_token & 0xff000000){
7384 case MONO_TOKEN_TYPE_DEF:
7385 klass = mono_class_create_from_typedef (image, type_token, error);
7387 case MONO_TOKEN_TYPE_REF:
7388 klass = mono_class_from_typeref_checked (image, type_token, error);
7390 case MONO_TOKEN_TYPE_SPEC:
7391 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7394 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7398 /* Generic case, should be avoided for when a better error is possible. */
7399 if (!klass && mono_error_ok (error)) {
7400 char *name = mono_class_name_from_token (image, type_token);
7401 char *assembly = mono_assembly_name_from_token (image, type_token);
7402 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7410 * mono_type_get_checked:
7411 * @image: the image where the type resides
7412 * @type_token: the token for the type
7413 * @context: the generic context used to evaluate generic instantiations in
7414 * @error: Error handling context
7416 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7418 * Returns: The MonoType that represents @type_token in @image
7421 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7423 MonoType *type = NULL;
7424 gboolean inflated = FALSE;
7426 mono_error_init (error);
7428 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7429 if (image_is_dynamic (image)) {
7430 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7431 return_val_if_nok (error, NULL);
7432 return mono_class_get_type (klass);
7435 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7436 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7443 return mono_class_get_type (klass);
7446 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7453 MonoType *tmp = type;
7454 type = mono_class_get_type (mono_class_from_mono_type (type));
7455 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7456 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7457 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7459 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7461 if (type->type != tmp->type)
7464 mono_metadata_free_type (tmp);
7471 * @image: image where the class token will be looked up.
7472 * @type_token: a type token from the image
7474 * Returns the MonoClass with the given @type_token on the @image
7477 mono_class_get (MonoImage *image, guint32 type_token)
7479 return mono_class_get_full (image, type_token, NULL);
7483 * mono_image_init_name_cache:
7485 * Initializes the class name cache stored in image->name_cache.
7487 * LOCKING: Acquires the corresponding image lock.
7490 mono_image_init_name_cache (MonoImage *image)
7492 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7493 guint32 cols [MONO_TYPEDEF_SIZE];
7496 guint32 i, visib, nspace_index;
7497 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7499 if (image->name_cache)
7502 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7504 if (image_is_dynamic (image)) {
7505 mono_image_lock (image);
7506 if (image->name_cache) {
7507 /* Somebody initialized it before us */
7508 g_hash_table_destroy (the_name_cache);
7510 mono_atomic_store_release (&image->name_cache, the_name_cache);
7512 mono_image_unlock (image);
7516 /* Temporary hash table to avoid lookups in the nspace_table */
7517 name_cache2 = g_hash_table_new (NULL, NULL);
7519 for (i = 1; i <= t->rows; ++i) {
7520 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7521 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7523 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7524 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7526 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7528 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7529 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7531 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7532 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7533 if (!nspace_table) {
7534 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7535 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7536 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7539 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7542 /* Load type names from EXPORTEDTYPES table */
7544 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7545 guint32 cols [MONO_EXP_TYPE_SIZE];
7548 for (i = 0; i < t->rows; ++i) {
7549 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7551 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7552 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7556 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7557 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7559 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7560 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7561 if (!nspace_table) {
7562 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7563 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7564 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7567 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7571 g_hash_table_destroy (name_cache2);
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);
7583 /*FIXME Only dynamic assemblies should allow this operation.*/
7585 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7586 const char *name, guint32 index)
7588 GHashTable *nspace_table;
7589 GHashTable *name_cache;
7592 mono_image_init_name_cache (image);
7593 mono_image_lock (image);
7595 name_cache = image->name_cache;
7596 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7597 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7598 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7601 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7602 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7604 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7606 mono_image_unlock (image);
7615 find_nocase (gpointer key, gpointer value, gpointer user_data)
7617 char *name = (char*)key;
7618 FindUserData *data = (FindUserData*)user_data;
7620 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7621 data->value = value;
7625 * mono_class_from_name_case:
7626 * @image: The MonoImage where the type is looked up in
7627 * @name_space: the type namespace
7628 * @name: the type short name.
7629 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7631 * Obtains a MonoClass with a given namespace and a given name which
7632 * is located in the given MonoImage. The namespace and name
7633 * lookups are case insensitive.
7636 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7639 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7640 mono_error_cleanup (&error);
7646 * mono_class_from_name_case:
7647 * @image: The MonoImage where the type is looked up in
7648 * @name_space: the type namespace
7649 * @name: the type short name.
7652 * Obtains a MonoClass with a given namespace and a given name which
7653 * is located in the given MonoImage. The namespace and name
7654 * lookups are case insensitive.
7656 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7657 * was not found. The @error object will contain information about the problem
7661 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7663 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7664 guint32 cols [MONO_TYPEDEF_SIZE];
7669 mono_error_init (error);
7671 if (image_is_dynamic (image)) {
7673 FindUserData user_data;
7675 mono_image_init_name_cache (image);
7676 mono_image_lock (image);
7678 user_data.key = name_space;
7679 user_data.value = NULL;
7680 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7682 if (user_data.value) {
7683 GHashTable *nspace_table = (GHashTable*)user_data.value;
7685 user_data.key = name;
7686 user_data.value = NULL;
7688 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7690 if (user_data.value)
7691 token = GPOINTER_TO_UINT (user_data.value);
7694 mono_image_unlock (image);
7697 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7703 /* add a cache if needed */
7704 for (i = 1; i <= t->rows; ++i) {
7705 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7706 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7708 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7709 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7711 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7713 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7714 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7715 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7716 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7722 return_nested_in (MonoClass *klass, char *nested)
7725 char *s = strchr (nested, '/');
7726 gpointer iter = NULL;
7733 while ((found = mono_class_get_nested_types (klass, &iter))) {
7734 if (strcmp (found->name, nested) == 0) {
7736 return return_nested_in (found, s);
7744 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7746 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7747 MonoImage *file_image;
7751 mono_error_init (error);
7754 * The EXPORTEDTYPES table only contains public types, so have to search the
7756 * Note: image->modules contains the contents of the MODULEREF table, while
7757 * the real module list is in the FILE table.
7759 for (i = 0; i < file_table->rows; i++) {
7760 guint32 cols [MONO_FILE_SIZE];
7761 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7762 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7765 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7767 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7768 if (klass || !is_ok (error))
7777 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7779 GHashTable *nspace_table;
7780 MonoImage *loaded_image;
7787 mono_error_init (error);
7789 // Checking visited images avoids stack overflows when cyclic references exist.
7790 if (g_hash_table_lookup (visited_images, image))
7793 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7795 if ((nested = strchr (name, '/'))) {
7796 int pos = nested - name;
7797 int len = strlen (name);
7800 memcpy (buf, name, len + 1);
7802 nested = buf + pos + 1;
7806 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7807 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7808 gboolean res = get_class_from_name (image, name_space, name, &klass);
7811 klass = search_modules (image, name_space, name, error);
7816 return klass ? return_nested_in (klass, nested) : NULL;
7822 mono_image_init_name_cache (image);
7823 mono_image_lock (image);
7825 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7828 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7830 mono_image_unlock (image);
7832 if (!token && image_is_dynamic (image) && image->modules) {
7833 /* Search modules as well */
7834 for (i = 0; i < image->module_count; ++i) {
7835 MonoImage *module = image->modules [i];
7837 klass = mono_class_from_name_checked (module, name_space, name, error);
7838 if (klass || !is_ok (error))
7844 klass = search_modules (image, name_space, name, error);
7845 if (klass || !is_ok (error))
7850 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7851 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7852 guint32 cols [MONO_EXP_TYPE_SIZE];
7855 idx = mono_metadata_token_index (token);
7857 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7859 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7860 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7861 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7864 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7866 return klass ? return_nested_in (klass, nested) : NULL;
7868 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7869 guint32 assembly_idx;
7871 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7873 mono_assembly_load_reference (image, assembly_idx - 1);
7874 g_assert (image->references [assembly_idx - 1]);
7875 if (image->references [assembly_idx - 1] == (gpointer)-1)
7877 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7879 return klass ? return_nested_in (klass, nested) : NULL;
7882 g_assert_not_reached ();
7886 token = MONO_TOKEN_TYPE_DEF | token;
7888 klass = mono_class_get_checked (image, token, error);
7890 return return_nested_in (klass, nested);
7895 * mono_class_from_name_checked:
7896 * @image: The MonoImage where the type is looked up in
7897 * @name_space: the type namespace
7898 * @name: the type short name.
7900 * Obtains a MonoClass with a given namespace and a given name which
7901 * is located in the given MonoImage.
7903 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7904 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7907 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7910 GHashTable *visited_images;
7912 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7914 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7916 g_hash_table_destroy (visited_images);
7922 * mono_class_from_name:
7923 * @image: The MonoImage where the type is looked up in
7924 * @name_space: the type namespace
7925 * @name: the type short name.
7927 * Obtains a MonoClass with a given namespace and a given name which
7928 * is located in the given MonoImage.
7930 * To reference nested classes, use the "/" character as a separator.
7931 * For example use "Foo/Bar" to reference the class Bar that is nested
7932 * inside Foo, like this: "class Foo { class Bar {} }".
7935 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7940 klass = mono_class_from_name_checked (image, name_space, name, &error);
7941 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7947 * mono_class_load_from_name:
7948 * @image: The MonoImage where the type is looked up in
7949 * @name_space: the type namespace
7950 * @name: the type short name.
7952 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7953 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7954 * If they are missing. Thing of System.Object or System.String.
7957 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7962 klass = mono_class_from_name_checked (image, name_space, name, &error);
7964 g_error ("Runtime critical type %s.%s not found", name_space, name);
7965 if (!mono_error_ok (&error))
7966 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7971 * mono_class_try_load_from_name:
7972 * @image: The MonoImage where the type is looked up in
7973 * @name_space: the type namespace
7974 * @name: the type short name.
7976 * This function tries to load a type, returning the class was found or NULL otherwise.
7977 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7979 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7980 * a type that we would otherwise assume to be available but was not due some error.
7984 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7989 klass = mono_class_from_name_checked (image, name_space, name, &error);
7990 if (!mono_error_ok (&error))
7991 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7997 * mono_class_is_subclass_of:
7998 * @klass: class to probe if it is a subclass of another one
7999 * @klassc: the class we suspect is the base class
8000 * @check_interfaces: whether we should perform interface checks
8002 * This method determines whether @klass is a subclass of @klassc.
8004 * If the @check_interfaces flag is set, then if @klassc is an interface
8005 * this method return TRUE if the @klass implements the interface or
8006 * if @klass is an interface, if one of its base classes is @klass.
8008 * If @check_interfaces is false then, then if @klass is not an interface
8009 * then it returns TRUE if the @klass is a subclass of @klassc.
8011 * if @klass is an interface and @klassc is System.Object, then this function
8016 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8017 gboolean check_interfaces)
8019 /* FIXME test for interfaces with variant generic arguments */
8020 mono_class_init (klass);
8021 mono_class_init (klassc);
8023 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8024 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8026 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8029 for (i = 0; i < klass->interface_count; i ++) {
8030 MonoClass *ic = klass->interfaces [i];
8035 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8040 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8043 if (klassc == mono_defaults.object_class)
8050 mono_type_is_generic_argument (MonoType *type)
8052 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8056 mono_class_has_variant_generic_params (MonoClass *klass)
8059 MonoGenericContainer *container;
8061 if (!klass->generic_class)
8064 container = klass->generic_class->container_class->generic_container;
8066 for (i = 0; i < container->type_argc; ++i)
8067 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8074 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8076 if (target == candidate)
8079 if (check_for_reference_conv &&
8080 mono_type_is_generic_argument (&target->byval_arg) &&
8081 mono_type_is_generic_argument (&candidate->byval_arg)) {
8082 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8083 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8085 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8088 if (!mono_class_is_assignable_from (target, candidate))
8094 * @container the generic container from the GTD
8095 * @klass: the class to be assigned to
8096 * @oklass: the source class
8098 * Both @klass and @oklass must be instances of the same generic interface.
8100 * Returns: TRUE if @klass can be assigned to a @klass variable
8103 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8106 MonoType **klass_argv, **oklass_argv;
8107 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8108 MonoGenericContainer *container = klass_gtd->generic_container;
8110 if (klass == oklass)
8113 /*Viable candidates are instances of the same generic interface*/
8114 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8117 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8118 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8120 for (j = 0; j < container->type_argc; ++j) {
8121 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8122 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8124 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8128 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8129 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8131 if (param1_class != param2_class) {
8132 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8133 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8135 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8136 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8146 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8148 MonoGenericParam *gparam, *ogparam;
8149 MonoGenericParamInfo *tinfo, *cinfo;
8150 MonoClass **candidate_class;
8151 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8154 if (target == candidate)
8156 if (target->byval_arg.type != candidate->byval_arg.type)
8159 gparam = target->byval_arg.data.generic_param;
8160 ogparam = candidate->byval_arg.data.generic_param;
8161 tinfo = mono_generic_param_info (gparam);
8162 cinfo = mono_generic_param_info (ogparam);
8164 class_constraint_satisfied = FALSE;
8165 valuetype_constraint_satisfied = FALSE;
8167 /*candidate must have a super set of target's special constraints*/
8168 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8169 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8171 if (cinfo->constraints) {
8172 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8173 MonoClass *cc = *candidate_class;
8175 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8176 class_constraint_satisfied = TRUE;
8177 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8178 valuetype_constraint_satisfied = TRUE;
8181 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8182 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8184 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8186 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8188 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8189 valuetype_constraint_satisfied)) {
8194 /*candidate type constraints must be a superset of target's*/
8195 if (tinfo->constraints) {
8196 MonoClass **target_class;
8197 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8198 MonoClass *tc = *target_class;
8201 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8202 * check it's constraints since it satisfy the constraint by itself.
8204 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8207 if (!cinfo->constraints)
8210 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8211 MonoClass *cc = *candidate_class;
8213 if (mono_class_is_assignable_from (tc, cc))
8217 * This happens when we have the following:
8219 * Bar<K> where K : IFace
8220 * Foo<T, U> where T : U where U : IFace
8222 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8225 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8226 if (mono_gparam_is_assignable_from (target, cc))
8230 if (!*candidate_class)
8235 /*candidate itself must have a constraint that satisfy target*/
8236 if (cinfo->constraints) {
8237 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8238 MonoClass *cc = *candidate_class;
8239 if (mono_class_is_assignable_from (target, cc))
8247 * mono_class_is_assignable_from:
8248 * @klass: the class to be assigned to
8249 * @oklass: the source class
8251 * Returns: TRUE if an instance of object oklass can be assigned to an
8252 * instance of object @klass
8255 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8258 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8260 mono_class_init (klass);
8262 if (!oklass->inited)
8263 mono_class_init (oklass);
8265 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8268 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8269 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8271 return mono_gparam_is_assignable_from (klass, oklass);
8274 if (MONO_CLASS_IS_INTERFACE (klass)) {
8275 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8276 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8277 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8281 for (i = 0; constraints [i]; ++i) {
8282 if (mono_class_is_assignable_from (klass, constraints [i]))
8290 /* interface_offsets might not be set for dynamic classes */
8291 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8293 * oklass might be a generic type parameter but they have
8294 * interface_offsets set.
8296 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8297 if (!is_ok (&error)) {
8298 mono_error_cleanup (&error);
8303 if (!oklass->interface_bitmap)
8304 /* Happens with generic instances of not-yet created dynamic types */
8306 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8309 if (mono_class_has_variant_generic_params (klass)) {
8311 mono_class_setup_interfaces (oklass, &error);
8312 if (!mono_error_ok (&error)) {
8313 mono_error_cleanup (&error);
8317 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8318 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8319 MonoClass *iface = oklass->interfaces_packed [i];
8321 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8326 } else if (klass->delegate) {
8327 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8329 }else if (klass->rank) {
8330 MonoClass *eclass, *eoclass;
8332 if (oklass->rank != klass->rank)
8335 /* vectors vs. one dimensional arrays */
8336 if (oklass->byval_arg.type != klass->byval_arg.type)
8339 eclass = klass->cast_class;
8340 eoclass = oklass->cast_class;
8343 * a is b does not imply a[] is b[] when a is a valuetype, and
8344 * b is a reference type.
8347 if (eoclass->valuetype) {
8348 if ((eclass == mono_defaults.enum_class) ||
8349 (eclass == mono_defaults.enum_class->parent) ||
8350 (eclass == mono_defaults.object_class))
8354 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8355 } else if (mono_class_is_nullable (klass)) {
8356 if (mono_class_is_nullable (oklass))
8357 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8359 return mono_class_is_assignable_from (klass->cast_class, oklass);
8360 } else if (klass == mono_defaults.object_class)
8363 return mono_class_has_parent (oklass, klass);
8366 /*Check if @oklass is variant compatible with @klass.*/
8368 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8371 MonoType **klass_argv, **oklass_argv;
8372 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8373 MonoGenericContainer *container = klass_gtd->generic_container;
8375 /*Viable candidates are instances of the same generic interface*/
8376 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8379 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8380 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8382 for (j = 0; j < container->type_argc; ++j) {
8383 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8384 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8386 if (param1_class->valuetype != param2_class->valuetype)
8390 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8391 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8393 if (param1_class != param2_class) {
8394 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8395 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8397 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8398 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8406 /*Check if @candidate implements the interface @target*/
8408 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8412 gboolean is_variant = mono_class_has_variant_generic_params (target);
8414 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8415 if (mono_class_is_variant_compatible_slow (target, candidate))
8420 if (candidate == target)
8423 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8424 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8425 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8427 if (tb && tb->interfaces) {
8428 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8429 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8430 MonoClass *iface_class;
8432 /* we can't realize the type here since it can do pretty much anything. */
8435 iface_class = mono_class_from_mono_type (iface->type);
8436 if (iface_class == target)
8438 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8440 if (mono_class_implement_interface_slow (target, iface_class))
8445 /*setup_interfaces don't mono_class_init anything*/
8446 /*FIXME this doesn't handle primitive type arrays.
8447 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8448 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8450 mono_class_setup_interfaces (candidate, &error);
8451 if (!mono_error_ok (&error)) {
8452 mono_error_cleanup (&error);
8456 for (i = 0; i < candidate->interface_count; ++i) {
8457 if (candidate->interfaces [i] == target)
8460 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8463 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8467 candidate = candidate->parent;
8468 } while (candidate);
8474 * Check if @oklass can be assigned to @klass.
8475 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8478 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8480 if (candidate == target)
8482 if (target == mono_defaults.object_class)
8485 if (mono_class_has_parent (candidate, target))
8488 /*If target is not an interface there is no need to check them.*/
8489 if (MONO_CLASS_IS_INTERFACE (target))
8490 return mono_class_implement_interface_slow (target, candidate);
8492 if (target->delegate && mono_class_has_variant_generic_params (target))
8493 return mono_class_is_variant_compatible (target, candidate, FALSE);
8496 MonoClass *eclass, *eoclass;
8498 if (target->rank != candidate->rank)
8501 /* vectors vs. one dimensional arrays */
8502 if (target->byval_arg.type != candidate->byval_arg.type)
8505 eclass = target->cast_class;
8506 eoclass = candidate->cast_class;
8509 * a is b does not imply a[] is b[] when a is a valuetype, and
8510 * b is a reference type.
8513 if (eoclass->valuetype) {
8514 if ((eclass == mono_defaults.enum_class) ||
8515 (eclass == mono_defaults.enum_class->parent) ||
8516 (eclass == mono_defaults.object_class))
8520 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8522 /*FIXME properly handle nullables */
8523 /*FIXME properly handle (M)VAR */
8528 * mono_class_get_cctor:
8529 * @klass: A MonoClass pointer
8531 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8534 mono_class_get_cctor (MonoClass *klass)
8536 MonoCachedClassInfo cached_info;
8538 if (image_is_dynamic (klass->image)) {
8540 * has_cctor is not set for these classes because mono_class_init () is
8543 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8546 if (!klass->has_cctor)
8549 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8551 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8552 if (!mono_error_ok (&error))
8553 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8557 if (klass->generic_class && !klass->methods)
8558 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8560 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8564 * mono_class_get_finalizer:
8565 * @klass: The MonoClass pointer
8567 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8570 mono_class_get_finalizer (MonoClass *klass)
8572 MonoCachedClassInfo cached_info;
8575 mono_class_init (klass);
8576 if (!mono_class_has_finalizer (klass))
8579 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8581 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8582 if (!mono_error_ok (&error))
8583 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8586 mono_class_setup_vtable (klass);
8587 return klass->vtable [finalize_slot];
8592 * mono_class_needs_cctor_run:
8593 * @klass: the MonoClass pointer
8594 * @caller: a MonoMethod describing the caller
8596 * Determines whenever the class has a static constructor and whenever it
8597 * needs to be called when executing CALLER.
8600 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8604 method = mono_class_get_cctor (klass);
8606 return (method == caller) ? FALSE : TRUE;
8612 * mono_class_array_element_size:
8615 * Returns: The number of bytes an element of type @klass
8616 * uses when stored into an array.
8619 mono_class_array_element_size (MonoClass *klass)
8621 MonoType *type = &klass->byval_arg;
8624 switch (type->type) {
8627 case MONO_TYPE_BOOLEAN:
8631 case MONO_TYPE_CHAR:
8640 case MONO_TYPE_CLASS:
8641 case MONO_TYPE_STRING:
8642 case MONO_TYPE_OBJECT:
8643 case MONO_TYPE_SZARRAY:
8644 case MONO_TYPE_ARRAY:
8645 return sizeof (gpointer);
8650 case MONO_TYPE_VALUETYPE:
8651 if (type->data.klass->enumtype) {
8652 type = mono_class_enum_basetype (type->data.klass);
8653 klass = klass->element_class;
8656 return mono_class_instance_size (klass) - sizeof (MonoObject);
8657 case MONO_TYPE_GENERICINST:
8658 type = &type->data.generic_class->container_class->byval_arg;
8661 case MONO_TYPE_MVAR: {
8664 return mono_type_size (type, &align);
8666 case MONO_TYPE_VOID:
8670 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8676 * mono_array_element_size:
8677 * @ac: pointer to a #MonoArrayClass
8679 * Returns: The size of single array element.
8682 mono_array_element_size (MonoClass *ac)
8684 g_assert (ac->rank);
8685 return ac->sizes.element_size;
8689 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8690 MonoGenericContext *context)
8693 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8694 g_assert (mono_error_ok (&error));
8699 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8700 MonoGenericContext *context, MonoError *error)
8702 mono_error_init (error);
8704 if (image_is_dynamic (image)) {
8705 MonoClass *tmp_handle_class;
8706 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8708 mono_error_assert_ok (error);
8709 g_assert (tmp_handle_class);
8711 *handle_class = tmp_handle_class;
8713 if (tmp_handle_class == mono_defaults.typehandle_class)
8714 return &((MonoClass*)obj)->byval_arg;
8719 switch (token & 0xff000000) {
8720 case MONO_TOKEN_TYPE_DEF:
8721 case MONO_TOKEN_TYPE_REF:
8722 case MONO_TOKEN_TYPE_SPEC: {
8725 *handle_class = mono_defaults.typehandle_class;
8726 type = mono_type_get_checked (image, token, context, error);
8730 mono_class_init (mono_class_from_mono_type (type));
8731 /* We return a MonoType* as handle */
8734 case MONO_TOKEN_FIELD_DEF: {
8736 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8738 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8742 *handle_class = mono_defaults.fieldhandle_class;
8743 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8747 mono_class_init (klass);
8748 return mono_class_get_field (klass, token);
8750 case MONO_TOKEN_METHOD_DEF:
8751 case MONO_TOKEN_METHOD_SPEC: {
8753 meth = mono_get_method_checked (image, token, NULL, context, error);
8755 *handle_class = mono_defaults.methodhandle_class;
8761 case MONO_TOKEN_MEMBER_REF: {
8762 guint32 cols [MONO_MEMBERREF_SIZE];
8764 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8765 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8766 mono_metadata_decode_blob_size (sig, &sig);
8767 if (*sig == 0x6) { /* it's a field */
8769 MonoClassField *field;
8770 field = mono_field_from_token_checked (image, token, &klass, context, error);
8772 *handle_class = mono_defaults.fieldhandle_class;
8776 meth = mono_get_method_checked (image, token, NULL, context, error);
8778 *handle_class = mono_defaults.methodhandle_class;
8783 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8789 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8791 MonoClass *handle_class;
8792 mono_error_init (error);
8793 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8797 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8799 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8802 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8805 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8807 get_cached_class_info = func;
8811 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8813 if (!get_cached_class_info)
8816 return get_cached_class_info (klass, res);
8820 mono_install_get_class_from_name (MonoGetClassFromName func)
8822 get_class_from_name = func;
8826 * mono_class_get_image:
8828 * Use this method to get the `MonoImage*` where this class came from.
8830 * Returns: The image where this class is defined.
8833 mono_class_get_image (MonoClass *klass)
8835 return klass->image;
8839 * mono_class_get_element_class:
8840 * @klass: the MonoClass to act on
8842 * Use this function to get the element class of an array.
8844 * Returns: The element class of an array.
8847 mono_class_get_element_class (MonoClass *klass)
8849 return klass->element_class;
8853 * mono_class_is_valuetype:
8854 * @klass: the MonoClass to act on
8856 * Use this method to determine if the provided `MonoClass*` represents a value type,
8857 * or a reference type.
8859 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8862 mono_class_is_valuetype (MonoClass *klass)
8864 return klass->valuetype;
8868 * mono_class_is_enum:
8869 * @klass: the MonoClass to act on
8871 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8873 * Returns: TRUE if the MonoClass represents an enumeration.
8876 mono_class_is_enum (MonoClass *klass)
8878 return klass->enumtype;
8882 * mono_class_enum_basetype:
8883 * @klass: the MonoClass to act on
8885 * Use this function to get the underlying type for an enumeration value.
8887 * Returns: The underlying type representation for an enumeration.
8890 mono_class_enum_basetype (MonoClass *klass)
8892 if (klass->element_class == klass)
8893 /* SRE or broken types */
8896 return &klass->element_class->byval_arg;
8900 * mono_class_get_parent
8901 * @klass: the MonoClass to act on
8903 * Returns: The parent class for this class.
8906 mono_class_get_parent (MonoClass *klass)
8908 return klass->parent;
8912 * mono_class_get_nesting_type:
8913 * @klass: the MonoClass to act on
8915 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8917 * If the return is NULL, this indicates that this class is not nested.
8919 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8922 mono_class_get_nesting_type (MonoClass *klass)
8924 return klass->nested_in;
8928 * mono_class_get_rank:
8929 * @klass: the MonoClass to act on
8931 * Returns: The rank for the array (the number of dimensions).
8934 mono_class_get_rank (MonoClass *klass)
8940 * mono_class_get_flags:
8941 * @klass: the MonoClass to act on
8943 * The type flags from the TypeDef table from the metadata.
8944 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8947 * Returns: The flags from the TypeDef table.
8950 mono_class_get_flags (MonoClass *klass)
8952 return klass->flags;
8956 * mono_class_get_name
8957 * @klass: the MonoClass to act on
8959 * Returns: The name of the class.
8962 mono_class_get_name (MonoClass *klass)
8968 * mono_class_get_namespace:
8969 * @klass: the MonoClass to act on
8971 * Returns: The namespace of the class.
8974 mono_class_get_namespace (MonoClass *klass)
8976 return klass->name_space;
8980 * mono_class_get_type:
8981 * @klass: the MonoClass to act on
8983 * This method returns the internal Type representation for the class.
8985 * Returns: The MonoType from the class.
8988 mono_class_get_type (MonoClass *klass)
8990 return &klass->byval_arg;
8994 * mono_class_get_type_token:
8995 * @klass: the MonoClass to act on
8997 * This method returns type token for the class.
8999 * Returns: The type token for the class.
9002 mono_class_get_type_token (MonoClass *klass)
9004 return klass->type_token;
9008 * mono_class_get_byref_type:
9009 * @klass: the MonoClass to act on
9014 mono_class_get_byref_type (MonoClass *klass)
9016 return &klass->this_arg;
9020 * mono_class_num_fields:
9021 * @klass: the MonoClass to act on
9023 * Returns: The number of static and instance fields in the class.
9026 mono_class_num_fields (MonoClass *klass)
9028 return klass->field.count;
9032 * mono_class_num_methods:
9033 * @klass: the MonoClass to act on
9035 * Returns: The number of methods in the class.
9038 mono_class_num_methods (MonoClass *klass)
9040 return klass->method.count;
9044 * mono_class_num_properties
9045 * @klass: the MonoClass to act on
9047 * Returns: The number of properties in the class.
9050 mono_class_num_properties (MonoClass *klass)
9052 mono_class_setup_properties (klass);
9054 return klass->ext->property.count;
9058 * mono_class_num_events:
9059 * @klass: the MonoClass to act on
9061 * Returns: The number of events in the class.
9064 mono_class_num_events (MonoClass *klass)
9066 mono_class_setup_events (klass);
9068 return klass->ext->event.count;
9072 * mono_class_get_fields:
9073 * @klass: the MonoClass to act on
9075 * This routine is an iterator routine for retrieving the fields in a class.
9077 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9078 * iterate over all of the elements. When no more values are
9079 * available, the return value is NULL.
9081 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9084 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9086 MonoClassField* field;
9090 mono_class_setup_fields (klass);
9091 if (mono_class_has_failure (klass))
9093 /* start from the first */
9094 if (klass->field.count) {
9095 *iter = &klass->fields [0];
9096 return &klass->fields [0];
9102 field = (MonoClassField *)*iter;
9104 if (field < &klass->fields [klass->field.count]) {
9112 * mono_class_get_methods
9113 * @klass: the MonoClass to act on
9115 * This routine is an iterator routine for retrieving the fields in a class.
9117 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9118 * iterate over all of the elements. When no more values are
9119 * available, the return value is NULL.
9121 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9124 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9126 MonoMethod** method;
9130 mono_class_setup_methods (klass);
9133 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9134 * FIXME we should better report this error to the caller
9136 if (!klass->methods)
9138 /* start from the first */
9139 if (klass->method.count) {
9140 *iter = &klass->methods [0];
9141 return klass->methods [0];
9147 method = (MonoMethod **)*iter;
9149 if (method < &klass->methods [klass->method.count]) {
9157 * mono_class_get_virtual_methods:
9159 * Iterate over the virtual methods of KLASS.
9161 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9164 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9166 MonoMethod** method;
9169 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9171 mono_class_setup_methods (klass);
9173 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9174 * FIXME we should better report this error to the caller
9176 if (!klass->methods)
9178 /* start from the first */
9179 method = &klass->methods [0];
9181 method = (MonoMethod **)*iter;
9184 while (method < &klass->methods [klass->method.count]) {
9185 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9189 if (method < &klass->methods [klass->method.count]) {
9196 /* Search directly in metadata to avoid calling setup_methods () */
9197 MonoMethod *res = NULL;
9203 start_index = GPOINTER_TO_UINT (*iter);
9206 for (i = start_index; i < klass->method.count; ++i) {
9209 /* klass->method.first points into the methodptr table */
9210 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9212 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9216 if (i < klass->method.count) {
9218 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9219 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9221 /* Add 1 here so the if (*iter) check fails */
9222 *iter = GUINT_TO_POINTER (i + 1);
9231 * mono_class_get_properties:
9232 * @klass: the MonoClass to act on
9234 * This routine is an iterator routine for retrieving the properties in a class.
9236 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9237 * iterate over all of the elements. When no more values are
9238 * available, the return value is NULL.
9240 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9243 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9245 MonoProperty* property;
9249 mono_class_setup_properties (klass);
9250 /* start from the first */
9251 if (klass->ext->property.count) {
9252 *iter = &klass->ext->properties [0];
9253 return (MonoProperty *)*iter;
9259 property = (MonoProperty *)*iter;
9261 if (property < &klass->ext->properties [klass->ext->property.count]) {
9263 return (MonoProperty *)*iter;
9269 * mono_class_get_events:
9270 * @klass: the MonoClass to act on
9272 * This routine is an iterator routine for retrieving the properties in a class.
9274 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9275 * iterate over all of the elements. When no more values are
9276 * available, the return value is NULL.
9278 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9281 mono_class_get_events (MonoClass* klass, gpointer *iter)
9287 mono_class_setup_events (klass);
9288 /* start from the first */
9289 if (klass->ext->event.count) {
9290 *iter = &klass->ext->events [0];
9291 return (MonoEvent *)*iter;
9297 event = (MonoEvent *)*iter;
9299 if (event < &klass->ext->events [klass->ext->event.count]) {
9301 return (MonoEvent *)*iter;
9307 * mono_class_get_interfaces
9308 * @klass: the MonoClass to act on
9310 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9312 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9313 * iterate over all of the elements. When no more values are
9314 * available, the return value is NULL.
9316 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9319 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9327 mono_class_init (klass);
9328 if (!klass->interfaces_inited) {
9329 mono_class_setup_interfaces (klass, &error);
9330 if (!mono_error_ok (&error)) {
9331 mono_error_cleanup (&error);
9335 /* start from the first */
9336 if (klass->interface_count) {
9337 *iter = &klass->interfaces [0];
9338 return klass->interfaces [0];
9344 iface = (MonoClass **)*iter;
9346 if (iface < &klass->interfaces [klass->interface_count]) {
9354 setup_nested_types (MonoClass *klass)
9357 GList *classes, *nested_classes, *l;
9360 if (klass->nested_classes_inited)
9363 if (!klass->type_token)
9364 klass->nested_classes_inited = TRUE;
9366 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9370 guint32 cols [MONO_NESTED_CLASS_SIZE];
9371 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9372 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9373 if (!mono_error_ok (&error)) {
9374 /*FIXME don't swallow the error message*/
9375 mono_error_cleanup (&error);
9377 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9381 classes = g_list_prepend (classes, nclass);
9383 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9386 mono_class_alloc_ext (klass);
9388 nested_classes = NULL;
9389 for (l = classes; l; l = l->next)
9390 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9391 g_list_free (classes);
9393 mono_image_lock (klass->image);
9395 mono_memory_barrier ();
9396 if (!klass->nested_classes_inited) {
9397 klass->ext->nested_classes = nested_classes;
9398 mono_memory_barrier ();
9399 klass->nested_classes_inited = TRUE;
9402 mono_image_unlock (klass->image);
9406 * mono_class_get_nested_types
9407 * @klass: the MonoClass to act on
9409 * This routine is an iterator routine for retrieving the nested types of a class.
9410 * This works only if @klass is non-generic, or a generic type definition.
9412 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9413 * iterate over all of the elements. When no more values are
9414 * available, the return value is NULL.
9416 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9419 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9425 if (!klass->nested_classes_inited)
9426 setup_nested_types (klass);
9429 /* start from the first */
9430 if (klass->ext && klass->ext->nested_classes) {
9431 *iter = klass->ext->nested_classes;
9432 return (MonoClass *)klass->ext->nested_classes->data;
9434 /* no nested types */
9438 item = (GList *)*iter;
9442 return (MonoClass *)item->data;
9449 * mono_class_is_delegate
9450 * @klass: the MonoClass to act on
9452 * Returns: TRUE if the MonoClass represents a System.Delegate.
9455 mono_class_is_delegate (MonoClass *klass)
9457 return klass->delegate;
9461 * mono_class_implements_interface
9462 * @klass: The MonoClass to act on
9463 * @interface: The interface to check if @klass implements.
9465 * Returns: TRUE if @klass implements @interface.
9468 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9470 return mono_class_is_assignable_from (iface, klass);
9474 * mono_field_get_name:
9475 * @field: the MonoClassField to act on
9477 * Returns: The name of the field.
9480 mono_field_get_name (MonoClassField *field)
9486 * mono_field_get_type:
9487 * @field: the MonoClassField to act on
9489 * Returns: MonoType of the field.
9492 mono_field_get_type (MonoClassField *field)
9495 MonoType *type = mono_field_get_type_checked (field, &error);
9496 if (!mono_error_ok (&error)) {
9497 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9498 mono_error_cleanup (&error);
9505 * mono_field_get_type_checked:
9506 * @field: the MonoClassField to act on
9507 * @error: used to return any erro found while retrieving @field type
9509 * Returns: MonoType of the field.
9512 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9514 mono_error_init (error);
9516 mono_field_resolve_type (field, error);
9521 * mono_field_get_parent:
9522 * @field: the MonoClassField to act on
9524 * Returns: MonoClass where the field was defined.
9527 mono_field_get_parent (MonoClassField *field)
9529 return field->parent;
9533 * mono_field_get_flags;
9534 * @field: the MonoClassField to act on
9536 * The metadata flags for a field are encoded using the
9537 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9539 * Returns: The flags for the field.
9542 mono_field_get_flags (MonoClassField *field)
9545 return mono_field_resolve_flags (field);
9546 return field->type->attrs;
9550 * mono_field_get_offset:
9551 * @field: the MonoClassField to act on
9553 * Returns: The field offset.
9556 mono_field_get_offset (MonoClassField *field)
9558 return field->offset;
9562 mono_field_get_rva (MonoClassField *field)
9566 MonoClass *klass = field->parent;
9567 MonoFieldDefaultValue *field_def_values;
9569 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9571 if (!klass->ext || !klass->ext->field_def_values) {
9572 mono_class_alloc_ext (klass);
9574 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9576 mono_image_lock (klass->image);
9577 if (!klass->ext->field_def_values)
9578 klass->ext->field_def_values = field_def_values;
9579 mono_image_unlock (klass->image);
9582 field_index = mono_field_get_index (field);
9584 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9585 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9587 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9588 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9591 return klass->ext->field_def_values [field_index].data;
9595 * mono_field_get_data:
9596 * @field: the MonoClassField to act on
9598 * Returns: A pointer to the metadata constant value or to the field
9599 * data if it has an RVA flag.
9602 mono_field_get_data (MonoClassField *field)
9604 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9605 MonoTypeEnum def_type;
9607 return mono_class_get_field_default_value (field, &def_type);
9608 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9609 return mono_field_get_rva (field);
9616 * mono_property_get_name:
9617 * @prop: the MonoProperty to act on
9619 * Returns: The name of the property
9622 mono_property_get_name (MonoProperty *prop)
9628 * mono_property_get_set_method
9629 * @prop: the MonoProperty to act on.
9631 * Returns: The setter method of the property (A MonoMethod)
9634 mono_property_get_set_method (MonoProperty *prop)
9640 * mono_property_get_get_method
9641 * @prop: the MonoProperty to act on.
9643 * Returns: The setter method of the property (A MonoMethod)
9646 mono_property_get_get_method (MonoProperty *prop)
9652 * mono_property_get_parent:
9653 * @prop: the MonoProperty to act on.
9655 * Returns: The MonoClass where the property was defined.
9658 mono_property_get_parent (MonoProperty *prop)
9660 return prop->parent;
9664 * mono_property_get_flags:
9665 * @prop: the MonoProperty to act on.
9667 * The metadata flags for a property are encoded using the
9668 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9670 * Returns: The flags for the property.
9673 mono_property_get_flags (MonoProperty *prop)
9679 * mono_event_get_name:
9680 * @event: the MonoEvent to act on
9682 * Returns: The name of the event.
9685 mono_event_get_name (MonoEvent *event)
9691 * mono_event_get_add_method:
9692 * @event: The MonoEvent to act on.
9694 * Returns: The @add' method for the event (a MonoMethod).
9697 mono_event_get_add_method (MonoEvent *event)
9703 * mono_event_get_remove_method:
9704 * @event: The MonoEvent to act on.
9706 * Returns: The @remove method for the event (a MonoMethod).
9709 mono_event_get_remove_method (MonoEvent *event)
9711 return event->remove;
9715 * mono_event_get_raise_method:
9716 * @event: The MonoEvent to act on.
9718 * Returns: The @raise method for the event (a MonoMethod).
9721 mono_event_get_raise_method (MonoEvent *event)
9723 return event->raise;
9727 * mono_event_get_parent:
9728 * @event: the MonoEvent to act on.
9730 * Returns: The MonoClass where the event is defined.
9733 mono_event_get_parent (MonoEvent *event)
9735 return event->parent;
9739 * mono_event_get_flags
9740 * @event: the MonoEvent to act on.
9742 * The metadata flags for an event are encoded using the
9743 * EVENT_* constants. See the tabledefs.h file for details.
9745 * Returns: The flags for the event.
9748 mono_event_get_flags (MonoEvent *event)
9750 return event->attrs;
9754 * mono_class_get_method_from_name:
9755 * @klass: where to look for the method
9756 * @name: name of the method
9757 * @param_count: number of parameters. -1 for any number.
9759 * Obtains a MonoMethod with a given name and number of parameters.
9760 * It only works if there are no multiple signatures for any given method name.
9763 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9765 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9769 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9771 MonoMethod *res = NULL;
9774 /* Search directly in the metadata to avoid calling setup_methods () */
9775 for (i = 0; i < klass->method.count; ++i) {
9777 guint32 cols [MONO_METHOD_SIZE];
9779 MonoMethodSignature *sig;
9781 /* klass->method.first points into the methodptr table */
9782 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9784 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9785 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9787 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9790 if (param_count == -1) {
9794 sig = mono_method_signature_checked (method, &error);
9796 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9799 if (sig->param_count == param_count) {
9810 * mono_class_get_method_from_name_flags:
9811 * @klass: where to look for the method
9812 * @name_space: name of the method
9813 * @param_count: number of parameters. -1 for any number.
9814 * @flags: flags which must be set in the method
9816 * Obtains a MonoMethod with a given name and number of parameters.
9817 * It only works if there are no multiple signatures for any given method name.
9820 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9822 MonoMethod *res = NULL;
9825 mono_class_init (klass);
9827 if (klass->generic_class && !klass->methods) {
9828 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9831 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9832 if (!mono_error_ok (&error))
9833 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9838 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9839 mono_class_setup_methods (klass);
9841 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9842 See mono/tests/array_load_exception.il
9843 FIXME we should better report this error to the caller
9845 if (!klass->methods)
9847 for (i = 0; i < klass->method.count; ++i) {
9848 MonoMethod *method = klass->methods [i];
9850 if (method->name[0] == name [0] &&
9851 !strcmp (name, method->name) &&
9852 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9853 ((method->flags & flags) == flags)) {
9860 res = find_method_in_metadata (klass, name, param_count, flags);
9867 * mono_class_set_failure:
9868 * @klass: class in which the failure was detected
9869 * @ex_type: the kind of exception/error to be thrown (later)
9870 * @ex_data: exception data (specific to each type of exception/error)
9872 * Keep a detected failure informations in the class for later processing.
9873 * Note that only the first failure is kept.
9875 * LOCKING: Acquires the loader lock.
9878 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9880 g_assert (boxed_error != NULL);
9882 if (mono_class_has_failure (klass))
9885 mono_loader_lock ();
9886 klass->has_failure = 1;
9887 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9888 mono_loader_unlock ();
9894 mono_class_has_failure (const MonoClass *klass)
9896 g_assert (klass != NULL);
9897 return klass->has_failure != 0;
9902 * mono_class_set_type_load_failure:
9903 * @klass: class in which the failure was detected
9904 * @fmt: Printf-style error message string.
9906 * Collect detected failure informaion in the class for later processing.
9907 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9908 * Note that only the first failure is kept.
9910 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9912 * LOCKING: Acquires the loader lock.
9915 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9917 MonoError prepare_error;
9920 if (mono_class_has_failure (klass))
9923 mono_error_init (&prepare_error);
9925 va_start (args, fmt);
9926 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9929 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9930 mono_error_cleanup (&prepare_error);
9931 return mono_class_set_failure (klass, box);
9935 * mono_class_get_exception_data:
9937 * Return the exception_data property of KLASS.
9939 * LOCKING: Acquires the loader lock.
9942 mono_class_get_exception_data (const MonoClass *klass)
9944 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9948 * mono_classes_init:
9950 * Initialize the resources used by this module.
9953 mono_classes_init (void)
9955 mono_os_mutex_init (&classes_mutex);
9957 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9959 mono_counters_register ("Inflated methods size",
9960 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9961 mono_counters_register ("Inflated classes",
9962 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9963 mono_counters_register ("Inflated classes size",
9964 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9965 mono_counters_register ("MonoClass size",
9966 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9967 mono_counters_register ("MonoClassExt size",
9968 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9972 * mono_classes_cleanup:
9974 * Free the resources used by this module.
9977 mono_classes_cleanup (void)
9979 mono_native_tls_free (setup_fields_tls_id);
9981 if (global_interface_bitset)
9982 mono_bitset_free (global_interface_bitset);
9983 global_interface_bitset = NULL;
9984 mono_os_mutex_destroy (&classes_mutex);
9988 * mono_class_get_exception_for_failure:
9989 * @klass: class in which the failure was detected
9991 * Return a constructed MonoException than the caller can then throw
9992 * using mono_raise_exception - or NULL if no failure is present (or
9993 * doesn't result in an exception).
9996 mono_class_get_exception_for_failure (MonoClass *klass)
9998 if (!mono_class_has_failure (klass))
10000 MonoError unboxed_error;
10001 mono_error_init (&unboxed_error);
10002 mono_error_set_for_class_failure (&unboxed_error, klass);
10003 return mono_error_convert_to_exception (&unboxed_error);
10007 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10009 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10010 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10012 if (outer_klass == inner_klass)
10014 inner_klass = inner_klass->nested_in;
10015 } while (inner_klass);
10020 mono_class_get_generic_type_definition (MonoClass *klass)
10022 return klass->generic_class ? klass->generic_class->container_class : klass;
10026 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10028 * Generic instantiations are ignored for all super types of @klass.
10030 * Visibility checks ignoring generic instantiations.
10033 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10036 klass = mono_class_get_generic_type_definition (klass);
10037 parent = mono_class_get_generic_type_definition (parent);
10038 mono_class_setup_supertypes (klass);
10040 for (i = 0; i < klass->idepth; ++i) {
10041 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10047 * Subtype can only access parent members with family protection if the site object
10048 * is subclass of Subtype. For example:
10049 * class A { protected int x; }
10051 * void valid_access () {
10055 * void invalid_access () {
10062 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10064 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10067 if (context_klass == NULL)
10069 /*if access_klass is not member_klass context_klass must be type compat*/
10070 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10076 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10079 if (accessing == accessed)
10081 if (!accessed || !accessing)
10084 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10085 * anywhere so untrusted friends are not safe to access platform's code internals */
10086 if (mono_security_core_clr_enabled ()) {
10087 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10091 mono_assembly_load_friends (accessed);
10092 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10093 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10094 /* Be conservative with checks */
10095 if (!friend_->name)
10097 if (strcmp (accessing->aname.name, friend_->name))
10099 if (friend_->public_key_token [0]) {
10100 if (!accessing->aname.public_key_token [0])
10102 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10111 * If klass is a generic type or if it is derived from a generic type, return the
10112 * MonoClass of the generic definition
10113 * Returns NULL if not found
10116 get_generic_definition_class (MonoClass *klass)
10119 if (klass->generic_class && klass->generic_class->container_class)
10120 return klass->generic_class->container_class;
10121 klass = klass->parent;
10127 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10130 for (i = 0; i < ginst->type_argc; ++i) {
10131 MonoType *type = ginst->type_argv[i];
10132 switch (type->type) {
10133 case MONO_TYPE_SZARRAY:
10134 if (!can_access_type (access_klass, type->data.klass))
10137 case MONO_TYPE_ARRAY:
10138 if (!can_access_type (access_klass, type->data.array->eklass))
10141 case MONO_TYPE_PTR:
10142 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10145 case MONO_TYPE_CLASS:
10146 case MONO_TYPE_VALUETYPE:
10147 case MONO_TYPE_GENERICINST:
10148 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10158 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10162 if (access_klass == member_klass)
10165 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10168 if (access_klass->element_class && !access_klass->enumtype)
10169 access_klass = access_klass->element_class;
10171 if (member_klass->element_class && !member_klass->enumtype)
10172 member_klass = member_klass->element_class;
10174 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10176 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10179 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10182 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10185 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10188 /*Non nested type with nested visibility. We just fail it.*/
10189 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10192 switch (access_level) {
10193 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10194 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10196 case TYPE_ATTRIBUTE_PUBLIC:
10199 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10202 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10203 return is_nesting_type (member_klass, access_klass);
10205 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10206 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10208 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10209 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10211 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10212 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10213 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10215 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10216 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10217 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10222 /* FIXME: check visibility of type, too */
10224 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10226 MonoClass *member_generic_def;
10227 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10230 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10231 access_klass->generic_container) &&
10232 (member_generic_def = get_generic_definition_class (member_klass))) {
10233 MonoClass *access_container;
10235 if (access_klass->generic_container)
10236 access_container = access_klass;
10238 access_container = access_klass->generic_class->container_class;
10240 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10244 /* Partition I 8.5.3.2 */
10245 /* the access level values are the same for fields and methods */
10246 switch (access_level) {
10247 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10248 /* same compilation unit */
10249 return access_klass->image == member_klass->image;
10250 case FIELD_ATTRIBUTE_PRIVATE:
10251 return access_klass == member_klass;
10252 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10253 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10254 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10257 case FIELD_ATTRIBUTE_ASSEMBLY:
10258 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10259 case FIELD_ATTRIBUTE_FAMILY:
10260 if (is_valid_family_access (access_klass, member_klass, context_klass))
10263 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10264 if (is_valid_family_access (access_klass, member_klass, context_klass))
10266 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10267 case FIELD_ATTRIBUTE_PUBLIC:
10274 * mono_method_can_access_field:
10275 * @method: Method that will attempt to access the field
10276 * @field: the field to access
10278 * Used to determine if a method is allowed to access the specified field.
10280 * Returns: TRUE if the given @method is allowed to access the @field while following
10281 * the accessibility rules of the CLI.
10284 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10286 /* FIXME: check all overlapping fields */
10287 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10289 MonoClass *nested = method->klass->nested_in;
10291 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10294 nested = nested->nested_in;
10301 * mono_method_can_access_method:
10302 * @method: Method that will attempt to access the other method
10303 * @called: the method that we want to probe for accessibility.
10305 * Used to determine if the @method is allowed to access the specified @called method.
10307 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10308 * the accessibility rules of the CLI.
10311 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10313 method = mono_method_get_method_definition (method);
10314 called = mono_method_get_method_definition (called);
10315 return mono_method_can_access_method_full (method, called, NULL);
10319 * mono_method_can_access_method_full:
10320 * @method: The caller method
10321 * @called: The called method
10322 * @context_klass: The static type on stack of the owner @called object used
10324 * This function must be used with instance calls, as they have more strict family accessibility.
10325 * It can be used with static methods, but context_klass should be NULL.
10327 * Returns: TRUE if caller have proper visibility and acessibility to @called
10330 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10332 /* Wrappers are except from access checks */
10333 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10336 MonoClass *access_class = method->klass;
10337 MonoClass *member_class = called->klass;
10338 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10340 MonoClass *nested = access_class->nested_in;
10342 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10345 nested = nested->nested_in;
10352 can = can_access_type (access_class, member_class);
10354 MonoClass *nested = access_class->nested_in;
10356 can = can_access_type (nested, member_class);
10359 nested = nested->nested_in;
10366 if (called->is_inflated) {
10367 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10368 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10377 * mono_method_can_access_field_full:
10378 * @method: The caller method
10379 * @field: The accessed field
10380 * @context_klass: The static type on stack of the owner @field object used
10382 * This function must be used with instance fields, as they have more strict family accessibility.
10383 * It can be used with static fields, but context_klass should be NULL.
10385 * Returns: TRUE if caller have proper visibility and acessibility to @field
10388 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10390 MonoClass *access_class = method->klass;
10391 MonoClass *member_class = field->parent;
10392 /* FIXME: check all overlapping fields */
10393 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10395 MonoClass *nested = access_class->nested_in;
10397 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10400 nested = nested->nested_in;
10407 can = can_access_type (access_class, member_class);
10409 MonoClass *nested = access_class->nested_in;
10411 can = can_access_type (nested, member_class);
10414 nested = nested->nested_in;
10424 * mono_class_can_access_class:
10425 * @source_class: The source class
10426 * @target_class: The accessed class
10428 * This function returns is @target_class is visible to @source_class
10430 * Returns: TRUE if source have proper visibility and acessibility to target
10433 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10435 return can_access_type (source_class, target_class);
10439 * mono_type_is_valid_enum_basetype:
10440 * @type: The MonoType to check
10442 * Returns: TRUE if the type can be used as the basetype of an enum
10444 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10445 switch (type->type) {
10448 case MONO_TYPE_BOOLEAN:
10451 case MONO_TYPE_CHAR:
10465 * mono_class_is_valid_enum:
10466 * @klass: An enum class to be validated
10468 * This method verify the required properties an enum should have.
10470 * Returns: TRUE if the informed enum class is valid
10472 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10473 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10474 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10476 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10477 MonoClassField * field;
10478 gpointer iter = NULL;
10479 gboolean found_base_field = FALSE;
10481 g_assert (klass->enumtype);
10482 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10483 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10487 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10490 while ((field = mono_class_get_fields (klass, &iter))) {
10491 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10492 if (found_base_field)
10494 found_base_field = TRUE;
10495 if (!mono_type_is_valid_enum_basetype (field->type))
10500 if (!found_base_field)
10503 if (klass->method.count > 0)
10510 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10512 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10516 * mono_class_setup_interface_id:
10518 * Initializes MonoClass::interface_id if required.
10520 * LOCKING: Acquires the loader lock.
10523 mono_class_setup_interface_id (MonoClass *klass)
10525 mono_loader_lock ();
10526 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10527 klass->interface_id = mono_get_unique_iid (klass);
10528 mono_loader_unlock ();
10532 * mono_class_alloc_ext:
10534 * Allocate klass->ext if not already done.
10537 mono_class_alloc_ext (MonoClass *klass)
10544 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10545 mono_image_lock (klass->image);
10546 mono_memory_barrier ();
10549 class_ext_size += sizeof (MonoClassExt);
10550 mono_image_unlock (klass->image);
10554 * mono_class_setup_interfaces:
10556 * Initialize klass->interfaces/interfaces_count.
10557 * LOCKING: Acquires the loader lock.
10558 * This function can fail the type.
10561 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10563 int i, interface_count;
10564 MonoClass **interfaces;
10566 mono_error_init (error);
10568 if (klass->interfaces_inited)
10571 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10572 MonoType *args [1];
10574 /* generic IList, ICollection, IEnumerable */
10575 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10576 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10578 args [0] = &klass->element_class->byval_arg;
10579 interfaces [0] = mono_class_bind_generic_parameters (
10580 mono_defaults.generic_ilist_class, 1, args, FALSE);
10581 if (interface_count > 1)
10582 interfaces [1] = mono_class_bind_generic_parameters (
10583 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10584 } else if (klass->generic_class) {
10585 MonoClass *gklass = klass->generic_class->container_class;
10587 mono_class_setup_interfaces (gklass, error);
10588 if (!mono_error_ok (error)) {
10589 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10593 interface_count = gklass->interface_count;
10594 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10595 for (i = 0; i < interface_count; i++) {
10596 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10597 if (!mono_error_ok (error)) {
10598 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10603 interface_count = 0;
10607 mono_image_lock (klass->image);
10609 if (!klass->interfaces_inited) {
10610 klass->interface_count = interface_count;
10611 klass->interfaces = interfaces;
10613 mono_memory_barrier ();
10615 klass->interfaces_inited = TRUE;
10618 mono_image_unlock (klass->image);
10622 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10624 MonoClass *klass = field->parent;
10625 MonoImage *image = klass->image;
10626 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10627 int field_idx = field - klass->fields;
10629 mono_error_init (error);
10632 MonoClassField *gfield = >d->fields [field_idx];
10633 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10634 if (!mono_error_ok (error)) {
10635 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10638 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10639 if (!mono_error_ok (error)) {
10640 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10644 guint32 cols [MONO_FIELD_SIZE];
10645 MonoGenericContainer *container = NULL;
10646 int idx = klass->field.first + field_idx;
10648 /*FIXME, in theory we do not lazy load SRE fields*/
10649 g_assert (!image_is_dynamic (image));
10651 if (klass->generic_container) {
10652 container = klass->generic_container;
10654 container = gtd->generic_container;
10655 g_assert (container);
10658 /* klass->field.first and idx points into the fieldptr table */
10659 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10661 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10662 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10663 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10667 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10669 mono_metadata_decode_value (sig, &sig);
10670 /* FIELD signature == 0x06 */
10671 g_assert (*sig == 0x06);
10673 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10674 if (!field->type) {
10675 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10681 mono_field_resolve_flags (MonoClassField *field)
10683 MonoClass *klass = field->parent;
10684 MonoImage *image = klass->image;
10685 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10686 int field_idx = field - klass->fields;
10690 MonoClassField *gfield = >d->fields [field_idx];
10691 return mono_field_get_flags (gfield);
10693 int idx = klass->field.first + field_idx;
10695 /*FIXME, in theory we do not lazy load SRE fields*/
10696 g_assert (!image_is_dynamic (image));
10698 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10703 * mono_class_get_fields_lazy:
10704 * @klass: the MonoClass to act on
10706 * This routine is an iterator routine for retrieving the fields in a class.
10707 * Only minimal information about fields are loaded. Accessors must be used
10708 * for all MonoClassField returned.
10710 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10711 * iterate over all of the elements. When no more values are
10712 * available, the return value is NULL.
10714 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10717 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10719 MonoClassField* field;
10723 mono_class_setup_basic_field_info (klass);
10724 if (!klass->fields)
10726 /* start from the first */
10727 if (klass->field.count) {
10728 *iter = &klass->fields [0];
10729 return (MonoClassField *)*iter;
10735 field = (MonoClassField *)*iter;
10737 if (field < &klass->fields [klass->field.count]) {
10739 return (MonoClassField *)*iter;
10745 mono_class_full_name (MonoClass *klass)
10747 return mono_type_full_name (&klass->byval_arg);
10750 /* Declare all shared lazy type lookup functions */
10751 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)