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 klass->fields [i].offset = field_offsets [i];
2080 mono_memory_barrier ();
2081 klass->size_inited = 1;
2082 mono_loader_unlock ();
2085 * Compute static field layout and size
2086 * Static fields can reference the class itself, so this has to be
2087 * done after instance_size etc. are initialized.
2090 for (i = 0; i < top; i++) {
2094 field = &klass->fields [i];
2096 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2098 if (mono_field_is_deleted (field))
2101 if (mono_type_has_exceptions (field->type)) {
2102 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2106 has_static_fields = TRUE;
2108 size = mono_type_size (field->type, &align);
2109 field_offsets [i] = class_size;
2110 /*align is always non-zero here*/
2111 field_offsets [i] += align - 1;
2112 field_offsets [i] &= ~(align - 1);
2113 class_size = field_offsets [i] + size;
2116 if (has_static_fields && class_size == 0)
2117 /* Simplify code which depends on class_size != 0 if the class has static fields */
2120 /* Compute klass->has_static_refs */
2121 has_static_refs = FALSE;
2122 for (i = 0; i < top; i++) {
2125 field = &klass->fields [i];
2127 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2128 ftype = mono_type_get_underlying_type (field->type);
2129 ftype = mono_type_get_basic_type_from_generic (ftype);
2130 if (type_has_references (klass, ftype))
2131 has_static_refs = TRUE;
2135 /*valuetypes can't be neither bigger than 1Mb or empty. */
2136 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2137 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2139 /* Publish the data */
2140 mono_loader_lock ();
2142 klass->sizes.class_size = class_size;
2143 klass->has_static_refs = has_static_refs;
2144 for (i = 0; i < top; ++i) {
2145 field = &klass->fields [i];
2147 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2148 field->offset = field_offsets [i];
2151 mono_memory_barrier ();
2152 klass->fields_inited = 1;
2153 mono_loader_unlock ();
2155 g_free (field_offsets);
2159 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2163 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2164 method->klass = klass;
2165 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2166 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2167 method->signature = sig;
2168 method->name = name;
2171 if (name [0] == '.') {
2172 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2174 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2180 * mono_class_setup_methods:
2183 * Initializes the 'methods' array in CLASS.
2184 * Calling this method should be avoided if possible since it allocates a lot
2185 * of long-living MonoMethod structures.
2186 * Methods belonging to an interface are assigned a sequential slot starting
2189 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2192 mono_class_setup_methods (MonoClass *klass)
2195 MonoMethod **methods;
2200 if (klass->generic_class) {
2202 MonoClass *gklass = klass->generic_class->container_class;
2204 mono_class_init (gklass);
2205 if (!mono_class_has_failure (gklass))
2206 mono_class_setup_methods (gklass);
2207 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2210 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2211 count = gklass->method.count;
2212 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2214 for (i = 0; i < count; i++) {
2215 methods [i] = mono_class_inflate_generic_method_full_checked (
2216 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2217 if (!mono_error_ok (&error)) {
2218 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2219 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2222 mono_error_cleanup (&error);
2226 } else if (klass->rank) {
2228 MonoMethod *amethod;
2229 MonoMethodSignature *sig;
2230 int count_generic = 0, first_generic = 0;
2232 gboolean jagged_ctor = FALSE;
2234 count = 3 + (klass->rank > 1? 2: 1);
2236 mono_class_setup_interfaces (klass, &error);
2237 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2239 if (klass->rank == 1 && klass->element_class->rank) {
2241 klass->method.count ++;
2244 if (klass->interface_count) {
2245 count_generic = generic_array_methods (klass);
2246 first_generic = count;
2247 count += klass->interface_count * count_generic;
2250 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2252 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2253 sig->ret = &mono_defaults.void_class->byval_arg;
2254 sig->pinvoke = TRUE;
2255 sig->hasthis = TRUE;
2256 for (i = 0; i < klass->rank; ++i)
2257 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2259 amethod = create_array_method (klass, ".ctor", sig);
2260 methods [method_num++] = amethod;
2261 if (klass->rank > 1) {
2262 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2263 sig->ret = &mono_defaults.void_class->byval_arg;
2264 sig->pinvoke = TRUE;
2265 sig->hasthis = TRUE;
2266 for (i = 0; i < klass->rank * 2; ++i)
2267 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2269 amethod = create_array_method (klass, ".ctor", sig);
2270 methods [method_num++] = amethod;
2274 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2275 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2276 sig->ret = &mono_defaults.void_class->byval_arg;
2277 sig->pinvoke = TRUE;
2278 sig->hasthis = TRUE;
2279 for (i = 0; i < klass->rank + 1; ++i)
2280 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2281 amethod = create_array_method (klass, ".ctor", sig);
2282 methods [method_num++] = amethod;
2285 /* element Get (idx11, [idx2, ...]) */
2286 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2287 sig->ret = &klass->element_class->byval_arg;
2288 sig->pinvoke = TRUE;
2289 sig->hasthis = TRUE;
2290 for (i = 0; i < klass->rank; ++i)
2291 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2292 amethod = create_array_method (klass, "Get", sig);
2293 methods [method_num++] = amethod;
2294 /* element& Address (idx11, [idx2, ...]) */
2295 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2296 sig->ret = &klass->element_class->this_arg;
2297 sig->pinvoke = TRUE;
2298 sig->hasthis = TRUE;
2299 for (i = 0; i < klass->rank; ++i)
2300 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2301 amethod = create_array_method (klass, "Address", sig);
2302 methods [method_num++] = amethod;
2303 /* void Set (idx11, [idx2, ...], element) */
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2305 sig->ret = &mono_defaults.void_class->byval_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2310 sig->params [i] = &klass->element_class->byval_arg;
2311 amethod = create_array_method (klass, "Set", sig);
2312 methods [method_num++] = amethod;
2314 for (i = 0; i < klass->interface_count; i++)
2315 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2319 count = klass->method.count;
2320 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2321 for (i = 0; i < count; ++i) {
2322 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2323 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2325 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2326 mono_error_cleanup (&error);
2331 if (MONO_CLASS_IS_INTERFACE (klass)) {
2333 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2334 for (i = 0; i < count; ++i) {
2335 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2336 methods [i]->slot = slot++;
2340 mono_image_lock (klass->image);
2342 if (!klass->methods) {
2343 klass->method.count = count;
2345 /* Needed because of the double-checking locking pattern */
2346 mono_memory_barrier ();
2348 klass->methods = methods;
2351 mono_image_unlock (klass->image);
2355 * mono_class_get_method_by_index:
2357 * Returns klass->methods [index], initializing klass->methods if neccesary.
2359 * LOCKING: Acquires the loader lock.
2362 mono_class_get_method_by_index (MonoClass *klass, int index)
2365 /* Avoid calling setup_methods () if possible */
2366 if (klass->generic_class && !klass->methods) {
2367 MonoClass *gklass = klass->generic_class->container_class;
2370 m = mono_class_inflate_generic_method_full_checked (
2371 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2372 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2374 * If setup_methods () is called later for this class, no duplicates are created,
2375 * since inflate_generic_method guarantees that only one instance of a method
2376 * is created for each context.
2379 mono_class_setup_methods (klass);
2380 g_assert (m == klass->methods [index]);
2384 mono_class_setup_methods (klass);
2385 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2387 g_assert (index >= 0 && index < klass->method.count);
2388 return klass->methods [index];
2393 * mono_class_get_inflated_method:
2395 * Given an inflated class CLASS and a method METHOD which should be a method of
2396 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2399 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2401 MonoClass *gklass = klass->generic_class->container_class;
2404 g_assert (method->klass == gklass);
2406 mono_class_setup_methods (gklass);
2407 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2409 for (i = 0; i < gklass->method.count; ++i) {
2410 if (gklass->methods [i] == method) {
2411 if (klass->methods) {
2412 return klass->methods [i];
2415 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2416 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2426 * mono_class_get_vtable_entry:
2428 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2429 * LOCKING: Acquires the loader lock.
2432 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2436 if (klass->rank == 1) {
2438 * szarrays do not overwrite any methods of Array, so we can avoid
2439 * initializing their vtables in some cases.
2441 mono_class_setup_vtable (klass->parent);
2442 if (offset < klass->parent->vtable_size)
2443 return klass->parent->vtable [offset];
2446 if (klass->generic_class) {
2448 MonoClass *gklass = klass->generic_class->container_class;
2449 mono_class_setup_vtable (gklass);
2450 m = gklass->vtable [offset];
2452 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2453 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2455 mono_class_setup_vtable (klass);
2456 if (mono_class_has_failure (klass))
2458 m = klass->vtable [offset];
2465 * mono_class_get_vtable_size:
2467 * Return the vtable size for KLASS.
2470 mono_class_get_vtable_size (MonoClass *klass)
2472 mono_class_setup_vtable (klass);
2474 return klass->vtable_size;
2478 * mono_class_setup_properties:
2480 * Initialize klass->ext.property and klass->ext.properties.
2482 * This method can fail the class.
2485 mono_class_setup_properties (MonoClass *klass)
2487 guint startm, endm, i, j;
2488 guint32 cols [MONO_PROPERTY_SIZE];
2489 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2490 MonoProperty *properties;
2494 if (klass->ext && klass->ext->properties)
2497 if (klass->generic_class) {
2498 MonoClass *gklass = klass->generic_class->container_class;
2500 mono_class_init (gklass);
2501 mono_class_setup_properties (gklass);
2502 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2505 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2507 for (i = 0; i < gklass->ext->property.count; i++) {
2509 MonoProperty *prop = &properties [i];
2511 *prop = gklass->ext->properties [i];
2514 prop->get = mono_class_inflate_generic_method_full_checked (
2515 prop->get, klass, mono_class_get_context (klass), &error);
2517 prop->set = mono_class_inflate_generic_method_full_checked (
2518 prop->set, klass, mono_class_get_context (klass), &error);
2520 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2521 prop->parent = klass;
2524 first = gklass->ext->property.first;
2525 count = gklass->ext->property.count;
2527 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2528 count = last - first;
2531 mono_class_setup_methods (klass);
2532 if (mono_class_has_failure (klass))
2536 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2537 for (i = first; i < last; ++i) {
2538 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2539 properties [i - first].parent = klass;
2540 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2541 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2543 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2544 for (j = startm; j < endm; ++j) {
2547 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2549 if (klass->image->uncompressed_metadata) {
2551 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2552 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2553 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2555 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2558 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2559 case METHOD_SEMANTIC_SETTER:
2560 properties [i - first].set = method;
2562 case METHOD_SEMANTIC_GETTER:
2563 properties [i - first].get = method;
2572 mono_class_alloc_ext (klass);
2574 mono_image_lock (klass->image);
2576 if (klass->ext->properties) {
2577 /* We leak 'properties' which was allocated from the image mempool */
2578 mono_image_unlock (klass->image);
2582 klass->ext->property.first = first;
2583 klass->ext->property.count = count;
2585 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2586 mono_memory_barrier ();
2588 /* Leave this assignment as the last op in the function */
2589 klass->ext->properties = properties;
2591 mono_image_unlock (klass->image);
2595 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2597 MonoMethod **om, **retval;
2600 for (om = methods, count = 0; *om; ++om, ++count)
2603 retval = g_new0 (MonoMethod*, count + 1);
2605 for (om = methods, count = 0; *om; ++om, ++count) {
2607 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2608 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2614 /*This method can fail the class.*/
2616 mono_class_setup_events (MonoClass *klass)
2619 guint startm, endm, i, j;
2620 guint32 cols [MONO_EVENT_SIZE];
2621 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2625 if (klass->ext && klass->ext->events)
2628 if (klass->generic_class) {
2629 MonoClass *gklass = klass->generic_class->container_class;
2630 MonoGenericContext *context = NULL;
2632 mono_class_setup_events (gklass);
2633 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2636 first = gklass->ext->event.first;
2637 count = gklass->ext->event.count;
2639 events = mono_class_new0 (klass, MonoEvent, count);
2642 context = mono_class_get_context (klass);
2644 for (i = 0; i < count; i++) {
2646 MonoEvent *event = &events [i];
2647 MonoEvent *gevent = &gklass->ext->events [i];
2649 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2651 event->parent = klass;
2652 event->name = gevent->name;
2653 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2654 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2655 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2656 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2657 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2658 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2660 #ifndef MONO_SMALL_CONFIG
2661 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2663 event->attrs = gevent->attrs;
2666 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2667 count = last - first;
2670 mono_class_setup_methods (klass);
2671 if (mono_class_has_failure (klass)) {
2676 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2677 for (i = first; i < last; ++i) {
2678 MonoEvent *event = &events [i - first];
2680 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2681 event->parent = klass;
2682 event->attrs = cols [MONO_EVENT_FLAGS];
2683 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2685 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2686 for (j = startm; j < endm; ++j) {
2689 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2691 if (klass->image->uncompressed_metadata) {
2693 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2694 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2695 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2697 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2700 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2701 case METHOD_SEMANTIC_ADD_ON:
2702 event->add = method;
2704 case METHOD_SEMANTIC_REMOVE_ON:
2705 event->remove = method;
2707 case METHOD_SEMANTIC_FIRE:
2708 event->raise = method;
2710 case METHOD_SEMANTIC_OTHER: {
2711 #ifndef MONO_SMALL_CONFIG
2714 if (event->other == NULL) {
2715 event->other = g_new0 (MonoMethod*, 2);
2717 while (event->other [n])
2719 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2721 event->other [n] = method;
2722 /* NULL terminated */
2723 event->other [n + 1] = NULL;
2734 mono_class_alloc_ext (klass);
2736 mono_image_lock (klass->image);
2738 if (klass->ext->events) {
2739 mono_image_unlock (klass->image);
2743 klass->ext->event.first = first;
2744 klass->ext->event.count = count;
2746 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2747 mono_memory_barrier ();
2749 /* Leave this assignment as the last op in the function */
2750 klass->ext->events = events;
2752 mono_image_unlock (klass->image);
2756 * Global pool of interface IDs, represented as a bitset.
2757 * LOCKING: Protected by the classes lock.
2759 static MonoBitSet *global_interface_bitset = NULL;
2762 * mono_unload_interface_ids:
2763 * @bitset: bit set of interface IDs
2765 * When an image is unloaded, the interface IDs associated with
2766 * the image are put back in the global pool of IDs so the numbers
2770 mono_unload_interface_ids (MonoBitSet *bitset)
2773 mono_bitset_sub (global_interface_bitset, bitset);
2778 mono_unload_interface_id (MonoClass *klass)
2780 if (global_interface_bitset && klass->interface_id) {
2782 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2788 * mono_get_unique_iid:
2791 * Assign a unique integer ID to the interface represented by @class.
2792 * The ID will positive and as small as possible.
2793 * LOCKING: Acquires the classes lock.
2794 * Returns: The new ID.
2797 mono_get_unique_iid (MonoClass *klass)
2801 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2805 if (!global_interface_bitset) {
2806 global_interface_bitset = mono_bitset_new (128, 0);
2809 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2811 int old_size = mono_bitset_size (global_interface_bitset);
2812 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2813 mono_bitset_free (global_interface_bitset);
2814 global_interface_bitset = new_set;
2817 mono_bitset_set (global_interface_bitset, iid);
2818 /* set the bit also in the per-image set */
2819 if (!klass->generic_class) {
2820 if (klass->image->interface_bitset) {
2821 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2822 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2823 mono_bitset_free (klass->image->interface_bitset);
2824 klass->image->interface_bitset = new_set;
2827 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2829 mono_bitset_set (klass->image->interface_bitset, iid);
2834 #ifndef MONO_SMALL_CONFIG
2835 if (mono_print_vtable) {
2837 char *type_name = mono_type_full_name (&klass->byval_arg);
2838 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2839 generic_id = klass->generic_class->context.class_inst->id;
2840 g_assert (generic_id != 0);
2844 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2849 g_assert (iid <= 65535);
2854 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2859 mono_class_setup_interfaces (klass, error);
2860 return_if_nok (error);
2862 for (i = 0; i < klass->interface_count; i++) {
2863 ic = klass->interfaces [i];
2866 *res = g_ptr_array_new ();
2867 g_ptr_array_add (*res, ic);
2868 mono_class_init (ic);
2869 if (mono_class_has_failure (ic)) {
2870 mono_error_set_type_load_class (error, ic, "Error Loading class");
2874 collect_implemented_interfaces_aux (ic, res, error);
2875 return_if_nok (error);
2880 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2882 GPtrArray *res = NULL;
2884 collect_implemented_interfaces_aux (klass, &res, error);
2885 if (!mono_error_ok (error)) {
2887 g_ptr_array_free (res, TRUE);
2894 compare_interface_ids (const void *p_key, const void *p_element) {
2895 const MonoClass *key = (const MonoClass *)p_key;
2896 const MonoClass *element = *(const MonoClass **)p_element;
2898 return (key->interface_id - element->interface_id);
2901 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2903 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2904 MonoClass **result = (MonoClass **)mono_binary_search (
2906 klass->interfaces_packed,
2907 klass->interface_offsets_count,
2908 sizeof (MonoClass *),
2909 compare_interface_ids);
2911 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2918 * mono_class_interface_offset_with_variance:
2920 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2921 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2923 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2925 * FIXME figure out MS disambiguation rules and fix this function.
2928 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2929 int i = mono_class_interface_offset (klass, itf);
2930 *non_exact_match = FALSE;
2934 if (!mono_class_has_variant_generic_params (itf))
2937 for (i = 0; i < klass->interface_offsets_count; i++) {
2938 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2939 *non_exact_match = TRUE;
2940 return klass->interface_offsets_packed [i];
2948 print_implemented_interfaces (MonoClass *klass) {
2951 GPtrArray *ifaces = NULL;
2953 int ancestor_level = 0;
2955 name = mono_type_get_full_name (klass);
2956 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2959 for (i = 0; i < klass->interface_offsets_count; i++)
2960 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2961 klass->interfaces_packed [i]->interface_id,
2962 klass->interface_offsets_packed [i],
2963 klass->interfaces_packed [i]->method.count,
2964 klass->interfaces_packed [i]->name_space,
2965 klass->interfaces_packed [i]->name );
2966 printf ("Interface flags: ");
2967 for (i = 0; i <= klass->max_interface_id; i++)
2968 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2969 printf ("(%d,T)", i);
2971 printf ("(%d,F)", i);
2973 printf ("Dump interface flags:");
2974 #ifdef COMPRESSED_INTERFACE_BITMAP
2976 const uint8_t* p = klass->interface_bitmap;
2977 i = klass->max_interface_id;
2979 printf (" %d x 00 %02X", p [0], p [1]);
2985 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2986 printf (" %02X", klass->interface_bitmap [i]);
2989 while (klass != NULL) {
2990 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2991 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2992 if (!mono_error_ok (&error)) {
2993 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2994 mono_error_cleanup (&error);
2995 } else if (ifaces) {
2996 for (i = 0; i < ifaces->len; i++) {
2997 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2998 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2999 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3001 mono_class_interface_offset (klass, ic),
3006 g_ptr_array_free (ifaces, TRUE);
3009 klass = klass->parent;
3014 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3017 args [0] = &arg0->byval_arg;
3019 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3023 array_class_get_if_rank (MonoClass *klass, guint rank)
3025 return rank ? mono_array_class_get (klass, rank) : klass;
3029 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3031 valuetype_types [0] = eclass;
3032 if (eclass == mono_defaults.int16_class)
3033 valuetype_types [1] = mono_defaults.uint16_class;
3034 else if (eclass == mono_defaults.uint16_class)
3035 valuetype_types [1] = mono_defaults.int16_class;
3036 else if (eclass == mono_defaults.int32_class)
3037 valuetype_types [1] = mono_defaults.uint32_class;
3038 else if (eclass == mono_defaults.uint32_class)
3039 valuetype_types [1] = mono_defaults.int32_class;
3040 else if (eclass == mono_defaults.int64_class)
3041 valuetype_types [1] = mono_defaults.uint64_class;
3042 else if (eclass == mono_defaults.uint64_class)
3043 valuetype_types [1] = mono_defaults.int64_class;
3044 else if (eclass == mono_defaults.byte_class)
3045 valuetype_types [1] = mono_defaults.sbyte_class;
3046 else if (eclass == mono_defaults.sbyte_class)
3047 valuetype_types [1] = mono_defaults.byte_class;
3048 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3049 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3052 /* this won't be needed once bug #325495 is completely fixed
3053 * though we'll need something similar to know which interfaces to allow
3054 * in arrays when they'll be lazyly created
3056 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3057 * MS returns diferrent types based on which instance is called. For example:
3058 * object obj = new byte[10][];
3059 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3060 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3063 * Fixing this should kill quite some code, save some bits and improve compatibility.
3066 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3068 MonoClass *eclass = klass->element_class;
3069 static MonoClass* generic_icollection_class = NULL;
3070 static MonoClass* generic_ienumerable_class = NULL;
3071 static MonoClass* generic_ienumerator_class = NULL;
3072 static MonoClass* generic_ireadonlylist_class = NULL;
3073 static MonoClass* generic_ireadonlycollection_class = NULL;
3074 MonoClass *valuetype_types[2] = { NULL, NULL };
3075 MonoClass **interfaces = NULL;
3076 int i, nifaces, interface_count, real_count, original_rank;
3078 gboolean internal_enumerator;
3079 gboolean eclass_is_valuetype;
3081 if (!mono_defaults.generic_ilist_class) {
3085 internal_enumerator = FALSE;
3086 eclass_is_valuetype = FALSE;
3087 original_rank = eclass->rank;
3088 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3089 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3091 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3093 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3094 original_rank = eclass->rank;
3096 eclass = eclass->element_class;
3097 internal_enumerator = TRUE;
3098 *is_enumerator = TRUE;
3106 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3107 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3109 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3111 if (!generic_icollection_class) {
3112 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3113 "System.Collections.Generic", "ICollection`1");
3114 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3115 "System.Collections.Generic", "IEnumerable`1");
3116 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3117 "System.Collections.Generic", "IEnumerator`1");
3118 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3119 "System.Collections.Generic", "IReadOnlyList`1");
3120 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3121 "System.Collections.Generic", "IReadOnlyCollection`1");
3124 mono_class_init (eclass);
3127 * Arrays in 2.0 need to implement a number of generic interfaces
3128 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3129 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3130 * We collect the types needed to build the
3131 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3132 * the generic interfaces needed to implement.
3134 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3135 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3137 if (eclass->valuetype) {
3138 nifaces = generic_ireadonlylist_class ? 5 : 3;
3139 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3141 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3142 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3143 if (internal_enumerator) {
3145 if (valuetype_types [1])
3149 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3150 interfaces [0] = valuetype_types [0];
3151 if (valuetype_types [1])
3152 interfaces [nifaces] = valuetype_types [1];
3154 eclass_is_valuetype = TRUE;
3157 int idepth = eclass->idepth;
3158 if (!internal_enumerator)
3160 nifaces = generic_ireadonlylist_class ? 2 : 3;
3162 // FIXME: This doesn't seem to work/required for generic params
3163 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3164 mono_class_setup_interface_offsets (eclass);
3166 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3167 /* we add object for interfaces and the supertypes for the other
3168 * types. The last of the supertypes is the element class itself which we
3169 * already created the explicit interfaces for (so we include it for IEnumerator
3170 * and exclude it for arrays).
3172 if (MONO_CLASS_IS_INTERFACE (eclass))
3175 interface_count += idepth;
3176 if (eclass->rank && eclass->element_class->valuetype) {
3177 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3178 if (valuetype_types [1])
3181 /* IList, ICollection, IEnumerable, IReadOnlyList */
3182 interface_count *= nifaces;
3183 real_count = interface_count;
3184 if (internal_enumerator) {
3185 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3186 if (valuetype_types [1])
3189 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3190 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3191 interfaces [0] = mono_defaults.object_class;
3195 for (i = 0; i < idepth; i++) {
3196 mono_class_init (eclass->supertypes [i]);
3197 interfaces [j] = eclass->supertypes [i];
3201 if (all_interfaces) {
3202 for (i = 0; i < eclass->interface_offsets_count; i++) {
3203 interfaces [j] = eclass->interfaces_packed [i];
3207 for (i = 0; i < eclass->interface_count; i++) {
3208 interfaces [j] = eclass->interfaces [i];
3212 if (valuetype_types [1]) {
3213 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3218 /* instantiate the generic interfaces */
3219 for (i = 0; i < interface_count; i += nifaces) {
3220 MonoClass *iface = interfaces [i];
3222 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3223 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3225 if (eclass->valuetype) {
3226 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3227 if (generic_ireadonlylist_class) {
3228 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3229 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3232 if (!generic_ireadonlylist_class)
3233 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3236 if (internal_enumerator) {
3238 /* instantiate IEnumerator<iface> */
3239 for (i = 0; i < interface_count; i++) {
3240 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3242 j = interface_count;
3243 if (!eclass_is_valuetype) {
3244 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3245 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3248 for (i = 0; i < eclass->idepth; i++) {
3249 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3253 for (i = 0; i < eclass->interface_offsets_count; i++) {
3254 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3258 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3260 if (valuetype_types [1])
3261 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3265 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3266 for (i = 0; i < real_count; ++i) {
3267 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3268 g_print ("%s implements %s\n", type_name, name);
3279 find_array_interface (MonoClass *klass, const char *name)
3282 for (i = 0; i < klass->interface_count; ++i) {
3283 if (strcmp (klass->interfaces [i]->name, name) == 0)
3290 * Return the number of virtual methods.
3291 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3292 * Return -1 on failure.
3293 * FIXME It would be nice if this information could be cached somewhere.
3296 count_virtual_methods (MonoClass *klass)
3300 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3302 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3303 mono_class_setup_methods (klass);
3304 if (mono_class_has_failure (klass))
3307 for (i = 0; i < klass->method.count; ++i) {
3308 flags = klass->methods [i]->flags;
3309 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3313 for (i = 0; i < klass->method.count; ++i) {
3314 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3316 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3324 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3332 m = (l + num_ifaces) / 2;
3333 if (interfaces_full [m] == ic)
3335 if (l == num_ifaces)
3337 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3346 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3348 int i = find_interface (num_ifaces, interfaces_full, ic);
3350 return interface_offsets_full [i];
3355 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3357 int i = find_interface (num_ifaces, interfaces_full, ic);
3361 interface_offsets_full [i] = offset;
3364 for (i = 0; i < num_ifaces; ++i) {
3365 if (interfaces_full [i]) {
3367 if (interfaces_full [i]->interface_id < ic->interface_id)
3370 while (end < num_ifaces && interfaces_full [end]) end++;
3371 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3372 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3374 interfaces_full [i] = ic;
3375 interface_offsets_full [i] = offset;
3381 #ifdef COMPRESSED_INTERFACE_BITMAP
3384 * Compressed interface bitmap design.
3386 * Interface bitmaps take a large amount of memory, because their size is
3387 * linear with the maximum interface id assigned in the process (each interface
3388 * is assigned a unique id as it is loaded). The number of interface classes
3389 * is high because of the many implicit interfaces implemented by arrays (we'll
3390 * need to lazy-load them in the future).
3391 * Most classes implement a very small number of interfaces, so the bitmap is
3392 * sparse. This bitmap needs to be checked by interface casts, so access to the
3393 * needed bit must be fast and doable with few jit instructions.
3395 * The current compression format is as follows:
3396 * *) it is a sequence of one or more two-byte elements
3397 * *) the first byte in the element is the count of empty bitmap bytes
3398 * at the current bitmap position
3399 * *) the second byte in the element is an actual bitmap byte at the current
3402 * As an example, the following compressed bitmap bytes:
3403 * 0x07 0x01 0x00 0x7
3404 * correspond to the following bitmap:
3405 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3407 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3408 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3409 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3413 * mono_compress_bitmap:
3414 * @dest: destination buffer
3415 * @bitmap: bitmap buffer
3416 * @size: size of @bitmap in bytes
3418 * This is a mono internal function.
3419 * The @bitmap data is compressed into a format that is small but
3420 * still searchable in few instructions by the JIT and runtime.
3421 * The compressed data is stored in the buffer pointed to by the
3422 * @dest array. Passing a #NULL value for @dest allows to just compute
3423 * the size of the buffer.
3424 * This compression algorithm assumes the bits set in the bitmap are
3425 * few and far between, like in interface bitmaps.
3426 * Returns: The size of the compressed bitmap in bytes.
3429 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3433 const uint8_t *end = bitmap + size;
3434 while (bitmap < end) {
3435 if (*bitmap || numz == 255) {
3459 * mono_class_interface_match:
3460 * @bitmap: a compressed bitmap buffer
3461 * @id: the index to check in the bitmap
3463 * This is a mono internal function.
3464 * Checks if a bit is set in a compressed interface bitmap. @id must
3465 * be already checked for being smaller than the maximum id encoded in the
3468 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3472 mono_class_interface_match (const uint8_t *bitmap, int id)
3475 id -= bitmap [0] * 8;
3479 return bitmap [1] & (1 << id);
3488 * LOCKING: this is supposed to be called with the loader lock held.
3489 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3492 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3496 int i, j, max_iid, num_ifaces;
3497 MonoClass **interfaces_full = NULL;
3498 int *interface_offsets_full = NULL;
3500 GPtrArray **ifaces_array = NULL;
3501 int interface_offsets_count;
3502 MonoClass **array_interfaces = NULL;
3503 int num_array_interfaces;
3504 int is_enumerator = FALSE;
3506 mono_class_setup_supertypes (klass);
3508 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3509 * implicit interfaces have the property that they are assigned the same slot in the
3510 * vtables for compatible interfaces
3512 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3514 /* compute maximum number of slots and maximum interface id */
3516 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3517 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3518 for (j = 0; j < klass->idepth; j++) {
3519 k = klass->supertypes [j];
3520 num_ifaces += k->interface_count;
3521 for (i = 0; i < k->interface_count; i++) {
3522 ic = k->interfaces [i];
3525 mono_class_init (ic);
3527 if (max_iid < ic->interface_id)
3528 max_iid = ic->interface_id;
3530 ifaces = mono_class_get_implemented_interfaces (k, &error);
3531 if (!mono_error_ok (&error)) {
3532 char *name = mono_type_get_full_name (k);
3533 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3535 mono_error_cleanup (&error);
3540 num_ifaces += ifaces->len;
3541 for (i = 0; i < ifaces->len; ++i) {
3542 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3543 if (max_iid < ic->interface_id)
3544 max_iid = ic->interface_id;
3546 ifaces_array [j] = ifaces;
3550 for (i = 0; i < num_array_interfaces; ++i) {
3551 ic = array_interfaces [i];
3552 mono_class_init (ic);
3553 if (max_iid < ic->interface_id)
3554 max_iid = ic->interface_id;
3557 if (MONO_CLASS_IS_INTERFACE (klass)) {
3559 if (max_iid < klass->interface_id)
3560 max_iid = klass->interface_id;
3562 klass->max_interface_id = max_iid;
3563 /* compute vtable offset for interfaces */
3564 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3565 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3567 for (i = 0; i < num_ifaces; i++) {
3568 interface_offsets_full [i] = -1;
3571 /* skip the current class */
3572 for (j = 0; j < klass->idepth - 1; j++) {
3573 k = klass->supertypes [j];
3574 ifaces = ifaces_array [j];
3577 for (i = 0; i < ifaces->len; ++i) {
3579 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3581 /*Force the sharing of interface offsets between parent and subtypes.*/
3582 io = mono_class_interface_offset (k, ic);
3584 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3589 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3590 ifaces = ifaces_array [klass->idepth - 1];
3592 for (i = 0; i < ifaces->len; ++i) {
3594 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3595 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3597 count = count_virtual_methods (ic);
3599 char *name = mono_type_get_full_name (ic);
3600 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3609 if (MONO_CLASS_IS_INTERFACE (klass))
3610 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3612 if (num_array_interfaces) {
3613 if (is_enumerator) {
3614 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3615 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3616 g_assert (ienumerator_offset >= 0);
3617 for (i = 0; i < num_array_interfaces; ++i) {
3618 ic = array_interfaces [i];
3619 if (strcmp (ic->name, "IEnumerator`1") == 0)
3620 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3622 g_assert_not_reached ();
3623 /*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);*/
3626 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3627 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3628 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3629 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3630 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3631 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3632 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3633 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3634 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3635 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3636 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3637 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3638 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3639 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3640 for (i = 0; i < num_array_interfaces; ++i) {
3642 ic = array_interfaces [i];
3643 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3644 offset = ilist_offset;
3645 else if (strcmp (ic->name, "ICollection`1") == 0)
3646 offset = icollection_offset;
3647 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3648 offset = ienumerable_offset;
3649 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3650 offset = ireadonlylist_offset;
3651 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3652 offset = ireadonlycollection_offset;
3654 g_assert_not_reached ();
3655 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3656 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3661 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3662 if (interface_offsets_full [i] != -1) {
3663 interface_offsets_count ++;
3668 * We might get called multiple times:
3669 * - mono_class_init ()
3670 * - mono_class_setup_vtable ().
3671 * - mono_class_setup_interface_offsets ().
3672 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3673 * means we have to overwrite those when called from other places (#4440).
3675 if (klass->interfaces_packed) {
3677 g_assert (klass->interface_offsets_count == interface_offsets_count);
3681 klass->interface_offsets_count = interface_offsets_count;
3682 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3683 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3684 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3685 #ifdef COMPRESSED_INTERFACE_BITMAP
3686 bitmap = g_malloc0 (bsize);
3688 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3690 for (i = 0; i < interface_offsets_count; i++) {
3691 int id = interfaces_full [i]->interface_id;
3692 bitmap [id >> 3] |= (1 << (id & 7));
3693 klass->interfaces_packed [i] = interfaces_full [i];
3694 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3695 /*if (num_array_interfaces)
3696 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]);*/
3698 #ifdef COMPRESSED_INTERFACE_BITMAP
3699 i = mono_compress_bitmap (NULL, bitmap, bsize);
3700 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3701 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3704 klass->interface_bitmap = bitmap;
3709 g_free (interfaces_full);
3710 g_free (interface_offsets_full);
3711 g_free (array_interfaces);
3712 for (i = 0; i < klass->idepth; i++) {
3713 ifaces = ifaces_array [i];
3715 g_ptr_array_free (ifaces, TRUE);
3717 g_free (ifaces_array);
3719 //printf ("JUST DONE: ");
3720 //print_implemented_interfaces (klass);
3726 * Setup interface offsets for interfaces.
3728 * - klass->max_interface_id
3729 * - klass->interface_offsets_count
3730 * - klass->interfaces_packed
3731 * - klass->interface_offsets_packed
3732 * - klass->interface_bitmap
3734 * This function can fail @class.
3737 mono_class_setup_interface_offsets (MonoClass *klass)
3739 mono_loader_lock ();
3741 setup_interface_offsets (klass, 0, FALSE);
3743 mono_loader_unlock ();
3746 /*Checks if @klass has @parent as one of it's parents type gtd
3750 * Bar<T> : Foo<Bar<Bar<T>>>
3754 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3756 klass = mono_class_get_generic_type_definition (klass);
3757 parent = mono_class_get_generic_type_definition (parent);
3758 mono_class_setup_supertypes (klass);
3759 mono_class_setup_supertypes (parent);
3761 return klass->idepth >= parent->idepth &&
3762 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3766 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3768 MonoGenericInst *ginst;
3770 if (!klass->generic_class) {
3771 mono_class_setup_vtable_full (klass, in_setup);
3772 return !mono_class_has_failure (klass);
3775 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3776 if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
3779 ginst = klass->generic_class->context.class_inst;
3780 for (i = 0; i < ginst->type_argc; ++i) {
3782 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3784 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3785 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3786 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3788 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3789 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3797 * mono_class_setup_vtable:
3799 * Creates the generic vtable of CLASS.
3800 * Initializes the following fields in MonoClass:
3803 * Plus all the fields initialized by setup_interface_offsets ().
3804 * If there is an error during vtable construction, klass->has_failure
3805 * is set and details are stored in a MonoErrorBoxed.
3807 * LOCKING: Acquires the loader lock.
3810 mono_class_setup_vtable (MonoClass *klass)
3812 mono_class_setup_vtable_full (klass, NULL);
3816 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3819 MonoMethod **overrides;
3820 MonoGenericContext *context;
3828 if (MONO_CLASS_IS_INTERFACE (klass)) {
3829 /* This sets method->slot for all methods if this is an interface */
3830 mono_class_setup_methods (klass);
3834 if (mono_class_has_failure (klass))
3837 if (g_list_find (in_setup, klass))
3840 mono_loader_lock ();
3842 if (klass->vtable) {
3843 mono_loader_unlock ();
3847 mono_stats.generic_vtable_count ++;
3848 in_setup = g_list_prepend (in_setup, klass);
3850 if (klass->generic_class) {
3851 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3852 mono_loader_unlock ();
3853 g_list_remove (in_setup, klass);
3857 context = mono_class_get_context (klass);
3858 type_token = klass->generic_class->container_class->type_token;
3860 context = (MonoGenericContext *) klass->generic_container;
3861 type_token = klass->type_token;
3864 if (image_is_dynamic (klass->image)) {
3865 /* Generic instances can have zero method overrides without causing any harm.
3866 * This is true since we don't do layout all over again for them, we simply inflate
3867 * the layout of the parent.
3869 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3870 if (!is_ok (&error)) {
3871 mono_loader_unlock ();
3872 g_list_remove (in_setup, klass);
3873 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3874 mono_error_cleanup (&error);
3878 /* The following call fails if there are missing methods in the type */
3879 /* FIXME it's probably a good idea to avoid this for generic instances. */
3880 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3884 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3886 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3890 mono_loader_unlock ();
3891 g_list_remove (in_setup, klass);
3896 #define DEBUG_INTERFACE_VTABLE_CODE 0
3897 #define TRACE_INTERFACE_VTABLE_CODE 0
3898 #define VERIFY_INTERFACE_VTABLE_CODE 0
3899 #define VTABLE_SELECTOR (1)
3901 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3902 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3903 if (!(VTABLE_SELECTOR)) break; \
3907 #define DEBUG_INTERFACE_VTABLE(stmt)
3910 #if TRACE_INTERFACE_VTABLE_CODE
3911 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3912 if (!(VTABLE_SELECTOR)) break; \
3916 #define TRACE_INTERFACE_VTABLE(stmt)
3919 #if VERIFY_INTERFACE_VTABLE_CODE
3920 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3921 if (!(VTABLE_SELECTOR)) break; \
3925 #define VERIFY_INTERFACE_VTABLE(stmt)
3929 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3931 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3935 GString *res = g_string_new ("");
3937 g_string_append_c (res, '(');
3938 for (i = 0; i < sig->param_count; ++i) {
3940 g_string_append_c (res, ',');
3941 mono_type_get_desc (res, sig->params [i], include_namespace);
3943 g_string_append (res, ")=>");
3944 if (sig->ret != NULL) {
3945 mono_type_get_desc (res, sig->ret, include_namespace);
3947 g_string_append (res, "NULL");
3950 g_string_free (res, FALSE);
3954 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3955 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3956 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3957 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3965 is_wcf_hack_disabled (void)
3967 static gboolean disabled;
3968 static gboolean inited = FALSE;
3970 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3977 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3979 MonoMethodSignature *cmsig, *imsig;
3980 if (strcmp (im->name, cm->name) == 0) {
3981 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3982 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3985 if (! slot_is_empty) {
3986 if (require_newslot) {
3987 if (! interface_is_explicitly_implemented_by_class) {
3988 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3991 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3992 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3996 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3999 cmsig = mono_method_signature (cm);
4000 imsig = mono_method_signature (im);
4001 if (!cmsig || !imsig) {
4002 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4006 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4007 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4008 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4009 TRACE_INTERFACE_VTABLE (printf ("]"));
4012 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4013 if (mono_security_core_clr_enabled ())
4014 mono_security_core_clr_check_override (klass, cm, im);
4016 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4017 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4018 char *body_name = mono_method_full_name (cm, TRUE);
4019 char *decl_name = mono_method_full_name (im, TRUE);
4020 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4028 MonoClass *ic = im->klass;
4029 const char *ic_name_space = ic->name_space;
4030 const char *ic_name = ic->name;
4033 if (! require_newslot) {
4034 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4037 if (cm->klass->rank == 0) {
4038 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4041 cmsig = mono_method_signature (cm);
4042 imsig = mono_method_signature (im);
4043 if (!cmsig || !imsig) {
4044 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4048 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4049 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4050 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4051 TRACE_INTERFACE_VTABLE (printf ("]"));
4054 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4055 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4058 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4059 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4062 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))) {
4063 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4067 subname = strstr (cm->name, ic_name_space);
4068 if (subname != cm->name) {
4069 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4072 subname += strlen (ic_name_space);
4073 if (subname [0] != '.') {
4074 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4078 if (strstr (subname, ic_name) != subname) {
4079 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4082 subname += strlen (ic_name);
4083 if (subname [0] != '.') {
4084 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4088 if (strcmp (subname, im->name) != 0) {
4089 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4093 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4094 if (mono_security_core_clr_enabled ())
4095 mono_security_core_clr_check_override (klass, cm, im);
4097 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4098 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4099 char *body_name = mono_method_full_name (cm, TRUE);
4100 char *decl_name = mono_method_full_name (im, TRUE);
4101 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4111 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4113 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4114 MonoMethod *method = key;
4115 MonoMethod *override = value;
4116 MonoClass *method_class = mono_method_get_class (method);
4117 MonoClass *override_class = mono_method_get_class (override);
4119 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4120 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4121 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4124 print_overrides (GHashTable *override_map, const char *message) {
4126 printf ("Override map \"%s\" START:\n", message);
4127 g_hash_table_foreach (override_map, foreach_override, NULL);
4128 printf ("Override map \"%s\" END.\n", message);
4130 printf ("Override map \"%s\" EMPTY.\n", message);
4134 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4135 char *full_name = mono_type_full_name (&klass->byval_arg);
4139 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4141 if (print_interfaces) {
4142 print_implemented_interfaces (klass);
4143 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4146 if (klass->parent) {
4147 parent_size = klass->parent->vtable_size;
4151 for (i = 0; i < size; ++i) {
4152 MonoMethod *cm = vtable [i];
4153 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4154 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4156 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4164 #if VERIFY_INTERFACE_VTABLE_CODE
4166 mono_method_try_get_vtable_index (MonoMethod *method)
4168 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4169 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4170 if (imethod->declaring->is_generic)
4171 return imethod->declaring->slot;
4173 return method->slot;
4177 mono_class_verify_vtable (MonoClass *klass)
4180 char *full_name = mono_type_full_name (&klass->byval_arg);
4182 printf ("*** Verifying VTable of class '%s' \n", full_name);
4186 if (!klass->methods)
4189 for (i = 0; i < klass->method.count; ++i) {
4190 MonoMethod *cm = klass->methods [i];
4193 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4197 full_name = mono_method_full_name (cm, TRUE);
4199 slot = mono_method_try_get_vtable_index (cm);
4201 if (slot >= klass->vtable_size) {
4202 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4206 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4207 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4208 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4209 g_free (other_name);
4212 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4219 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4221 char *method_signature;
4224 for (index = 0; index < onum; ++index) {
4225 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4226 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4228 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4229 type_name = mono_type_full_name (&klass->byval_arg);
4230 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4231 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4232 g_free (method_signature);
4234 mono_class_setup_methods (klass);
4235 if (mono_class_has_failure (klass)) {
4236 char *name = mono_type_get_full_name (klass);
4237 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4241 for (index = 0; index < klass->method.count; ++index) {
4242 MonoMethod *cm = klass->methods [index];
4243 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4245 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4246 g_free (method_signature);
4251 mono_method_get_method_definition (MonoMethod *method)
4253 while (method->is_inflated)
4254 method = ((MonoMethodInflated*)method)->declaring;
4259 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4263 for (i = 0; i < onum; ++i) {
4264 MonoMethod *decl = overrides [i * 2];
4265 MonoMethod *body = overrides [i * 2 + 1];
4267 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4268 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4272 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4273 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4274 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4276 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4280 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4281 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4282 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4284 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4288 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4289 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4293 body = mono_method_get_method_definition (body);
4294 decl = mono_method_get_method_definition (decl);
4296 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4297 char *body_name = mono_method_full_name (body, TRUE);
4298 char *decl_name = mono_method_full_name (decl, TRUE);
4299 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4309 mono_class_need_stelemref_method (MonoClass *klass)
4311 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4315 * LOCKING: this is supposed to be called with the loader lock held.
4318 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4322 MonoMethod **vtable;
4323 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4324 GPtrArray *ifaces = NULL;
4325 GHashTable *override_map = NULL;
4327 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4328 int first_non_interface_slot;
4330 GSList *virt_methods = NULL, *l;
4331 int stelemref_slot = 0;
4336 if (overrides && !verify_class_overrides (klass, overrides, onum))
4339 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4340 if (!mono_error_ok (&error)) {
4341 char *name = mono_type_get_full_name (klass);
4342 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4344 mono_error_cleanup (&error);
4346 } else if (ifaces) {
4347 for (i = 0; i < ifaces->len; i++) {
4348 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4349 max_vtsize += ic->method.count;
4351 g_ptr_array_free (ifaces, TRUE);
4355 if (klass->parent) {
4356 mono_class_init (klass->parent);
4357 mono_class_setup_vtable_full (klass->parent, in_setup);
4359 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4362 max_vtsize += klass->parent->vtable_size;
4363 cur_slot = klass->parent->vtable_size;
4366 max_vtsize += klass->method.count;
4368 /*Array have a slot for stelemref*/
4369 if (mono_class_need_stelemref_method (klass)) {
4370 stelemref_slot = cur_slot;
4375 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4376 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4378 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4380 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4381 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4384 max_iid = klass->max_interface_id;
4385 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4387 /* Optimized version for generic instances */
4388 if (klass->generic_class) {
4390 MonoClass *gklass = klass->generic_class->container_class;
4393 mono_class_setup_vtable_full (gklass, in_setup);
4394 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4397 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4398 klass->vtable_size = gklass->vtable_size;
4399 for (i = 0; i < gklass->vtable_size; ++i)
4400 if (gklass->vtable [i]) {
4401 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4402 if (!mono_error_ok (&error)) {
4403 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4404 mono_error_cleanup (&error);
4408 tmp [i]->slot = gklass->vtable [i]->slot;
4410 mono_memory_barrier ();
4411 klass->vtable = tmp;
4413 /* Have to set method->slot for abstract virtual methods */
4414 if (klass->methods && gklass->methods) {
4415 for (i = 0; i < klass->method.count; ++i)
4416 if (klass->methods [i]->slot == -1)
4417 klass->methods [i]->slot = gklass->methods [i]->slot;
4423 if (klass->parent && klass->parent->vtable_size) {
4424 MonoClass *parent = klass->parent;
4427 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4429 // Also inherit parent interface vtables, just as a starting point.
4430 // This is needed otherwise bug-77127.exe fails when the property methods
4431 // have different names in the iterface and the class, because for child
4432 // classes the ".override" information is not used anymore.
4433 for (i = 0; i < parent->interface_offsets_count; i++) {
4434 MonoClass *parent_interface = parent->interfaces_packed [i];
4435 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4436 /*FIXME this is now dead code as this condition will never hold true.
4437 Since interface offsets are inherited then the offset of an interface implemented
4438 by a parent will never be the out of it's vtable boundary.
4440 if (interface_offset >= parent->vtable_size) {
4441 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4444 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4445 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4446 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4447 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4448 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4449 parent_interface_offset + j, parent_interface_offset, j,
4450 interface_offset + j, interface_offset, j));
4457 /*Array have a slot for stelemref*/
4458 if (mono_class_need_stelemref_method (klass)) {
4459 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4461 method->slot = stelemref_slot;
4463 g_assert (method->slot == stelemref_slot);
4465 vtable [stelemref_slot] = method;
4468 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4469 /* override interface methods */
4470 for (i = 0; i < onum; i++) {
4471 MonoMethod *decl = overrides [i*2];
4472 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4474 dslot = mono_method_get_vtable_slot (decl);
4476 mono_class_set_type_load_failure (klass, "");
4480 dslot += mono_class_interface_offset (klass, decl->klass);
4481 vtable [dslot] = overrides [i*2 + 1];
4482 vtable [dslot]->slot = dslot;
4484 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4486 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4488 if (mono_security_core_clr_enabled ())
4489 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4492 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4493 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4496 * Create a list of virtual methods to avoid calling
4497 * mono_class_get_virtual_methods () which is slow because of the metadata
4501 gpointer iter = NULL;
4504 virt_methods = NULL;
4505 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4506 virt_methods = g_slist_prepend (virt_methods, cm);
4508 if (mono_class_has_failure (klass))
4512 // Loop on all implemented interfaces...
4513 for (i = 0; i < klass->interface_offsets_count; i++) {
4514 MonoClass *parent = klass->parent;
4516 gboolean interface_is_explicitly_implemented_by_class;
4519 ic = klass->interfaces_packed [i];
4520 ic_offset = mono_class_interface_offset (klass, ic);
4522 mono_class_setup_methods (ic);
4523 if (mono_class_has_failure (ic))
4526 // Check if this interface is explicitly implemented (instead of just inherited)
4527 if (parent != NULL) {
4528 int implemented_interfaces_index;
4529 interface_is_explicitly_implemented_by_class = FALSE;
4530 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4531 if (ic == klass->interfaces [implemented_interfaces_index]) {
4532 interface_is_explicitly_implemented_by_class = TRUE;
4537 interface_is_explicitly_implemented_by_class = TRUE;
4540 // Loop on all interface methods...
4541 for (im_index = 0; im_index < ic->method.count; im_index++) {
4542 MonoMethod *im = ic->methods [im_index];
4543 int im_slot = ic_offset + im->slot;
4544 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4546 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4549 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4551 // If there is an explicit implementation, just use it right away,
4552 // otherwise look for a matching method
4553 if (override_im == NULL) {
4557 // First look for a suitable method among the class methods
4558 for (l = virt_methods; l; l = l->next) {
4559 cm = (MonoMethod *)l->data;
4560 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)));
4561 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4562 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4563 vtable [im_slot] = cm;
4564 /* Why do we need this? */
4569 TRACE_INTERFACE_VTABLE (printf ("\n"));
4570 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4574 // If the slot is still empty, look in all the inherited virtual methods...
4575 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4576 MonoClass *parent = klass->parent;
4577 // Reverse order, so that last added methods are preferred
4578 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4579 MonoMethod *cm = parent->vtable [cm_index];
4581 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));
4582 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4583 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4584 vtable [im_slot] = cm;
4585 /* Why do we need this? */
4591 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4593 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4597 g_assert (vtable [im_slot] == override_im);
4602 // If the class is not abstract, check that all its interface slots are full.
4603 // The check is done here and not directly at the end of the loop above because
4604 // it can happen (for injected generic array interfaces) that the same slot is
4605 // processed multiple times (those interfaces have overlapping slots), and it
4606 // will not always be the first pass the one that fills the slot.
4607 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4608 for (i = 0; i < klass->interface_offsets_count; i++) {
4612 ic = klass->interfaces_packed [i];
4613 ic_offset = mono_class_interface_offset (klass, ic);
4615 for (im_index = 0; im_index < ic->method.count; im_index++) {
4616 MonoMethod *im = ic->methods [im_index];
4617 int im_slot = ic_offset + im->slot;
4619 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4622 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4623 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4624 if (vtable [im_slot] == NULL) {
4625 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4632 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4633 for (l = virt_methods; l; l = l->next) {
4634 cm = (MonoMethod *)l->data;
4636 * If the method is REUSE_SLOT, we must check in the
4637 * base class for a method to override.
4639 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4641 for (k = klass->parent; k ; k = k->parent) {
4646 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4647 MonoMethodSignature *cmsig, *m1sig;
4649 cmsig = mono_method_signature (cm);
4650 m1sig = mono_method_signature (m1);
4652 if (!cmsig || !m1sig) {
4653 /* FIXME proper error message */
4654 mono_class_set_type_load_failure (klass, "");
4658 if (!strcmp(cm->name, m1->name) &&
4659 mono_metadata_signature_equal (cmsig, m1sig)) {
4661 if (mono_security_core_clr_enabled ())
4662 mono_security_core_clr_check_override (klass, cm, m1);
4664 slot = mono_method_get_vtable_slot (m1);
4668 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4669 char *body_name = mono_method_full_name (cm, TRUE);
4670 char *decl_name = mono_method_full_name (m1, TRUE);
4671 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4677 g_assert (cm->slot < max_vtsize);
4679 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4680 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4681 mono_method_full_name (m1, 1), m1,
4682 mono_method_full_name (cm, 1), cm));
4683 g_hash_table_insert (override_map, m1, cm);
4687 if (mono_class_has_failure (k))
4697 /*Non final newslot methods must be given a non-interface vtable slot*/
4698 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4702 cm->slot = cur_slot++;
4704 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4705 vtable [cm->slot] = cm;
4708 /* override non interface methods */
4709 for (i = 0; i < onum; i++) {
4710 MonoMethod *decl = overrides [i*2];
4711 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4712 g_assert (decl->slot != -1);
4713 vtable [decl->slot] = overrides [i*2 + 1];
4714 overrides [i * 2 + 1]->slot = decl->slot;
4716 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4717 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4718 mono_method_full_name (decl, 1), decl,
4719 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4720 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4722 if (mono_security_core_clr_enabled ())
4723 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4728 * If a method occupies more than one place in the vtable, and it is
4729 * overriden, then change the other occurances too.
4734 for (i = 0; i < max_vtsize; ++i)
4736 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4738 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4743 g_hash_table_destroy (override_map);
4744 override_map = NULL;
4747 g_slist_free (virt_methods);
4748 virt_methods = NULL;
4750 /* Ensure that all vtable slots are filled with concrete instance methods */
4751 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4752 for (i = 0; i < cur_slot; ++i) {
4753 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4754 char *type_name = mono_type_get_full_name (klass);
4755 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4756 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4758 g_free (method_name);
4764 if (klass->generic_class) {
4765 MonoClass *gklass = klass->generic_class->container_class;
4767 mono_class_init (gklass);
4769 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4771 /* Check that the vtable_size value computed in mono_class_init () is correct */
4772 if (klass->vtable_size)
4773 g_assert (cur_slot == klass->vtable_size);
4774 klass->vtable_size = cur_slot;
4777 /* Try to share the vtable with our parent. */
4778 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4779 mono_memory_barrier ();
4780 klass->vtable = klass->parent->vtable;
4782 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4783 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4784 mono_memory_barrier ();
4785 klass->vtable = tmp;
4788 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4789 if (mono_print_vtable) {
4792 print_implemented_interfaces (klass);
4794 for (i = 0; i <= max_iid; i++)
4795 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4798 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4799 klass->vtable_size, icount);
4801 for (i = 0; i < cur_slot; ++i) {
4806 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4807 mono_method_full_name (cm, TRUE));
4813 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4814 klass->name, max_iid);
4816 for (i = 0; i < klass->interface_count; i++) {
4817 ic = klass->interfaces [i];
4818 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4819 mono_class_interface_offset (klass, ic),
4820 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4823 for (k = klass->parent; k ; k = k->parent) {
4824 for (i = 0; i < k->interface_count; i++) {
4825 ic = k->interfaces [i];
4826 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4827 mono_class_interface_offset (klass, ic),
4828 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4834 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4839 char *name = mono_type_get_full_name (klass);
4840 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4843 g_hash_table_destroy (override_map);
4845 g_slist_free (virt_methods);
4850 * mono_method_get_vtable_slot:
4852 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4853 * LOCKING: Acquires the loader lock.
4855 * FIXME Use proper MonoError machinery here.
4858 mono_method_get_vtable_slot (MonoMethod *method)
4860 if (method->slot == -1) {
4861 mono_class_setup_vtable (method->klass);
4862 if (mono_class_has_failure (method->klass))
4864 if (method->slot == -1) {
4868 if (!method->klass->generic_class) {
4869 g_assert (method->is_inflated);
4870 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4873 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4874 g_assert (method->klass->generic_class);
4875 gklass = method->klass->generic_class->container_class;
4876 mono_class_setup_methods (method->klass);
4877 g_assert (method->klass->methods);
4878 for (i = 0; i < method->klass->method.count; ++i) {
4879 if (method->klass->methods [i] == method)
4882 g_assert (i < method->klass->method.count);
4883 g_assert (gklass->methods);
4884 method->slot = gklass->methods [i]->slot;
4886 g_assert (method->slot != -1);
4888 return method->slot;
4892 * mono_method_get_vtable_index:
4895 * Returns the index into the runtime vtable to access the method or,
4896 * in the case of a virtual generic method, the virtual generic method
4897 * thunk. Returns -1 on failure.
4899 * FIXME Use proper MonoError machinery here.
4902 mono_method_get_vtable_index (MonoMethod *method)
4904 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4905 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4906 if (imethod->declaring->is_generic)
4907 return mono_method_get_vtable_slot (imethod->declaring);
4909 return mono_method_get_vtable_slot (method);
4912 static MonoMethod *default_ghc = NULL;
4913 static MonoMethod *default_finalize = NULL;
4914 static int finalize_slot = -1;
4915 static int ghc_slot = -1;
4918 initialize_object_slots (MonoClass *klass)
4923 if (klass == mono_defaults.object_class) {
4924 mono_class_setup_vtable (klass);
4925 for (i = 0; i < klass->vtable_size; ++i) {
4926 MonoMethod *cm = klass->vtable [i];
4928 if (!strcmp (cm->name, "GetHashCode"))
4930 else if (!strcmp (cm->name, "Finalize"))
4934 g_assert (ghc_slot > 0);
4935 default_ghc = klass->vtable [ghc_slot];
4937 g_assert (finalize_slot > 0);
4938 default_finalize = klass->vtable [finalize_slot];
4943 MonoMethod *array_method;
4945 } GenericArrayMethodInfo;
4947 static int generic_array_method_num = 0;
4948 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4951 generic_array_methods (MonoClass *klass)
4953 int i, count_generic = 0;
4954 GList *list = NULL, *tmp;
4955 if (generic_array_method_num)
4956 return generic_array_method_num;
4957 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4958 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4959 for (i = 0; i < klass->parent->method.count; i++) {
4960 MonoMethod *m = klass->parent->methods [i];
4961 if (!strncmp (m->name, "InternalArray__", 15)) {
4963 list = g_list_prepend (list, m);
4966 list = g_list_reverse (list);
4967 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4969 for (tmp = list; tmp; tmp = tmp->next) {
4970 const char *mname, *iname;
4972 MonoMethod *m = (MonoMethod *)tmp->data;
4973 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4974 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4976 generic_array_method_info [i].array_method = m;
4977 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4978 iname = "System.Collections.Generic.ICollection`1.";
4979 mname = m->name + 27;
4980 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4981 iname = "System.Collections.Generic.IEnumerable`1.";
4982 mname = m->name + 27;
4983 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4984 iname = "System.Collections.Generic.IReadOnlyList`1.";
4985 mname = m->name + strlen (ireadonlylist_prefix);
4986 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4987 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4988 mname = m->name + strlen (ireadonlycollection_prefix);
4989 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4990 iname = "System.Collections.Generic.IList`1.";
4991 mname = m->name + 15;
4993 g_assert_not_reached ();
4996 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4997 strcpy (name, iname);
4998 strcpy (name + strlen (iname), mname);
4999 generic_array_method_info [i].name = name;
5002 /*g_print ("array generic methods: %d\n", count_generic);*/
5004 generic_array_method_num = count_generic;
5006 return generic_array_method_num;
5010 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5012 MonoGenericContext tmp_context;
5015 tmp_context.class_inst = NULL;
5016 tmp_context.method_inst = iface->generic_class->context.class_inst;
5017 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5019 for (i = 0; i < generic_array_method_num; i++) {
5021 MonoMethod *m = generic_array_method_info [i].array_method;
5022 MonoMethod *inflated;
5024 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5025 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5026 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5031 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5033 int null_length = strlen ("(null)");
5034 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5035 char *s = (char *)mono_image_alloc (image, len);
5038 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5039 g_assert (result == len - 1);
5046 * @class: the class to initialize
5048 * Compute the instance_size, class_size and other infos that cannot be
5049 * computed at mono_class_get() time. Also compute vtable_size if possible.
5050 * Returns TRUE on success or FALSE if there was a problem in loading
5051 * the type (incorrect assemblies, missing assemblies, methods, etc).
5053 * LOCKING: Acquires the loader lock.
5056 mono_class_init (MonoClass *klass)
5059 MonoCachedClassInfo cached_info;
5060 gboolean has_cached_info;
5064 /* Double-checking locking pattern */
5065 if (klass->inited || mono_class_has_failure (klass))
5066 return !mono_class_has_failure (klass);
5068 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5070 /* We do everything inside the lock to prevent races */
5071 mono_loader_lock ();
5073 if (klass->inited || mono_class_has_failure (klass)) {
5074 mono_loader_unlock ();
5075 /* Somebody might have gotten in before us */
5076 return !mono_class_has_failure (klass);
5079 if (klass->init_pending) {
5080 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5084 klass->init_pending = 1;
5086 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5087 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5092 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5093 MonoClass *element_class = klass->element_class;
5094 if (!element_class->inited)
5095 mono_class_init (element_class);
5096 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5100 mono_stats.initialized_class_count++;
5102 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5103 MonoClass *gklass = klass->generic_class->container_class;
5105 mono_stats.generic_class_count++;
5107 klass->method = gklass->method;
5108 klass->field = gklass->field;
5110 mono_class_init (gklass);
5111 // FIXME: Why is this needed ?
5112 if (!mono_class_has_failure (gklass))
5113 mono_class_setup_methods (gklass);
5114 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5117 if (MONO_CLASS_IS_INTERFACE (klass))
5118 klass->interface_id = mono_get_unique_iid (klass);
5121 if (klass->parent && !klass->parent->inited)
5122 mono_class_init (klass->parent);
5124 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5126 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5127 klass->nested_classes_inited = TRUE;
5130 * Computes the size used by the fields, and their locations
5132 if (has_cached_info) {
5133 klass->instance_size = cached_info.instance_size;
5134 klass->sizes.class_size = cached_info.class_size;
5135 klass->packing_size = cached_info.packing_size;
5136 klass->min_align = cached_info.min_align;
5137 klass->blittable = cached_info.blittable;
5138 klass->has_references = cached_info.has_references;
5139 klass->has_static_refs = cached_info.has_static_refs;
5140 klass->no_special_static_fields = cached_info.no_special_static_fields;
5143 if (!klass->size_inited){
5144 mono_class_setup_fields (klass);
5145 if (mono_class_has_failure (klass))
5149 /* Initialize arrays */
5151 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5153 if (klass->interface_count) {
5154 int count_generic = generic_array_methods (klass);
5155 klass->method.count += klass->interface_count * count_generic;
5159 mono_class_setup_supertypes (klass);
5162 initialize_object_slots (klass);
5165 * Initialize the rest of the data without creating a generic vtable if possible.
5166 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5167 * also avoid computing a generic vtable.
5169 if (has_cached_info) {
5171 klass->vtable_size = cached_info.vtable_size;
5172 klass->has_finalize = cached_info.has_finalize;
5173 klass->has_finalize_inited = TRUE;
5174 klass->ghcimpl = cached_info.ghcimpl;
5175 klass->has_cctor = cached_info.has_cctor;
5176 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5177 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5178 * The first slot if for array with.
5180 static int szarray_vtable_size[2] = { 0 };
5182 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5185 if (!szarray_vtable_size [slot]) {
5186 mono_class_setup_vtable (klass);
5187 szarray_vtable_size [slot] = klass->vtable_size;
5189 klass->vtable_size = szarray_vtable_size[slot];
5191 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5192 MonoClass *gklass = klass->generic_class->container_class;
5194 /* Generic instance case */
5195 klass->ghcimpl = gklass->ghcimpl;
5196 klass->has_cctor = gklass->has_cctor;
5198 mono_class_setup_vtable (gklass);
5199 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5202 klass->vtable_size = gklass->vtable_size;
5206 /* ghcimpl is not currently used
5208 if (klass->parent) {
5209 MonoMethod *cmethod = klass->vtable [ghc_slot];
5210 if (cmethod->is_inflated)
5211 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5212 if (cmethod == default_ghc) {
5218 /* C# doesn't allow interfaces to have cctors */
5219 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5220 MonoMethod *cmethod = NULL;
5222 if (klass->type_token && !image_is_dynamic(klass->image)) {
5223 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5224 /* The find_method function ignores the 'flags' argument */
5225 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5226 klass->has_cctor = 1;
5228 mono_class_setup_methods (klass);
5229 if (mono_class_has_failure (klass))
5232 for (i = 0; i < klass->method.count; ++i) {
5233 MonoMethod *method = klass->methods [i];
5234 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5235 (strcmp (".cctor", method->name) == 0)) {
5236 klass->has_cctor = 1;
5244 if (klass->parent) {
5245 MonoError parent_error;
5246 mono_error_init (&parent_error);
5247 int first_iface_slot;
5248 /* This will compute klass->parent->vtable_size for some classes */
5249 mono_class_init (klass->parent);
5250 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to initialize")) {
5253 if (!klass->parent->vtable_size) {
5254 /* FIXME: Get rid of this somehow */
5255 mono_class_setup_vtable (klass->parent);
5256 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize")) {
5260 first_iface_slot = klass->parent->vtable_size;
5261 if (mono_class_need_stelemref_method (klass))
5263 setup_interface_offsets (klass, first_iface_slot, TRUE);
5265 setup_interface_offsets (klass, 0, TRUE);
5268 if (mono_security_core_clr_enabled ())
5269 mono_security_core_clr_check_inheritance (klass);
5271 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5272 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5277 /* Because of the double-checking locking pattern */
5278 mono_memory_barrier ();
5280 klass->init_pending = 0;
5282 mono_loader_unlock ();
5284 return !mono_class_has_failure (klass);
5288 * mono_class_has_finalizer:
5290 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5294 mono_class_has_finalizer (MonoClass *klass)
5296 gboolean has_finalize = FALSE;
5298 if (klass->has_finalize_inited)
5299 return klass->has_finalize;
5301 /* Interfaces and valuetypes are not supposed to have finalizers */
5302 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5303 MonoMethod *cmethod = NULL;
5305 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5306 } else if (klass->generic_class) {
5307 MonoClass *gklass = klass->generic_class->container_class;
5309 has_finalize = mono_class_has_finalizer (gklass);
5310 } else if (klass->parent && klass->parent->has_finalize) {
5311 has_finalize = TRUE;
5313 if (klass->parent) {
5315 * Can't search in metadata for a method named Finalize, because that
5316 * ignores overrides.
5318 mono_class_setup_vtable (klass);
5319 if (mono_class_has_failure (klass))
5322 cmethod = klass->vtable [finalize_slot];
5326 g_assert (klass->vtable_size > finalize_slot);
5328 if (klass->parent) {
5329 if (cmethod->is_inflated)
5330 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5331 if (cmethod != default_finalize)
5332 has_finalize = TRUE;
5338 mono_image_lock (klass->image);
5340 if (!klass->has_finalize_inited) {
5341 klass->has_finalize = has_finalize ? 1 : 0;
5343 mono_memory_barrier ();
5344 klass->has_finalize_inited = TRUE;
5347 mono_image_unlock (klass->image);
5349 return klass->has_finalize;
5353 mono_is_corlib_image (MonoImage *image)
5355 return image == mono_defaults.corlib;
5359 * LOCKING: this assumes the loader lock is held
5362 mono_class_setup_mono_type (MonoClass *klass)
5364 const char *name = klass->name;
5365 const char *nspace = klass->name_space;
5366 gboolean is_corlib = mono_is_corlib_image (klass->image);
5368 klass->this_arg.byref = 1;
5369 klass->this_arg.data.klass = klass;
5370 klass->this_arg.type = MONO_TYPE_CLASS;
5371 klass->byval_arg.data.klass = klass;
5372 klass->byval_arg.type = MONO_TYPE_CLASS;
5374 if (is_corlib && !strcmp (nspace, "System")) {
5375 if (!strcmp (name, "ValueType")) {
5377 * do not set the valuetype bit for System.ValueType.
5378 * klass->valuetype = 1;
5380 klass->blittable = TRUE;
5381 } else if (!strcmp (name, "Enum")) {
5383 * do not set the valuetype bit for System.Enum.
5384 * klass->valuetype = 1;
5386 klass->valuetype = 0;
5387 klass->enumtype = 0;
5388 } else if (!strcmp (name, "Object")) {
5389 klass->byval_arg.type = MONO_TYPE_OBJECT;
5390 klass->this_arg.type = MONO_TYPE_OBJECT;
5391 } else if (!strcmp (name, "String")) {
5392 klass->byval_arg.type = MONO_TYPE_STRING;
5393 klass->this_arg.type = MONO_TYPE_STRING;
5394 } else if (!strcmp (name, "TypedReference")) {
5395 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5396 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5400 if (klass->valuetype) {
5401 int t = MONO_TYPE_VALUETYPE;
5403 if (is_corlib && !strcmp (nspace, "System")) {
5406 if (!strcmp (name, "Boolean")) {
5407 t = MONO_TYPE_BOOLEAN;
5408 } else if (!strcmp(name, "Byte")) {
5410 klass->blittable = TRUE;
5414 if (!strcmp (name, "Char")) {
5419 if (!strcmp (name, "Double")) {
5421 klass->blittable = TRUE;
5425 if (!strcmp (name, "Int32")) {
5427 klass->blittable = TRUE;
5428 } else if (!strcmp(name, "Int16")) {
5430 klass->blittable = TRUE;
5431 } else if (!strcmp(name, "Int64")) {
5433 klass->blittable = TRUE;
5434 } else if (!strcmp(name, "IntPtr")) {
5436 klass->blittable = TRUE;
5440 if (!strcmp (name, "Single")) {
5442 klass->blittable = TRUE;
5443 } else if (!strcmp(name, "SByte")) {
5445 klass->blittable = TRUE;
5449 if (!strcmp (name, "UInt32")) {
5451 klass->blittable = TRUE;
5452 } else if (!strcmp(name, "UInt16")) {
5454 klass->blittable = TRUE;
5455 } else if (!strcmp(name, "UInt64")) {
5457 klass->blittable = TRUE;
5458 } else if (!strcmp(name, "UIntPtr")) {
5460 klass->blittable = TRUE;
5464 if (!strcmp (name, "TypedReference")) {
5465 t = MONO_TYPE_TYPEDBYREF;
5466 klass->blittable = TRUE;
5470 if (!strcmp (name, "Void")) {
5478 klass->byval_arg.type = (MonoTypeEnum)t;
5479 klass->this_arg.type = (MonoTypeEnum)t;
5482 if (MONO_CLASS_IS_INTERFACE (klass))
5483 klass->interface_id = mono_get_unique_iid (klass);
5489 * COM initialization is delayed until needed.
5490 * However when a [ComImport] attribute is present on a type it will trigger
5491 * the initialization. This is not a problem unless the BCL being executed
5492 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5495 init_com_from_comimport (MonoClass *klass)
5497 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5498 if (mono_security_core_clr_enabled ()) {
5499 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5500 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5501 /* but it can not be made available for application (i.e. user code) since all COM calls
5502 * are considered native calls. In this case we fail with a TypeLoadException (just like
5503 * Silverlight 2 does */
5504 mono_class_set_type_load_failure (klass, "");
5509 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5511 #endif /*DISABLE_COM*/
5514 * LOCKING: this assumes the loader lock is held
5517 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5519 gboolean system_namespace;
5520 gboolean is_corlib = mono_is_corlib_image (klass->image);
5522 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5524 /* if root of the hierarchy */
5525 if (system_namespace && !strcmp (klass->name, "Object")) {
5526 klass->parent = NULL;
5527 klass->instance_size = sizeof (MonoObject);
5530 if (!strcmp (klass->name, "<Module>")) {
5531 klass->parent = NULL;
5532 klass->instance_size = 0;
5536 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5537 /* Imported COM Objects always derive from __ComObject. */
5539 if (MONO_CLASS_IS_IMPORT (klass)) {
5540 init_com_from_comimport (klass);
5541 if (parent == mono_defaults.object_class)
5542 parent = mono_class_get_com_object_class ();
5546 /* set the parent to something useful and safe, but mark the type as broken */
5547 parent = mono_defaults.object_class;
5548 mono_class_set_type_load_failure (klass, "");
5551 klass->parent = parent;
5553 if (parent->generic_class && !parent->name) {
5555 * If the parent is a generic instance, we may get
5556 * called before it is fully initialized, especially
5557 * before it has its name.
5562 #ifndef DISABLE_REMOTING
5563 klass->marshalbyref = parent->marshalbyref;
5564 klass->contextbound = parent->contextbound;
5567 klass->delegate = parent->delegate;
5569 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5570 mono_class_set_is_com_object (klass);
5572 if (system_namespace) {
5573 #ifndef DISABLE_REMOTING
5574 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5575 klass->marshalbyref = 1;
5577 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5578 klass->contextbound = 1;
5580 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5581 klass->delegate = 1;
5584 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5585 (strcmp (klass->parent->name_space, "System") == 0)))
5586 klass->valuetype = 1;
5587 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5588 klass->valuetype = klass->enumtype = 1;
5590 /*klass->enumtype = klass->parent->enumtype; */
5592 /* initialize com types if COM interfaces are present */
5594 if (MONO_CLASS_IS_IMPORT (klass))
5595 init_com_from_comimport (klass);
5597 klass->parent = NULL;
5603 * mono_class_setup_supertypes:
5606 * Build the data structure needed to make fast type checks work.
5607 * This currently sets two fields in @class:
5608 * - idepth: distance between @class and System.Object in the type
5610 * - supertypes: array of classes: each element has a class in the hierarchy
5611 * starting from @class up to System.Object
5613 * LOCKING: This function is atomic, in case of contention we waste memory.
5616 mono_class_setup_supertypes (MonoClass *klass)
5619 MonoClass **supertypes;
5621 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5625 if (klass->parent && !klass->parent->supertypes)
5626 mono_class_setup_supertypes (klass->parent);
5628 klass->idepth = klass->parent->idepth + 1;
5632 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5633 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5635 if (klass->parent) {
5636 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5639 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5640 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5642 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5645 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5649 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5651 MonoClass *gtd = (MonoClass*)user_data;
5652 /* Only try to fix generic instances of @gtd */
5653 if (gclass->generic_class->container_class != gtd)
5656 /* Check if the generic instance has no parent. */
5657 if (gtd->parent && !gclass->parent)
5658 mono_generic_class_setup_parent (gclass, gtd);
5664 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5666 mono_class_set_type_load_failure (klass, "%s", msg);
5667 mono_error_set_type_load_class (error, klass, "%s", msg);
5671 * mono_class_create_from_typedef:
5672 * @image: image where the token is valid
5673 * @type_token: typedef token
5674 * @error: used to return any error found while creating the type
5676 * Create the MonoClass* representing the specified type token.
5677 * @type_token must be a TypeDef token.
5679 * FIXME: don't return NULL on failure, just the the caller figure it out.
5682 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5684 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5685 MonoClass *klass, *parent = NULL;
5686 guint32 cols [MONO_TYPEDEF_SIZE];
5687 guint32 cols_next [MONO_TYPEDEF_SIZE];
5688 guint tidx = mono_metadata_token_index (type_token);
5689 MonoGenericContext *context = NULL;
5690 const char *name, *nspace;
5692 MonoClass **interfaces;
5693 guint32 field_last, method_last;
5694 guint32 nesting_tokeen;
5696 mono_error_init (error);
5698 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5699 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5703 mono_loader_lock ();
5705 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5706 mono_loader_unlock ();
5710 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5712 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5713 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5715 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5718 klass->name_space = nspace;
5720 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5722 klass->image = image;
5723 klass->type_token = type_token;
5724 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5726 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5728 classes_size += sizeof (MonoClass);
5731 * Check whether we're a generic type definition.
5733 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5734 if (klass->generic_container) {
5735 klass->is_generic = 1;
5736 klass->generic_container->owner.klass = klass;
5737 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5738 context = &klass->generic_container->context;
5741 if (klass->generic_container)
5742 enable_gclass_recording ();
5744 if (cols [MONO_TYPEDEF_EXTENDS]) {
5746 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5748 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5749 /*WARNING: this must satisfy mono_metadata_type_hash*/
5750 klass->this_arg.byref = 1;
5751 klass->this_arg.data.klass = klass;
5752 klass->this_arg.type = MONO_TYPE_CLASS;
5753 klass->byval_arg.data.klass = klass;
5754 klass->byval_arg.type = MONO_TYPE_CLASS;
5756 parent = mono_class_get_checked (image, parent_token, error);
5757 if (parent && context) /* Always inflate */
5758 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5760 if (parent == NULL) {
5761 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5762 goto parent_failure;
5765 for (tmp = parent; tmp; tmp = tmp->parent) {
5767 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5768 goto parent_failure;
5770 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5771 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5772 goto parent_failure;
5777 mono_class_setup_parent (klass, parent);
5779 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5780 mono_class_setup_mono_type (klass);
5782 if (klass->generic_container)
5783 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5786 * This might access klass->byval_arg for recursion generated by generic constraints,
5787 * so it has to come after setup_mono_type ().
5789 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5790 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5791 if (!mono_error_ok (error)) {
5792 /*FIXME implement a mono_class_set_failure_from_mono_error */
5793 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5794 mono_loader_unlock ();
5795 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5800 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5804 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5808 klass->cast_class = klass->element_class = klass;
5810 if (!klass->enumtype) {
5811 if (!mono_metadata_interfaces_from_typedef_full (
5812 image, type_token, &interfaces, &icount, FALSE, context, error)){
5814 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5815 mono_loader_unlock ();
5816 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5820 klass->interfaces = interfaces;
5821 klass->interface_count = icount;
5822 klass->interfaces_inited = 1;
5825 /*g_print ("Load class %s\n", name);*/
5828 * Compute the field and method lists
5830 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5831 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5833 if (tt->rows > tidx){
5834 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5835 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5836 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5838 field_last = image->tables [MONO_TABLE_FIELD].rows;
5839 method_last = image->tables [MONO_TABLE_METHOD].rows;
5842 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5843 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5844 klass->field.count = field_last - klass->field.first;
5846 klass->field.count = 0;
5848 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5849 klass->method.count = method_last - klass->method.first;
5851 klass->method.count = 0;
5853 /* reserve space to store vector pointer in arrays */
5854 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5855 klass->instance_size += 2 * sizeof (gpointer);
5856 g_assert (klass->field.count == 0);
5859 if (klass->enumtype) {
5860 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5861 if (!enum_basetype) {
5862 /*set it to a default value as the whole runtime can't handle this to be null*/
5863 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5864 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5865 mono_loader_unlock ();
5866 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5869 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5873 * If we're a generic type definition, load the constraints.
5874 * We must do this after the class has been constructed to make certain recursive scenarios
5877 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5878 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5879 mono_loader_unlock ();
5880 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5884 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5885 if (!strncmp (name, "Vector", 6))
5886 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");
5889 mono_loader_unlock ();
5891 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5896 mono_class_setup_mono_type (klass);
5897 mono_loader_unlock ();
5898 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5902 /** Is klass a Nullable<T> ginst? */
5904 mono_class_is_nullable (MonoClass *klass)
5906 return klass->generic_class != NULL &&
5907 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5911 /** if klass is T? return T */
5913 mono_class_get_nullable_param (MonoClass *klass)
5915 g_assert (mono_class_is_nullable (klass));
5916 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5920 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5924 MonoGenericClass *gclass = klass->generic_class;
5926 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5927 if (!mono_error_ok (&error)) {
5928 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5929 klass->parent = mono_defaults.object_class;
5930 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5931 mono_error_cleanup (&error);
5935 mono_class_setup_parent (klass, klass->parent);
5937 if (klass->enumtype) {
5938 klass->cast_class = gtd->cast_class;
5939 klass->element_class = gtd->element_class;
5945 * Create the `MonoClass' for an instantiation of a generic type.
5946 * We only do this if we actually need it.
5949 mono_generic_class_get_class (MonoGenericClass *gclass)
5951 MonoClass *klass, *gklass;
5953 if (gclass->cached_class)
5954 return gclass->cached_class;
5956 mono_loader_lock ();
5957 if (gclass->cached_class) {
5958 mono_loader_unlock ();
5959 return gclass->cached_class;
5962 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5964 gklass = gclass->container_class;
5966 if (record_gclass_instantiation > 0)
5967 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5969 if (gklass->nested_in) {
5970 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5971 klass->nested_in = gklass->nested_in;
5974 klass->name = gklass->name;
5975 klass->name_space = gklass->name_space;
5977 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5979 klass->image = gklass->image;
5980 klass->flags = gklass->flags;
5981 klass->type_token = gklass->type_token;
5982 klass->field.count = gklass->field.count;
5984 klass->is_inflated = 1;
5985 klass->generic_class = gclass;
5987 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5988 klass->this_arg.type = klass->byval_arg.type;
5989 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5990 klass->this_arg.byref = TRUE;
5991 klass->enumtype = gklass->enumtype;
5992 klass->valuetype = gklass->valuetype;
5994 klass->cast_class = klass->element_class = klass;
5996 if (mono_class_is_nullable (klass))
5997 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6000 * We're not interested in the nested classes of a generic instance.
6001 * We use the generic type definition to look for nested classes.
6004 mono_generic_class_setup_parent (klass, gklass);
6006 if (gclass->is_dynamic) {
6008 * 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.
6009 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6010 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6012 if (!gklass->wastypebuilder)
6015 mono_class_setup_supertypes (klass);
6017 if (klass->enumtype) {
6019 * For enums, gklass->fields might not been set, but instance_size etc. is
6020 * already set in mono_reflection_create_internal_class (). For non-enums,
6021 * these will be computed normally in mono_class_layout_fields ().
6023 klass->instance_size = gklass->instance_size;
6024 klass->sizes.class_size = gklass->sizes.class_size;
6025 mono_memory_barrier ();
6026 klass->size_inited = 1;
6030 mono_memory_barrier ();
6031 gclass->cached_class = klass;
6033 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6035 inflated_classes ++;
6036 inflated_classes_size += sizeof (MonoClass);
6038 mono_loader_unlock ();
6044 get_image_for_container (MonoGenericContainer *container)
6047 if (container->is_anonymous) {
6048 result = container->owner.image;
6051 if (container->is_method) {
6052 MonoMethod *method = container->owner.method;
6053 g_assert_checked (method);
6054 klass = method->klass;
6056 klass = container->owner.klass;
6058 g_assert_checked (klass);
6059 result = klass->image;
6066 get_image_for_generic_param (MonoGenericParam *param)
6068 MonoGenericContainer *container = mono_generic_param_owner (param);
6069 g_assert_checked (container);
6070 return get_image_for_container (container);
6073 // Make a string in the designated image consisting of a single integer.
6074 #define INT_STRING_SIZE 16
6076 make_generic_name_string (MonoImage *image, int num)
6078 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6079 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6083 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6084 // pinfo is derived from param by the caller for us.
6086 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6088 MonoClass *klass, **ptr;
6090 MonoGenericContainer *container = mono_generic_param_owner (param);
6091 g_assert_checked (container);
6093 MonoImage *image = get_image_for_container (container);
6094 gboolean is_mvar = container->is_method;
6095 gboolean is_anonymous = container->is_anonymous;
6097 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6098 classes_size += sizeof (MonoClass);
6101 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6103 int n = mono_generic_param_num (param);
6104 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6108 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6109 } else if (is_mvar) {
6110 MonoMethod *omethod = container->owner.method;
6111 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6113 MonoClass *oklass = container->owner.klass;
6114 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6117 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6119 // Count non-NULL items in pinfo->constraints
6122 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6126 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6127 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6129 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6130 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6132 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6135 if (count - pos > 0) {
6136 klass->interface_count = count - pos;
6137 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6138 klass->interfaces_inited = TRUE;
6139 for (i = pos; i < count; i++)
6140 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6143 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6145 klass->inited = TRUE;
6146 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6147 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6148 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6150 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6151 klass->this_arg.type = klass->byval_arg.type;
6152 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6153 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6154 klass->this_arg.byref = TRUE;
6156 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6157 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6159 /*Init these fields to sane values*/
6160 klass->min_align = 1;
6162 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6163 * constrained to, the JIT depends on this.
6165 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6166 mono_memory_barrier ();
6167 klass->size_inited = 1;
6169 mono_class_setup_supertypes (klass);
6171 if (count - pos > 0) {
6172 mono_class_setup_vtable (klass->parent);
6173 if (mono_class_has_failure (klass->parent))
6174 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6176 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6182 #define FAST_CACHE_SIZE 16
6185 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6186 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6187 * we cache the MonoClasses.
6188 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6189 * LOCKING: Takes the image lock depending on @take_lock.
6192 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6194 int n = mono_generic_param_num (param);
6195 MonoImage *image = get_image_for_generic_param (param);
6196 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6197 MonoClass *klass = NULL;
6202 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6203 // For high numbers or constraints we have to use pointer hashes.
6204 if (param->gshared_constraint) {
6205 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6208 mono_image_lock (image);
6209 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6211 mono_image_unlock (image);
6216 if (n < FAST_CACHE_SIZE) {
6218 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6220 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6222 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6225 mono_image_lock (image);
6226 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6228 mono_image_unlock (image);
6235 * LOCKING: Image lock (param->image) must be held
6238 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6240 int n = mono_generic_param_num (param);
6241 MonoImage *image = get_image_for_generic_param (param);
6242 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6246 if (param->gshared_constraint) {
6247 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6249 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6250 mono_memory_barrier ();
6252 image->mvar_cache_constrained = ht;
6254 image->var_cache_constrained = ht;
6256 g_hash_table_insert (ht, param, klass);
6257 } else if (n < FAST_CACHE_SIZE) {
6259 /* Requires locking to avoid droping an already published class */
6260 if (!image->mvar_cache_fast)
6261 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6262 image->mvar_cache_fast [n] = klass;
6264 if (!image->var_cache_fast)
6265 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6266 image->var_cache_fast [n] = klass;
6269 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6271 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6273 ht = g_hash_table_new (NULL, NULL);
6274 mono_memory_barrier ();
6276 image->mvar_cache_slow = ht;
6278 image->var_cache_slow = ht;
6281 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6286 * LOCKING: Acquires the image lock (@image).
6289 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6291 MonoImage *image = get_image_for_generic_param (param);
6292 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6293 MonoClass *klass, *klass2;
6295 // If a klass already exists for this object and is cached, return it.
6296 if (pinfo) // Non-anonymous
6297 klass = pinfo->pklass;
6299 klass = get_anon_gparam_class (param, TRUE);
6304 // Create a new klass
6305 klass = make_generic_param_class (param, pinfo);
6307 // Now we need to cache the klass we created.
6308 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6309 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6310 // and allow our newly-created klass object to just leak.
6311 mono_memory_barrier ();
6313 mono_image_lock (image);
6315 // Here "klass2" refers to the klass potentially created by the other thread.
6316 if (pinfo) // Repeat check from above
6317 klass2 = pinfo->pklass;
6319 klass2 = get_anon_gparam_class (param, FALSE);
6326 pinfo->pklass = klass;
6328 set_anon_gparam_class (param, klass);
6330 mono_image_unlock (image);
6332 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6334 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6336 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6342 * mono_class_from_generic_parameter:
6343 * @param: Parameter to find/construct a class for.
6344 * @arg2: Is ignored.
6345 * @arg3: Is ignored.
6348 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6350 return mono_class_from_generic_parameter_internal (param);
6355 mono_ptr_class_get (MonoType *type)
6358 MonoClass *el_class;
6362 el_class = mono_class_from_mono_type (type);
6363 image = el_class->image;
6365 mono_image_lock (image);
6366 if (image->ptr_cache) {
6367 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6368 mono_image_unlock (image);
6372 mono_image_unlock (image);
6374 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6376 classes_size += sizeof (MonoClass);
6378 result->parent = NULL; /* no parent for PTR types */
6379 result->name_space = el_class->name_space;
6380 name = g_strdup_printf ("%s*", el_class->name);
6381 result->name = mono_image_strdup (image, name);
6384 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6386 result->image = el_class->image;
6387 result->inited = TRUE;
6388 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6389 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6390 result->cast_class = result->element_class = el_class;
6391 result->blittable = TRUE;
6393 result->byval_arg.type = MONO_TYPE_PTR;
6394 result->this_arg.type = result->byval_arg.type;
6395 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6396 result->this_arg.byref = TRUE;
6398 mono_class_setup_supertypes (result);
6400 mono_image_lock (image);
6401 if (image->ptr_cache) {
6403 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6404 mono_image_unlock (image);
6405 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6409 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6411 g_hash_table_insert (image->ptr_cache, el_class, result);
6412 mono_image_unlock (image);
6414 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6420 mono_fnptr_class_get (MonoMethodSignature *sig)
6423 static GHashTable *ptr_hash = NULL;
6425 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6427 mono_loader_lock ();
6430 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6432 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6433 mono_loader_unlock ();
6436 result = g_new0 (MonoClass, 1);
6438 result->parent = NULL; /* no parent for PTR types */
6439 result->name_space = "System";
6440 result->name = "MonoFNPtrFakeClass";
6442 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6444 result->image = mono_defaults.corlib; /* need to fix... */
6445 result->inited = TRUE;
6446 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6447 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6448 result->cast_class = result->element_class = result;
6449 result->blittable = TRUE;
6451 result->byval_arg.type = MONO_TYPE_FNPTR;
6452 result->this_arg.type = result->byval_arg.type;
6453 result->this_arg.data.method = result->byval_arg.data.method = sig;
6454 result->this_arg.byref = TRUE;
6455 result->blittable = TRUE;
6457 mono_class_setup_supertypes (result);
6459 g_hash_table_insert (ptr_hash, sig, result);
6461 mono_loader_unlock ();
6463 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6469 * mono_class_from_mono_type:
6470 * @type: describes the type to return
6472 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6475 mono_class_from_mono_type (MonoType *type)
6477 switch (type->type) {
6478 case MONO_TYPE_OBJECT:
6479 return type->data.klass? type->data.klass: mono_defaults.object_class;
6480 case MONO_TYPE_VOID:
6481 return type->data.klass? type->data.klass: mono_defaults.void_class;
6482 case MONO_TYPE_BOOLEAN:
6483 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6484 case MONO_TYPE_CHAR:
6485 return type->data.klass? type->data.klass: mono_defaults.char_class;
6487 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6489 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6491 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6493 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6495 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6497 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6499 return type->data.klass? type->data.klass: mono_defaults.int_class;
6501 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6503 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6505 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6507 return type->data.klass? type->data.klass: mono_defaults.single_class;
6509 return type->data.klass? type->data.klass: mono_defaults.double_class;
6510 case MONO_TYPE_STRING:
6511 return type->data.klass? type->data.klass: mono_defaults.string_class;
6512 case MONO_TYPE_TYPEDBYREF:
6513 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6514 case MONO_TYPE_ARRAY:
6515 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6517 return mono_ptr_class_get (type->data.type);
6518 case MONO_TYPE_FNPTR:
6519 return mono_fnptr_class_get (type->data.method);
6520 case MONO_TYPE_SZARRAY:
6521 return mono_array_class_get (type->data.klass, 1);
6522 case MONO_TYPE_CLASS:
6523 case MONO_TYPE_VALUETYPE:
6524 return type->data.klass;
6525 case MONO_TYPE_GENERICINST:
6526 return mono_generic_class_get_class (type->data.generic_class);
6527 case MONO_TYPE_MVAR:
6529 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6531 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6532 g_assert_not_reached ();
6535 // Yes, this returns NULL, even if it is documented as not doing so, but there
6536 // is no way for the code to make it this far, due to the assert above.
6541 * mono_type_retrieve_from_typespec
6542 * @image: context where the image is created
6543 * @type_spec: typespec token
6544 * @context: the generic context used to evaluate generic instantiations in
6547 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6549 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6551 *did_inflate = FALSE;
6556 if (context && (context->class_inst || context->method_inst)) {
6557 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6559 if (!mono_error_ok (error)) {
6565 *did_inflate = TRUE;
6572 * mono_class_create_from_typespec
6573 * @image: context where the image is created
6574 * @type_spec: typespec token
6575 * @context: the generic context used to evaluate generic instantiations in
6578 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6581 gboolean inflated = FALSE;
6582 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6583 return_val_if_nok (error, NULL);
6584 ret = mono_class_from_mono_type (t);
6586 mono_metadata_free_type (t);
6591 * mono_bounded_array_class_get:
6592 * @element_class: element class
6593 * @rank: the dimension of the array class
6594 * @bounded: whenever the array has non-zero bounds
6596 * Returns: A class object describing the array with element type @element_type and
6600 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6604 MonoClass *parent = NULL;
6605 GSList *list, *rootlist = NULL;
6609 g_assert (rank <= 255);
6612 /* bounded only matters for one-dimensional arrays */
6615 image = eclass->image;
6617 if (rank == 1 && !bounded) {
6619 * This case is very frequent not just during compilation because of calls
6620 * from mono_class_from_mono_type (), mono_array_new (),
6621 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6623 mono_os_mutex_lock (&image->szarray_cache_lock);
6624 if (!image->szarray_cache)
6625 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6626 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6627 mono_os_mutex_unlock (&image->szarray_cache_lock);
6631 mono_loader_lock ();
6633 mono_loader_lock ();
6635 if (!image->array_cache)
6636 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6638 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6639 for (; list; list = list->next) {
6640 klass = (MonoClass *)list->data;
6641 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6642 mono_loader_unlock ();
6649 parent = mono_defaults.array_class;
6650 if (!parent->inited)
6651 mono_class_init (parent);
6653 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6655 klass->image = image;
6656 klass->name_space = eclass->name_space;
6657 nsize = strlen (eclass->name);
6658 name = (char *)g_malloc (nsize + 2 + rank + 1);
6659 memcpy (name, eclass->name, nsize);
6662 memset (name + nsize + 1, ',', rank - 1);
6664 name [nsize + rank] = '*';
6665 name [nsize + rank + bounded] = ']';
6666 name [nsize + rank + bounded + 1] = 0;
6667 klass->name = mono_image_strdup (image, name);
6670 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6672 classes_size += sizeof (MonoClass);
6674 klass->type_token = 0;
6675 /* all arrays are marked serializable and sealed, bug #42779 */
6676 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6677 klass->parent = parent;
6678 klass->instance_size = mono_class_instance_size (klass->parent);
6680 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6681 /*Arrays of those two types are invalid.*/
6682 MonoError prepared_error;
6683 mono_error_init (&prepared_error);
6684 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6685 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6686 mono_error_cleanup (&prepared_error);
6687 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6688 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6689 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6690 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6692 /* element_size -1 is ok as this is not an instantitable type*/
6693 klass->sizes.element_size = -1;
6695 klass->sizes.element_size = mono_class_array_element_size (eclass);
6697 mono_class_setup_supertypes (klass);
6699 if (eclass->generic_class)
6700 mono_class_init (eclass);
6701 if (!eclass->size_inited)
6702 mono_class_setup_fields (eclass);
6703 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6704 /*FIXME we fail the array type, but we have to let other fields be set.*/
6706 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6710 if (eclass->enumtype)
6711 klass->cast_class = eclass->element_class;
6713 klass->cast_class = eclass;
6715 switch (klass->cast_class->byval_arg.type) {
6717 klass->cast_class = mono_defaults.byte_class;
6720 klass->cast_class = mono_defaults.int16_class;
6723 #if SIZEOF_VOID_P == 4
6727 klass->cast_class = mono_defaults.int32_class;
6730 #if SIZEOF_VOID_P == 8
6734 klass->cast_class = mono_defaults.int64_class;
6740 klass->element_class = eclass;
6742 if ((rank > 1) || bounded) {
6743 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6744 klass->byval_arg.type = MONO_TYPE_ARRAY;
6745 klass->byval_arg.data.array = at;
6746 at->eklass = eclass;
6748 /* FIXME: complete.... */
6750 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6751 klass->byval_arg.data.klass = eclass;
6753 klass->this_arg = klass->byval_arg;
6754 klass->this_arg.byref = 1;
6756 klass->generic_container = eclass->generic_container;
6758 if (rank == 1 && !bounded) {
6759 MonoClass *prev_class;
6761 mono_os_mutex_lock (&image->szarray_cache_lock);
6762 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6764 /* Someone got in before us */
6767 g_hash_table_insert (image->szarray_cache, eclass, klass);
6768 mono_os_mutex_unlock (&image->szarray_cache_lock);
6770 list = g_slist_append (rootlist, klass);
6771 g_hash_table_insert (image->array_cache, eclass, list);
6774 mono_loader_unlock ();
6776 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6782 * mono_array_class_get:
6783 * @element_class: element class
6784 * @rank: the dimension of the array class
6786 * Returns: A class object describing the array with element type @element_type and
6790 mono_array_class_get (MonoClass *eclass, guint32 rank)
6792 return mono_bounded_array_class_get (eclass, rank, FALSE);
6796 * mono_class_instance_size:
6799 * Use to get the size of a class in bytes.
6801 * Returns: The size of an object instance
6804 mono_class_instance_size (MonoClass *klass)
6806 if (!klass->size_inited)
6807 mono_class_init (klass);
6809 return klass->instance_size;
6813 * mono_class_min_align:
6816 * Use to get the computed minimum alignment requirements for the specified class.
6818 * Returns: minimm alignment requirements
6821 mono_class_min_align (MonoClass *klass)
6823 if (!klass->size_inited)
6824 mono_class_init (klass);
6826 return klass->min_align;
6830 * mono_class_value_size:
6833 * This function is used for value types, and return the
6834 * space and the alignment to store that kind of value object.
6836 * Returns: the size of a value of kind @klass
6839 mono_class_value_size (MonoClass *klass, guint32 *align)
6843 /* fixme: check disable, because we still have external revereces to
6844 * mscorlib and Dummy Objects
6846 /*g_assert (klass->valuetype);*/
6848 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6851 *align = klass->min_align;
6857 * mono_class_data_size:
6860 * Returns: The size of the static class data
6863 mono_class_data_size (MonoClass *klass)
6866 mono_class_init (klass);
6867 /* This can happen with dynamically created types */
6868 if (!klass->fields_inited)
6869 mono_class_setup_fields (klass);
6871 /* in arrays, sizes.class_size is unioned with element_size
6872 * and arrays have no static fields
6876 return klass->sizes.class_size;
6880 * Auxiliary routine to mono_class_get_field
6882 * Takes a field index instead of a field token.
6884 static MonoClassField *
6885 mono_class_get_field_idx (MonoClass *klass, int idx)
6887 mono_class_setup_fields (klass);
6888 if (mono_class_has_failure (klass))
6892 if (klass->image->uncompressed_metadata) {
6894 * klass->field.first points to the FieldPtr table, while idx points into the
6895 * Field table, so we have to do a search.
6897 /*FIXME this is broken for types with multiple fields with the same name.*/
6898 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6901 for (i = 0; i < klass->field.count; ++i)
6902 if (mono_field_get_name (&klass->fields [i]) == name)
6903 return &klass->fields [i];
6904 g_assert_not_reached ();
6906 if (klass->field.count) {
6907 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6908 return &klass->fields [idx - klass->field.first];
6912 klass = klass->parent;
6918 * mono_class_get_field:
6919 * @class: the class to lookup the field.
6920 * @field_token: the field token
6922 * Returns: A MonoClassField representing the type and offset of
6923 * the field, or a NULL value if the field does not belong to this
6927 mono_class_get_field (MonoClass *klass, guint32 field_token)
6929 int idx = mono_metadata_token_index (field_token);
6931 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6933 return mono_class_get_field_idx (klass, idx - 1);
6937 * mono_class_get_field_from_name:
6938 * @klass: the class to lookup the field.
6939 * @name: the field name
6941 * Search the class @klass and it's parents for a field with the name @name.
6943 * Returns: The MonoClassField pointer of the named field or NULL
6946 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6948 return mono_class_get_field_from_name_full (klass, name, NULL);
6952 * mono_class_get_field_from_name_full:
6953 * @klass: the class to lookup the field.
6954 * @name: the field name
6955 * @type: the type of the fields. This optional.
6957 * Search the class @klass and it's parents for a field with the name @name and type @type.
6959 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6960 * of its generic type definition.
6962 * Returns: The MonoClassField pointer of the named field or NULL
6965 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6969 mono_class_setup_fields (klass);
6970 if (mono_class_has_failure (klass))
6974 for (i = 0; i < klass->field.count; ++i) {
6975 MonoClassField *field = &klass->fields [i];
6977 if (strcmp (name, mono_field_get_name (field)) != 0)
6981 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6982 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6987 klass = klass->parent;
6993 * mono_class_get_field_token:
6994 * @field: the field we need the token of
6996 * Get the token of a field. Note that the tokesn is only valid for the image
6997 * the field was loaded from. Don't use this function for fields in dynamic types.
6999 * Returns: The token representing the field in the image it was loaded from.
7002 mono_class_get_field_token (MonoClassField *field)
7004 MonoClass *klass = field->parent;
7007 mono_class_setup_fields (klass);
7012 for (i = 0; i < klass->field.count; ++i) {
7013 if (&klass->fields [i] == field) {
7014 int idx = klass->field.first + i + 1;
7016 if (klass->image->uncompressed_metadata)
7017 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7018 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7021 klass = klass->parent;
7024 g_assert_not_reached ();
7029 mono_field_get_index (MonoClassField *field)
7031 int index = field - field->parent->fields;
7033 g_assert (index >= 0 && index < field->parent->field.count);
7039 * mono_class_get_field_default_value:
7041 * Return the default value of the field as a pointer into the metadata blob.
7044 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7047 guint32 constant_cols [MONO_CONSTANT_SIZE];
7049 MonoClass *klass = field->parent;
7051 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7053 if (!klass->ext || !klass->ext->field_def_values) {
7054 MonoFieldDefaultValue *def_values;
7056 mono_class_alloc_ext (klass);
7058 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7060 mono_image_lock (klass->image);
7061 mono_memory_barrier ();
7062 if (!klass->ext->field_def_values)
7063 klass->ext->field_def_values = def_values;
7064 mono_image_unlock (klass->image);
7067 field_index = mono_field_get_index (field);
7069 if (!klass->ext->field_def_values [field_index].data) {
7070 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7074 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7076 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7077 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7078 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7081 *def_type = klass->ext->field_def_values [field_index].def_type;
7082 return klass->ext->field_def_values [field_index].data;
7086 mono_property_get_index (MonoProperty *prop)
7088 int index = prop - prop->parent->ext->properties;
7090 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7096 * mono_class_get_property_default_value:
7098 * Return the default value of the field as a pointer into the metadata blob.
7101 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7104 guint32 constant_cols [MONO_CONSTANT_SIZE];
7105 MonoClass *klass = property->parent;
7107 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7109 * We don't cache here because it is not used by C# so it's quite rare, but
7110 * we still do the lookup in klass->ext because that is where the data
7111 * is stored for dynamic assemblies.
7114 if (image_is_dynamic (klass->image)) {
7115 int prop_index = mono_property_get_index (property);
7116 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7117 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7118 return klass->ext->prop_def_values [prop_index].data;
7122 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7126 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7127 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7128 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7132 mono_class_get_event_token (MonoEvent *event)
7134 MonoClass *klass = event->parent;
7139 for (i = 0; i < klass->ext->event.count; ++i) {
7140 if (&klass->ext->events [i] == event)
7141 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7144 klass = klass->parent;
7147 g_assert_not_reached ();
7152 * mono_class_get_property_from_name:
7154 * @name: name of the property to lookup in the specified class
7156 * Use this method to lookup a property in a class
7157 * Returns: the MonoProperty with the given name, or NULL if the property
7158 * does not exist on the @klass.
7161 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7165 gpointer iter = NULL;
7166 while ((p = mono_class_get_properties (klass, &iter))) {
7167 if (! strcmp (name, p->name))
7170 klass = klass->parent;
7176 * mono_class_get_property_token:
7177 * @prop: MonoProperty to query
7179 * Returns: The ECMA token for the specified property.
7182 mono_class_get_property_token (MonoProperty *prop)
7184 MonoClass *klass = prop->parent;
7188 gpointer iter = NULL;
7189 while ((p = mono_class_get_properties (klass, &iter))) {
7190 if (&klass->ext->properties [i] == prop)
7191 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7195 klass = klass->parent;
7198 g_assert_not_reached ();
7203 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7205 const char *name, *nspace;
7206 if (image_is_dynamic (image))
7207 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7209 switch (type_token & 0xff000000){
7210 case MONO_TOKEN_TYPE_DEF: {
7211 guint32 cols [MONO_TYPEDEF_SIZE];
7212 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7213 guint tidx = mono_metadata_token_index (type_token);
7215 if (tidx > tt->rows)
7216 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7218 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7219 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7220 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7221 if (strlen (nspace) == 0)
7222 return g_strdup_printf ("%s", name);
7224 return g_strdup_printf ("%s.%s", nspace, name);
7227 case MONO_TOKEN_TYPE_REF: {
7229 guint32 cols [MONO_TYPEREF_SIZE];
7230 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7231 guint tidx = mono_metadata_token_index (type_token);
7234 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7236 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7237 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7238 mono_error_cleanup (&error);
7242 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7243 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7244 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7245 if (strlen (nspace) == 0)
7246 return g_strdup_printf ("%s", name);
7248 return g_strdup_printf ("%s.%s", nspace, name);
7251 case MONO_TOKEN_TYPE_SPEC:
7252 return g_strdup_printf ("Typespec 0x%08x", type_token);
7254 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7259 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7261 if (image_is_dynamic (image))
7262 return g_strdup_printf ("DynamicAssembly %s", image->name);
7264 switch (type_token & 0xff000000){
7265 case MONO_TOKEN_TYPE_DEF:
7266 if (image->assembly)
7267 return mono_stringify_assembly_name (&image->assembly->aname);
7268 else if (image->assembly_name)
7269 return g_strdup (image->assembly_name);
7270 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7271 case MONO_TOKEN_TYPE_REF: {
7273 MonoAssemblyName aname;
7274 guint32 cols [MONO_TYPEREF_SIZE];
7275 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7276 guint32 idx = mono_metadata_token_index (type_token);
7279 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7281 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7282 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7283 mono_error_cleanup (&error);
7286 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7288 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7289 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7290 case MONO_RESOLUTION_SCOPE_MODULE:
7292 return g_strdup ("");
7293 case MONO_RESOLUTION_SCOPE_MODULEREF:
7295 return g_strdup ("");
7296 case MONO_RESOLUTION_SCOPE_TYPEREF:
7298 return g_strdup ("");
7299 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7300 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7301 return mono_stringify_assembly_name (&aname);
7303 g_assert_not_reached ();
7307 case MONO_TOKEN_TYPE_SPEC:
7309 return g_strdup ("");
7311 g_assert_not_reached ();
7318 * mono_class_get_full:
7319 * @image: the image where the class resides
7320 * @type_token: the token for the class
7321 * @context: the generic context used to evaluate generic instantiations in
7322 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7324 * Returns: The MonoClass that represents @type_token in @image
7327 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7331 klass = mono_class_get_checked (image, type_token, &error);
7333 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7334 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7336 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7342 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7346 mono_error_init (error);
7347 klass = mono_class_get_checked (image, type_token, error);
7349 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7350 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7355 * mono_class_get_checked:
7356 * @image: the image where the class resides
7357 * @type_token: the token for the class
7358 * @error: error object to return any error
7360 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7363 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7365 MonoClass *klass = NULL;
7367 mono_error_init (error);
7369 if (image_is_dynamic (image)) {
7370 int table = mono_metadata_token_table (type_token);
7372 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7373 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7376 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7380 switch (type_token & 0xff000000){
7381 case MONO_TOKEN_TYPE_DEF:
7382 klass = mono_class_create_from_typedef (image, type_token, error);
7384 case MONO_TOKEN_TYPE_REF:
7385 klass = mono_class_from_typeref_checked (image, type_token, error);
7387 case MONO_TOKEN_TYPE_SPEC:
7388 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7391 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7395 /* Generic case, should be avoided for when a better error is possible. */
7396 if (!klass && mono_error_ok (error)) {
7397 char *name = mono_class_name_from_token (image, type_token);
7398 char *assembly = mono_assembly_name_from_token (image, type_token);
7399 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7407 * mono_type_get_checked:
7408 * @image: the image where the type resides
7409 * @type_token: the token for the type
7410 * @context: the generic context used to evaluate generic instantiations in
7411 * @error: Error handling context
7413 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7415 * Returns: The MonoType that represents @type_token in @image
7418 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7420 MonoType *type = NULL;
7421 gboolean inflated = FALSE;
7423 mono_error_init (error);
7425 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7426 if (image_is_dynamic (image)) {
7427 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7428 return_val_if_nok (error, NULL);
7429 return mono_class_get_type (klass);
7432 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7433 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7440 return mono_class_get_type (klass);
7443 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7450 MonoType *tmp = type;
7451 type = mono_class_get_type (mono_class_from_mono_type (type));
7452 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7453 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7454 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7456 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7458 if (type->type != tmp->type)
7461 mono_metadata_free_type (tmp);
7468 * @image: image where the class token will be looked up.
7469 * @type_token: a type token from the image
7471 * Returns the MonoClass with the given @type_token on the @image
7474 mono_class_get (MonoImage *image, guint32 type_token)
7476 return mono_class_get_full (image, type_token, NULL);
7480 * mono_image_init_name_cache:
7482 * Initializes the class name cache stored in image->name_cache.
7484 * LOCKING: Acquires the corresponding image lock.
7487 mono_image_init_name_cache (MonoImage *image)
7489 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7490 guint32 cols [MONO_TYPEDEF_SIZE];
7493 guint32 i, visib, nspace_index;
7494 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7496 if (image->name_cache)
7499 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7501 if (image_is_dynamic (image)) {
7502 mono_image_lock (image);
7503 if (image->name_cache) {
7504 /* Somebody initialized it before us */
7505 g_hash_table_destroy (the_name_cache);
7507 mono_atomic_store_release (&image->name_cache, the_name_cache);
7509 mono_image_unlock (image);
7513 /* Temporary hash table to avoid lookups in the nspace_table */
7514 name_cache2 = g_hash_table_new (NULL, NULL);
7516 for (i = 1; i <= t->rows; ++i) {
7517 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7518 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7520 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7521 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7523 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7525 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7526 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7528 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7529 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7530 if (!nspace_table) {
7531 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7532 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7533 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7536 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7539 /* Load type names from EXPORTEDTYPES table */
7541 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7542 guint32 cols [MONO_EXP_TYPE_SIZE];
7545 for (i = 0; i < t->rows; ++i) {
7546 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7548 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7549 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7553 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7554 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7556 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7557 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7558 if (!nspace_table) {
7559 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7560 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7561 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7564 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7568 g_hash_table_destroy (name_cache2);
7570 mono_image_lock (image);
7571 if (image->name_cache) {
7572 /* Somebody initialized it before us */
7573 g_hash_table_destroy (the_name_cache);
7575 mono_atomic_store_release (&image->name_cache, the_name_cache);
7577 mono_image_unlock (image);
7580 /*FIXME Only dynamic assemblies should allow this operation.*/
7582 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7583 const char *name, guint32 index)
7585 GHashTable *nspace_table;
7586 GHashTable *name_cache;
7589 mono_image_init_name_cache (image);
7590 mono_image_lock (image);
7592 name_cache = image->name_cache;
7593 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7594 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7595 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7598 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7599 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7601 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7603 mono_image_unlock (image);
7612 find_nocase (gpointer key, gpointer value, gpointer user_data)
7614 char *name = (char*)key;
7615 FindUserData *data = (FindUserData*)user_data;
7617 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7618 data->value = value;
7622 * mono_class_from_name_case:
7623 * @image: The MonoImage where the type is looked up in
7624 * @name_space: the type namespace
7625 * @name: the type short name.
7626 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7628 * Obtains a MonoClass with a given namespace and a given name which
7629 * is located in the given MonoImage. The namespace and name
7630 * lookups are case insensitive.
7633 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7636 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7637 mono_error_cleanup (&error);
7643 * mono_class_from_name_case:
7644 * @image: The MonoImage where the type is looked up in
7645 * @name_space: the type namespace
7646 * @name: the type short name.
7649 * Obtains a MonoClass with a given namespace and a given name which
7650 * is located in the given MonoImage. The namespace and name
7651 * lookups are case insensitive.
7653 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7654 * was not found. The @error object will contain information about the problem
7658 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7660 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7661 guint32 cols [MONO_TYPEDEF_SIZE];
7666 mono_error_init (error);
7668 if (image_is_dynamic (image)) {
7670 FindUserData user_data;
7672 mono_image_init_name_cache (image);
7673 mono_image_lock (image);
7675 user_data.key = name_space;
7676 user_data.value = NULL;
7677 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7679 if (user_data.value) {
7680 GHashTable *nspace_table = (GHashTable*)user_data.value;
7682 user_data.key = name;
7683 user_data.value = NULL;
7685 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7687 if (user_data.value)
7688 token = GPOINTER_TO_UINT (user_data.value);
7691 mono_image_unlock (image);
7694 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7700 /* add a cache if needed */
7701 for (i = 1; i <= t->rows; ++i) {
7702 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7703 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7705 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7706 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7708 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7710 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7711 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7712 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7713 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7719 return_nested_in (MonoClass *klass, char *nested)
7722 char *s = strchr (nested, '/');
7723 gpointer iter = NULL;
7730 while ((found = mono_class_get_nested_types (klass, &iter))) {
7731 if (strcmp (found->name, nested) == 0) {
7733 return return_nested_in (found, s);
7741 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7743 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7744 MonoImage *file_image;
7748 mono_error_init (error);
7751 * The EXPORTEDTYPES table only contains public types, so have to search the
7753 * Note: image->modules contains the contents of the MODULEREF table, while
7754 * the real module list is in the FILE table.
7756 for (i = 0; i < file_table->rows; i++) {
7757 guint32 cols [MONO_FILE_SIZE];
7758 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7759 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7762 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7764 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7765 if (klass || !is_ok (error))
7774 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7776 GHashTable *nspace_table;
7777 MonoImage *loaded_image;
7784 mono_error_init (error);
7786 // Checking visited images avoids stack overflows when cyclic references exist.
7787 if (g_hash_table_lookup (visited_images, image))
7790 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7792 if ((nested = strchr (name, '/'))) {
7793 int pos = nested - name;
7794 int len = strlen (name);
7797 memcpy (buf, name, len + 1);
7799 nested = buf + pos + 1;
7803 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7804 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7805 gboolean res = get_class_from_name (image, name_space, name, &klass);
7808 klass = search_modules (image, name_space, name, error);
7813 return klass ? return_nested_in (klass, nested) : NULL;
7819 mono_image_init_name_cache (image);
7820 mono_image_lock (image);
7822 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7825 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7827 mono_image_unlock (image);
7829 if (!token && image_is_dynamic (image) && image->modules) {
7830 /* Search modules as well */
7831 for (i = 0; i < image->module_count; ++i) {
7832 MonoImage *module = image->modules [i];
7834 klass = mono_class_from_name_checked (module, name_space, name, error);
7835 if (klass || !is_ok (error))
7841 klass = search_modules (image, name_space, name, error);
7842 if (klass || !is_ok (error))
7847 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7848 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7849 guint32 cols [MONO_EXP_TYPE_SIZE];
7852 idx = mono_metadata_token_index (token);
7854 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7856 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7857 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7858 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7861 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7863 return klass ? return_nested_in (klass, nested) : NULL;
7865 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7866 guint32 assembly_idx;
7868 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7870 mono_assembly_load_reference (image, assembly_idx - 1);
7871 g_assert (image->references [assembly_idx - 1]);
7872 if (image->references [assembly_idx - 1] == (gpointer)-1)
7874 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7876 return klass ? return_nested_in (klass, nested) : NULL;
7879 g_assert_not_reached ();
7883 token = MONO_TOKEN_TYPE_DEF | token;
7885 klass = mono_class_get_checked (image, token, error);
7887 return return_nested_in (klass, nested);
7892 * mono_class_from_name_checked:
7893 * @image: The MonoImage where the type is looked up in
7894 * @name_space: the type namespace
7895 * @name: the type short name.
7897 * Obtains a MonoClass with a given namespace and a given name which
7898 * is located in the given MonoImage.
7900 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7901 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7904 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7907 GHashTable *visited_images;
7909 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7911 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7913 g_hash_table_destroy (visited_images);
7919 * mono_class_from_name:
7920 * @image: The MonoImage where the type is looked up in
7921 * @name_space: the type namespace
7922 * @name: the type short name.
7924 * Obtains a MonoClass with a given namespace and a given name which
7925 * is located in the given MonoImage.
7927 * To reference nested classes, use the "/" character as a separator.
7928 * For example use "Foo/Bar" to reference the class Bar that is nested
7929 * inside Foo, like this: "class Foo { class Bar {} }".
7932 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7937 klass = mono_class_from_name_checked (image, name_space, name, &error);
7938 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7944 * mono_class_load_from_name:
7945 * @image: The MonoImage where the type is looked up in
7946 * @name_space: the type namespace
7947 * @name: the type short name.
7949 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7950 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7951 * If they are missing. Thing of System.Object or System.String.
7954 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7959 klass = mono_class_from_name_checked (image, name_space, name, &error);
7961 g_error ("Runtime critical type %s.%s not found", name_space, name);
7962 if (!mono_error_ok (&error))
7963 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7968 * mono_class_try_load_from_name:
7969 * @image: The MonoImage where the type is looked up in
7970 * @name_space: the type namespace
7971 * @name: the type short name.
7973 * This function tries to load a type, returning the class was found or NULL otherwise.
7974 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7976 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7977 * a type that we would otherwise assume to be available but was not due some error.
7981 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7986 klass = mono_class_from_name_checked (image, name_space, name, &error);
7987 if (!mono_error_ok (&error))
7988 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7994 * mono_class_is_subclass_of:
7995 * @klass: class to probe if it is a subclass of another one
7996 * @klassc: the class we suspect is the base class
7997 * @check_interfaces: whether we should perform interface checks
7999 * This method determines whether @klass is a subclass of @klassc.
8001 * If the @check_interfaces flag is set, then if @klassc is an interface
8002 * this method return TRUE if the @klass implements the interface or
8003 * if @klass is an interface, if one of its base classes is @klass.
8005 * If @check_interfaces is false then, then if @klass is not an interface
8006 * then it returns TRUE if the @klass is a subclass of @klassc.
8008 * if @klass is an interface and @klassc is System.Object, then this function
8013 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8014 gboolean check_interfaces)
8016 /* FIXME test for interfaces with variant generic arguments */
8017 mono_class_init (klass);
8018 mono_class_init (klassc);
8020 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8021 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8023 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8026 for (i = 0; i < klass->interface_count; i ++) {
8027 MonoClass *ic = klass->interfaces [i];
8032 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8037 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8040 if (klassc == mono_defaults.object_class)
8047 mono_type_is_generic_argument (MonoType *type)
8049 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8053 mono_class_has_variant_generic_params (MonoClass *klass)
8056 MonoGenericContainer *container;
8058 if (!klass->generic_class)
8061 container = klass->generic_class->container_class->generic_container;
8063 for (i = 0; i < container->type_argc; ++i)
8064 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8071 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8073 if (target == candidate)
8076 if (check_for_reference_conv &&
8077 mono_type_is_generic_argument (&target->byval_arg) &&
8078 mono_type_is_generic_argument (&candidate->byval_arg)) {
8079 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8080 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8082 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8085 if (!mono_class_is_assignable_from (target, candidate))
8091 * @container the generic container from the GTD
8092 * @klass: the class to be assigned to
8093 * @oklass: the source class
8095 * Both @klass and @oklass must be instances of the same generic interface.
8097 * Returns: TRUE if @klass can be assigned to a @klass variable
8100 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8103 MonoType **klass_argv, **oklass_argv;
8104 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8105 MonoGenericContainer *container = klass_gtd->generic_container;
8107 if (klass == oklass)
8110 /*Viable candidates are instances of the same generic interface*/
8111 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8114 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8115 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8117 for (j = 0; j < container->type_argc; ++j) {
8118 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8119 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8121 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8125 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8126 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8128 if (param1_class != param2_class) {
8129 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8130 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8132 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8133 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8143 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8145 MonoGenericParam *gparam, *ogparam;
8146 MonoGenericParamInfo *tinfo, *cinfo;
8147 MonoClass **candidate_class;
8148 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8151 if (target == candidate)
8153 if (target->byval_arg.type != candidate->byval_arg.type)
8156 gparam = target->byval_arg.data.generic_param;
8157 ogparam = candidate->byval_arg.data.generic_param;
8158 tinfo = mono_generic_param_info (gparam);
8159 cinfo = mono_generic_param_info (ogparam);
8161 class_constraint_satisfied = FALSE;
8162 valuetype_constraint_satisfied = FALSE;
8164 /*candidate must have a super set of target's special constraints*/
8165 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8166 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8168 if (cinfo->constraints) {
8169 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8170 MonoClass *cc = *candidate_class;
8172 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8173 class_constraint_satisfied = TRUE;
8174 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8175 valuetype_constraint_satisfied = TRUE;
8178 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8179 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8181 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8183 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8185 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8186 valuetype_constraint_satisfied)) {
8191 /*candidate type constraints must be a superset of target's*/
8192 if (tinfo->constraints) {
8193 MonoClass **target_class;
8194 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8195 MonoClass *tc = *target_class;
8198 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8199 * check it's constraints since it satisfy the constraint by itself.
8201 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8204 if (!cinfo->constraints)
8207 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8208 MonoClass *cc = *candidate_class;
8210 if (mono_class_is_assignable_from (tc, cc))
8214 * This happens when we have the following:
8216 * Bar<K> where K : IFace
8217 * Foo<T, U> where T : U where U : IFace
8219 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8222 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8223 if (mono_gparam_is_assignable_from (target, cc))
8227 if (!*candidate_class)
8232 /*candidate itself must have a constraint that satisfy target*/
8233 if (cinfo->constraints) {
8234 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8235 MonoClass *cc = *candidate_class;
8236 if (mono_class_is_assignable_from (target, cc))
8244 * mono_class_is_assignable_from:
8245 * @klass: the class to be assigned to
8246 * @oklass: the source class
8248 * Returns: TRUE if an instance of object oklass can be assigned to an
8249 * instance of object @klass
8252 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8255 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8257 mono_class_init (klass);
8259 if (!oklass->inited)
8260 mono_class_init (oklass);
8262 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8265 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8266 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8268 return mono_gparam_is_assignable_from (klass, oklass);
8271 if (MONO_CLASS_IS_INTERFACE (klass)) {
8272 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8273 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8274 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8278 for (i = 0; constraints [i]; ++i) {
8279 if (mono_class_is_assignable_from (klass, constraints [i]))
8287 /* interface_offsets might not be set for dynamic classes */
8288 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8290 * oklass might be a generic type parameter but they have
8291 * interface_offsets set.
8293 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8294 if (!is_ok (&error)) {
8295 mono_error_cleanup (&error);
8300 if (!oklass->interface_bitmap)
8301 /* Happens with generic instances of not-yet created dynamic types */
8303 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8306 if (mono_class_has_variant_generic_params (klass)) {
8308 mono_class_setup_interfaces (oklass, &error);
8309 if (!mono_error_ok (&error)) {
8310 mono_error_cleanup (&error);
8314 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8315 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8316 MonoClass *iface = oklass->interfaces_packed [i];
8318 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8323 } else if (klass->delegate) {
8324 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8326 }else if (klass->rank) {
8327 MonoClass *eclass, *eoclass;
8329 if (oklass->rank != klass->rank)
8332 /* vectors vs. one dimensional arrays */
8333 if (oklass->byval_arg.type != klass->byval_arg.type)
8336 eclass = klass->cast_class;
8337 eoclass = oklass->cast_class;
8340 * a is b does not imply a[] is b[] when a is a valuetype, and
8341 * b is a reference type.
8344 if (eoclass->valuetype) {
8345 if ((eclass == mono_defaults.enum_class) ||
8346 (eclass == mono_defaults.enum_class->parent) ||
8347 (eclass == mono_defaults.object_class))
8351 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8352 } else if (mono_class_is_nullable (klass)) {
8353 if (mono_class_is_nullable (oklass))
8354 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8356 return mono_class_is_assignable_from (klass->cast_class, oklass);
8357 } else if (klass == mono_defaults.object_class)
8360 return mono_class_has_parent (oklass, klass);
8363 /*Check if @oklass is variant compatible with @klass.*/
8365 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8368 MonoType **klass_argv, **oklass_argv;
8369 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8370 MonoGenericContainer *container = klass_gtd->generic_container;
8372 /*Viable candidates are instances of the same generic interface*/
8373 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8376 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8377 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8379 for (j = 0; j < container->type_argc; ++j) {
8380 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8381 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8383 if (param1_class->valuetype != param2_class->valuetype)
8387 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8388 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8390 if (param1_class != param2_class) {
8391 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8392 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8394 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8395 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8403 /*Check if @candidate implements the interface @target*/
8405 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8409 gboolean is_variant = mono_class_has_variant_generic_params (target);
8411 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8412 if (mono_class_is_variant_compatible_slow (target, candidate))
8417 if (candidate == target)
8420 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8421 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8422 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8424 if (tb && tb->interfaces) {
8425 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8426 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8427 MonoClass *iface_class;
8429 /* we can't realize the type here since it can do pretty much anything. */
8432 iface_class = mono_class_from_mono_type (iface->type);
8433 if (iface_class == target)
8435 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8437 if (mono_class_implement_interface_slow (target, iface_class))
8442 /*setup_interfaces don't mono_class_init anything*/
8443 /*FIXME this doesn't handle primitive type arrays.
8444 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8445 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8447 mono_class_setup_interfaces (candidate, &error);
8448 if (!mono_error_ok (&error)) {
8449 mono_error_cleanup (&error);
8453 for (i = 0; i < candidate->interface_count; ++i) {
8454 if (candidate->interfaces [i] == target)
8457 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8460 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8464 candidate = candidate->parent;
8465 } while (candidate);
8471 * Check if @oklass can be assigned to @klass.
8472 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8475 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8477 if (candidate == target)
8479 if (target == mono_defaults.object_class)
8482 if (mono_class_has_parent (candidate, target))
8485 /*If target is not an interface there is no need to check them.*/
8486 if (MONO_CLASS_IS_INTERFACE (target))
8487 return mono_class_implement_interface_slow (target, candidate);
8489 if (target->delegate && mono_class_has_variant_generic_params (target))
8490 return mono_class_is_variant_compatible (target, candidate, FALSE);
8493 MonoClass *eclass, *eoclass;
8495 if (target->rank != candidate->rank)
8498 /* vectors vs. one dimensional arrays */
8499 if (target->byval_arg.type != candidate->byval_arg.type)
8502 eclass = target->cast_class;
8503 eoclass = candidate->cast_class;
8506 * a is b does not imply a[] is b[] when a is a valuetype, and
8507 * b is a reference type.
8510 if (eoclass->valuetype) {
8511 if ((eclass == mono_defaults.enum_class) ||
8512 (eclass == mono_defaults.enum_class->parent) ||
8513 (eclass == mono_defaults.object_class))
8517 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8519 /*FIXME properly handle nullables */
8520 /*FIXME properly handle (M)VAR */
8525 * mono_class_get_cctor:
8526 * @klass: A MonoClass pointer
8528 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8531 mono_class_get_cctor (MonoClass *klass)
8533 MonoCachedClassInfo cached_info;
8535 if (image_is_dynamic (klass->image)) {
8537 * has_cctor is not set for these classes because mono_class_init () is
8540 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8543 if (!klass->has_cctor)
8546 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8548 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8549 if (!mono_error_ok (&error))
8550 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8554 if (klass->generic_class && !klass->methods)
8555 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8557 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8561 * mono_class_get_finalizer:
8562 * @klass: The MonoClass pointer
8564 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8567 mono_class_get_finalizer (MonoClass *klass)
8569 MonoCachedClassInfo cached_info;
8572 mono_class_init (klass);
8573 if (!mono_class_has_finalizer (klass))
8576 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8578 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8579 if (!mono_error_ok (&error))
8580 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8583 mono_class_setup_vtable (klass);
8584 return klass->vtable [finalize_slot];
8589 * mono_class_needs_cctor_run:
8590 * @klass: the MonoClass pointer
8591 * @caller: a MonoMethod describing the caller
8593 * Determines whenever the class has a static constructor and whenever it
8594 * needs to be called when executing CALLER.
8597 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8601 method = mono_class_get_cctor (klass);
8603 return (method == caller) ? FALSE : TRUE;
8609 * mono_class_array_element_size:
8612 * Returns: The number of bytes an element of type @klass
8613 * uses when stored into an array.
8616 mono_class_array_element_size (MonoClass *klass)
8618 MonoType *type = &klass->byval_arg;
8621 switch (type->type) {
8624 case MONO_TYPE_BOOLEAN:
8628 case MONO_TYPE_CHAR:
8637 case MONO_TYPE_CLASS:
8638 case MONO_TYPE_STRING:
8639 case MONO_TYPE_OBJECT:
8640 case MONO_TYPE_SZARRAY:
8641 case MONO_TYPE_ARRAY:
8642 return sizeof (gpointer);
8647 case MONO_TYPE_VALUETYPE:
8648 if (type->data.klass->enumtype) {
8649 type = mono_class_enum_basetype (type->data.klass);
8650 klass = klass->element_class;
8653 return mono_class_instance_size (klass) - sizeof (MonoObject);
8654 case MONO_TYPE_GENERICINST:
8655 type = &type->data.generic_class->container_class->byval_arg;
8658 case MONO_TYPE_MVAR: {
8661 return mono_type_size (type, &align);
8663 case MONO_TYPE_VOID:
8667 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8673 * mono_array_element_size:
8674 * @ac: pointer to a #MonoArrayClass
8676 * Returns: The size of single array element.
8679 mono_array_element_size (MonoClass *ac)
8681 g_assert (ac->rank);
8682 return ac->sizes.element_size;
8686 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8687 MonoGenericContext *context)
8690 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8691 g_assert (mono_error_ok (&error));
8696 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8697 MonoGenericContext *context, MonoError *error)
8699 mono_error_init (error);
8701 if (image_is_dynamic (image)) {
8702 MonoClass *tmp_handle_class;
8703 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8705 mono_error_assert_ok (error);
8706 g_assert (tmp_handle_class);
8708 *handle_class = tmp_handle_class;
8710 if (tmp_handle_class == mono_defaults.typehandle_class)
8711 return &((MonoClass*)obj)->byval_arg;
8716 switch (token & 0xff000000) {
8717 case MONO_TOKEN_TYPE_DEF:
8718 case MONO_TOKEN_TYPE_REF:
8719 case MONO_TOKEN_TYPE_SPEC: {
8722 *handle_class = mono_defaults.typehandle_class;
8723 type = mono_type_get_checked (image, token, context, error);
8727 mono_class_init (mono_class_from_mono_type (type));
8728 /* We return a MonoType* as handle */
8731 case MONO_TOKEN_FIELD_DEF: {
8733 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8735 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8739 *handle_class = mono_defaults.fieldhandle_class;
8740 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8744 mono_class_init (klass);
8745 return mono_class_get_field (klass, token);
8747 case MONO_TOKEN_METHOD_DEF:
8748 case MONO_TOKEN_METHOD_SPEC: {
8750 meth = mono_get_method_checked (image, token, NULL, context, error);
8752 *handle_class = mono_defaults.methodhandle_class;
8758 case MONO_TOKEN_MEMBER_REF: {
8759 guint32 cols [MONO_MEMBERREF_SIZE];
8761 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8762 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8763 mono_metadata_decode_blob_size (sig, &sig);
8764 if (*sig == 0x6) { /* it's a field */
8766 MonoClassField *field;
8767 field = mono_field_from_token_checked (image, token, &klass, context, error);
8769 *handle_class = mono_defaults.fieldhandle_class;
8773 meth = mono_get_method_checked (image, token, NULL, context, error);
8775 *handle_class = mono_defaults.methodhandle_class;
8780 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8786 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8788 MonoClass *handle_class;
8789 mono_error_init (error);
8790 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8794 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8796 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8799 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8802 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8804 get_cached_class_info = func;
8808 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8810 if (!get_cached_class_info)
8813 return get_cached_class_info (klass, res);
8817 mono_install_get_class_from_name (MonoGetClassFromName func)
8819 get_class_from_name = func;
8823 * mono_class_get_image:
8825 * Use this method to get the `MonoImage*` where this class came from.
8827 * Returns: The image where this class is defined.
8830 mono_class_get_image (MonoClass *klass)
8832 return klass->image;
8836 * mono_class_get_element_class:
8837 * @klass: the MonoClass to act on
8839 * Use this function to get the element class of an array.
8841 * Returns: The element class of an array.
8844 mono_class_get_element_class (MonoClass *klass)
8846 return klass->element_class;
8850 * mono_class_is_valuetype:
8851 * @klass: the MonoClass to act on
8853 * Use this method to determine if the provided `MonoClass*` represents a value type,
8854 * or a reference type.
8856 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8859 mono_class_is_valuetype (MonoClass *klass)
8861 return klass->valuetype;
8865 * mono_class_is_enum:
8866 * @klass: the MonoClass to act on
8868 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8870 * Returns: TRUE if the MonoClass represents an enumeration.
8873 mono_class_is_enum (MonoClass *klass)
8875 return klass->enumtype;
8879 * mono_class_enum_basetype:
8880 * @klass: the MonoClass to act on
8882 * Use this function to get the underlying type for an enumeration value.
8884 * Returns: The underlying type representation for an enumeration.
8887 mono_class_enum_basetype (MonoClass *klass)
8889 if (klass->element_class == klass)
8890 /* SRE or broken types */
8893 return &klass->element_class->byval_arg;
8897 * mono_class_get_parent
8898 * @klass: the MonoClass to act on
8900 * Returns: The parent class for this class.
8903 mono_class_get_parent (MonoClass *klass)
8905 return klass->parent;
8909 * mono_class_get_nesting_type:
8910 * @klass: the MonoClass to act on
8912 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8914 * If the return is NULL, this indicates that this class is not nested.
8916 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8919 mono_class_get_nesting_type (MonoClass *klass)
8921 return klass->nested_in;
8925 * mono_class_get_rank:
8926 * @klass: the MonoClass to act on
8928 * Returns: The rank for the array (the number of dimensions).
8931 mono_class_get_rank (MonoClass *klass)
8937 * mono_class_get_flags:
8938 * @klass: the MonoClass to act on
8940 * The type flags from the TypeDef table from the metadata.
8941 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8944 * Returns: The flags from the TypeDef table.
8947 mono_class_get_flags (MonoClass *klass)
8949 return klass->flags;
8953 * mono_class_get_name
8954 * @klass: the MonoClass to act on
8956 * Returns: The name of the class.
8959 mono_class_get_name (MonoClass *klass)
8965 * mono_class_get_namespace:
8966 * @klass: the MonoClass to act on
8968 * Returns: The namespace of the class.
8971 mono_class_get_namespace (MonoClass *klass)
8973 return klass->name_space;
8977 * mono_class_get_type:
8978 * @klass: the MonoClass to act on
8980 * This method returns the internal Type representation for the class.
8982 * Returns: The MonoType from the class.
8985 mono_class_get_type (MonoClass *klass)
8987 return &klass->byval_arg;
8991 * mono_class_get_type_token:
8992 * @klass: the MonoClass to act on
8994 * This method returns type token for the class.
8996 * Returns: The type token for the class.
8999 mono_class_get_type_token (MonoClass *klass)
9001 return klass->type_token;
9005 * mono_class_get_byref_type:
9006 * @klass: the MonoClass to act on
9011 mono_class_get_byref_type (MonoClass *klass)
9013 return &klass->this_arg;
9017 * mono_class_num_fields:
9018 * @klass: the MonoClass to act on
9020 * Returns: The number of static and instance fields in the class.
9023 mono_class_num_fields (MonoClass *klass)
9025 return klass->field.count;
9029 * mono_class_num_methods:
9030 * @klass: the MonoClass to act on
9032 * Returns: The number of methods in the class.
9035 mono_class_num_methods (MonoClass *klass)
9037 return klass->method.count;
9041 * mono_class_num_properties
9042 * @klass: the MonoClass to act on
9044 * Returns: The number of properties in the class.
9047 mono_class_num_properties (MonoClass *klass)
9049 mono_class_setup_properties (klass);
9051 return klass->ext->property.count;
9055 * mono_class_num_events:
9056 * @klass: the MonoClass to act on
9058 * Returns: The number of events in the class.
9061 mono_class_num_events (MonoClass *klass)
9063 mono_class_setup_events (klass);
9065 return klass->ext->event.count;
9069 * mono_class_get_fields:
9070 * @klass: the MonoClass to act on
9072 * This routine is an iterator routine for retrieving the fields in a class.
9074 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9075 * iterate over all of the elements. When no more values are
9076 * available, the return value is NULL.
9078 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9081 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9083 MonoClassField* field;
9087 mono_class_setup_fields (klass);
9088 if (mono_class_has_failure (klass))
9090 /* start from the first */
9091 if (klass->field.count) {
9092 *iter = &klass->fields [0];
9093 return &klass->fields [0];
9099 field = (MonoClassField *)*iter;
9101 if (field < &klass->fields [klass->field.count]) {
9109 * mono_class_get_methods
9110 * @klass: the MonoClass to act on
9112 * This routine is an iterator routine for retrieving the fields in a class.
9114 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9115 * iterate over all of the elements. When no more values are
9116 * available, the return value is NULL.
9118 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9121 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9123 MonoMethod** method;
9127 mono_class_setup_methods (klass);
9130 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9131 * FIXME we should better report this error to the caller
9133 if (!klass->methods)
9135 /* start from the first */
9136 if (klass->method.count) {
9137 *iter = &klass->methods [0];
9138 return klass->methods [0];
9144 method = (MonoMethod **)*iter;
9146 if (method < &klass->methods [klass->method.count]) {
9154 * mono_class_get_virtual_methods:
9156 * Iterate over the virtual methods of KLASS.
9158 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9161 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9163 MonoMethod** method;
9166 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9168 mono_class_setup_methods (klass);
9170 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9171 * FIXME we should better report this error to the caller
9173 if (!klass->methods)
9175 /* start from the first */
9176 method = &klass->methods [0];
9178 method = (MonoMethod **)*iter;
9181 while (method < &klass->methods [klass->method.count]) {
9182 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9186 if (method < &klass->methods [klass->method.count]) {
9193 /* Search directly in metadata to avoid calling setup_methods () */
9194 MonoMethod *res = NULL;
9200 start_index = GPOINTER_TO_UINT (*iter);
9203 for (i = start_index; i < klass->method.count; ++i) {
9206 /* klass->method.first points into the methodptr table */
9207 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9209 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9213 if (i < klass->method.count) {
9215 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9216 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9218 /* Add 1 here so the if (*iter) check fails */
9219 *iter = GUINT_TO_POINTER (i + 1);
9228 * mono_class_get_properties:
9229 * @klass: the MonoClass to act on
9231 * This routine is an iterator routine for retrieving the properties in a class.
9233 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9234 * iterate over all of the elements. When no more values are
9235 * available, the return value is NULL.
9237 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9240 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9242 MonoProperty* property;
9246 mono_class_setup_properties (klass);
9247 /* start from the first */
9248 if (klass->ext->property.count) {
9249 *iter = &klass->ext->properties [0];
9250 return (MonoProperty *)*iter;
9256 property = (MonoProperty *)*iter;
9258 if (property < &klass->ext->properties [klass->ext->property.count]) {
9260 return (MonoProperty *)*iter;
9266 * mono_class_get_events:
9267 * @klass: the MonoClass to act on
9269 * This routine is an iterator routine for retrieving the properties in a class.
9271 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9272 * iterate over all of the elements. When no more values are
9273 * available, the return value is NULL.
9275 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9278 mono_class_get_events (MonoClass* klass, gpointer *iter)
9284 mono_class_setup_events (klass);
9285 /* start from the first */
9286 if (klass->ext->event.count) {
9287 *iter = &klass->ext->events [0];
9288 return (MonoEvent *)*iter;
9294 event = (MonoEvent *)*iter;
9296 if (event < &klass->ext->events [klass->ext->event.count]) {
9298 return (MonoEvent *)*iter;
9304 * mono_class_get_interfaces
9305 * @klass: the MonoClass to act on
9307 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9309 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9310 * iterate over all of the elements. When no more values are
9311 * available, the return value is NULL.
9313 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9316 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9324 mono_class_init (klass);
9325 if (!klass->interfaces_inited) {
9326 mono_class_setup_interfaces (klass, &error);
9327 if (!mono_error_ok (&error)) {
9328 mono_error_cleanup (&error);
9332 /* start from the first */
9333 if (klass->interface_count) {
9334 *iter = &klass->interfaces [0];
9335 return klass->interfaces [0];
9341 iface = (MonoClass **)*iter;
9343 if (iface < &klass->interfaces [klass->interface_count]) {
9351 setup_nested_types (MonoClass *klass)
9354 GList *classes, *nested_classes, *l;
9357 if (klass->nested_classes_inited)
9360 if (!klass->type_token)
9361 klass->nested_classes_inited = TRUE;
9363 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9367 guint32 cols [MONO_NESTED_CLASS_SIZE];
9368 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9369 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9370 if (!mono_error_ok (&error)) {
9371 /*FIXME don't swallow the error message*/
9372 mono_error_cleanup (&error);
9374 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9378 classes = g_list_prepend (classes, nclass);
9380 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9383 mono_class_alloc_ext (klass);
9385 nested_classes = NULL;
9386 for (l = classes; l; l = l->next)
9387 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9388 g_list_free (classes);
9390 mono_image_lock (klass->image);
9392 mono_memory_barrier ();
9393 if (!klass->nested_classes_inited) {
9394 klass->ext->nested_classes = nested_classes;
9395 mono_memory_barrier ();
9396 klass->nested_classes_inited = TRUE;
9399 mono_image_unlock (klass->image);
9403 * mono_class_get_nested_types
9404 * @klass: the MonoClass to act on
9406 * This routine is an iterator routine for retrieving the nested types of a class.
9407 * This works only if @klass is non-generic, or a generic type definition.
9409 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9410 * iterate over all of the elements. When no more values are
9411 * available, the return value is NULL.
9413 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9416 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9422 if (!klass->nested_classes_inited)
9423 setup_nested_types (klass);
9426 /* start from the first */
9427 if (klass->ext && klass->ext->nested_classes) {
9428 *iter = klass->ext->nested_classes;
9429 return (MonoClass *)klass->ext->nested_classes->data;
9431 /* no nested types */
9435 item = (GList *)*iter;
9439 return (MonoClass *)item->data;
9446 * mono_class_is_delegate
9447 * @klass: the MonoClass to act on
9449 * Returns: TRUE if the MonoClass represents a System.Delegate.
9452 mono_class_is_delegate (MonoClass *klass)
9454 return klass->delegate;
9458 * mono_class_implements_interface
9459 * @klass: The MonoClass to act on
9460 * @interface: The interface to check if @klass implements.
9462 * Returns: TRUE if @klass implements @interface.
9465 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9467 return mono_class_is_assignable_from (iface, klass);
9471 * mono_field_get_name:
9472 * @field: the MonoClassField to act on
9474 * Returns: The name of the field.
9477 mono_field_get_name (MonoClassField *field)
9483 * mono_field_get_type:
9484 * @field: the MonoClassField to act on
9486 * Returns: MonoType of the field.
9489 mono_field_get_type (MonoClassField *field)
9492 MonoType *type = mono_field_get_type_checked (field, &error);
9493 if (!mono_error_ok (&error)) {
9494 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9495 mono_error_cleanup (&error);
9502 * mono_field_get_type_checked:
9503 * @field: the MonoClassField to act on
9504 * @error: used to return any erro found while retrieving @field type
9506 * Returns: MonoType of the field.
9509 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9511 mono_error_init (error);
9513 mono_field_resolve_type (field, error);
9518 * mono_field_get_parent:
9519 * @field: the MonoClassField to act on
9521 * Returns: MonoClass where the field was defined.
9524 mono_field_get_parent (MonoClassField *field)
9526 return field->parent;
9530 * mono_field_get_flags;
9531 * @field: the MonoClassField to act on
9533 * The metadata flags for a field are encoded using the
9534 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9536 * Returns: The flags for the field.
9539 mono_field_get_flags (MonoClassField *field)
9542 return mono_field_resolve_flags (field);
9543 return field->type->attrs;
9547 * mono_field_get_offset:
9548 * @field: the MonoClassField to act on
9550 * Returns: The field offset.
9553 mono_field_get_offset (MonoClassField *field)
9555 return field->offset;
9559 mono_field_get_rva (MonoClassField *field)
9563 MonoClass *klass = field->parent;
9564 MonoFieldDefaultValue *field_def_values;
9566 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9568 if (!klass->ext || !klass->ext->field_def_values) {
9569 mono_class_alloc_ext (klass);
9571 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9573 mono_image_lock (klass->image);
9574 if (!klass->ext->field_def_values)
9575 klass->ext->field_def_values = field_def_values;
9576 mono_image_unlock (klass->image);
9579 field_index = mono_field_get_index (field);
9581 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9582 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9584 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9585 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9588 return klass->ext->field_def_values [field_index].data;
9592 * mono_field_get_data:
9593 * @field: the MonoClassField to act on
9595 * Returns: A pointer to the metadata constant value or to the field
9596 * data if it has an RVA flag.
9599 mono_field_get_data (MonoClassField *field)
9601 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9602 MonoTypeEnum def_type;
9604 return mono_class_get_field_default_value (field, &def_type);
9605 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9606 return mono_field_get_rva (field);
9613 * mono_property_get_name:
9614 * @prop: the MonoProperty to act on
9616 * Returns: The name of the property
9619 mono_property_get_name (MonoProperty *prop)
9625 * mono_property_get_set_method
9626 * @prop: the MonoProperty to act on.
9628 * Returns: The setter method of the property (A MonoMethod)
9631 mono_property_get_set_method (MonoProperty *prop)
9637 * mono_property_get_get_method
9638 * @prop: the MonoProperty to act on.
9640 * Returns: The setter method of the property (A MonoMethod)
9643 mono_property_get_get_method (MonoProperty *prop)
9649 * mono_property_get_parent:
9650 * @prop: the MonoProperty to act on.
9652 * Returns: The MonoClass where the property was defined.
9655 mono_property_get_parent (MonoProperty *prop)
9657 return prop->parent;
9661 * mono_property_get_flags:
9662 * @prop: the MonoProperty to act on.
9664 * The metadata flags for a property are encoded using the
9665 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9667 * Returns: The flags for the property.
9670 mono_property_get_flags (MonoProperty *prop)
9676 * mono_event_get_name:
9677 * @event: the MonoEvent to act on
9679 * Returns: The name of the event.
9682 mono_event_get_name (MonoEvent *event)
9688 * mono_event_get_add_method:
9689 * @event: The MonoEvent to act on.
9691 * Returns: The @add' method for the event (a MonoMethod).
9694 mono_event_get_add_method (MonoEvent *event)
9700 * mono_event_get_remove_method:
9701 * @event: The MonoEvent to act on.
9703 * Returns: The @remove method for the event (a MonoMethod).
9706 mono_event_get_remove_method (MonoEvent *event)
9708 return event->remove;
9712 * mono_event_get_raise_method:
9713 * @event: The MonoEvent to act on.
9715 * Returns: The @raise method for the event (a MonoMethod).
9718 mono_event_get_raise_method (MonoEvent *event)
9720 return event->raise;
9724 * mono_event_get_parent:
9725 * @event: the MonoEvent to act on.
9727 * Returns: The MonoClass where the event is defined.
9730 mono_event_get_parent (MonoEvent *event)
9732 return event->parent;
9736 * mono_event_get_flags
9737 * @event: the MonoEvent to act on.
9739 * The metadata flags for an event are encoded using the
9740 * EVENT_* constants. See the tabledefs.h file for details.
9742 * Returns: The flags for the event.
9745 mono_event_get_flags (MonoEvent *event)
9747 return event->attrs;
9751 * mono_class_get_method_from_name:
9752 * @klass: where to look for the method
9753 * @name: name of the method
9754 * @param_count: number of parameters. -1 for any number.
9756 * Obtains a MonoMethod with a given name and number of parameters.
9757 * It only works if there are no multiple signatures for any given method name.
9760 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9762 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9766 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9768 MonoMethod *res = NULL;
9771 /* Search directly in the metadata to avoid calling setup_methods () */
9772 for (i = 0; i < klass->method.count; ++i) {
9774 guint32 cols [MONO_METHOD_SIZE];
9776 MonoMethodSignature *sig;
9778 /* klass->method.first points into the methodptr table */
9779 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9781 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9782 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9784 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9787 if (param_count == -1) {
9791 sig = mono_method_signature_checked (method, &error);
9793 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9796 if (sig->param_count == param_count) {
9807 * mono_class_get_method_from_name_flags:
9808 * @klass: where to look for the method
9809 * @name_space: name of the method
9810 * @param_count: number of parameters. -1 for any number.
9811 * @flags: flags which must be set in the method
9813 * Obtains a MonoMethod with a given name and number of parameters.
9814 * It only works if there are no multiple signatures for any given method name.
9817 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9819 MonoMethod *res = NULL;
9822 mono_class_init (klass);
9824 if (klass->generic_class && !klass->methods) {
9825 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9828 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9829 if (!mono_error_ok (&error))
9830 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9835 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9836 mono_class_setup_methods (klass);
9838 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9839 See mono/tests/array_load_exception.il
9840 FIXME we should better report this error to the caller
9842 if (!klass->methods)
9844 for (i = 0; i < klass->method.count; ++i) {
9845 MonoMethod *method = klass->methods [i];
9847 if (method->name[0] == name [0] &&
9848 !strcmp (name, method->name) &&
9849 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9850 ((method->flags & flags) == flags)) {
9857 res = find_method_in_metadata (klass, name, param_count, flags);
9864 * mono_class_set_failure:
9865 * @klass: class in which the failure was detected
9866 * @ex_type: the kind of exception/error to be thrown (later)
9867 * @ex_data: exception data (specific to each type of exception/error)
9869 * Keep a detected failure informations in the class for later processing.
9870 * Note that only the first failure is kept.
9872 * LOCKING: Acquires the loader lock.
9875 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9877 g_assert (boxed_error != NULL);
9879 if (mono_class_has_failure (klass))
9882 mono_loader_lock ();
9883 klass->has_failure = 1;
9884 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9885 mono_loader_unlock ();
9891 mono_class_has_failure (const MonoClass *klass)
9893 g_assert (klass != NULL);
9894 return klass->has_failure != 0;
9899 * mono_class_set_type_load_failure:
9900 * @klass: class in which the failure was detected
9901 * @fmt: Printf-style error message string.
9903 * Collect detected failure informaion in the class for later processing.
9904 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9905 * Note that only the first failure is kept.
9907 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9909 * LOCKING: Acquires the loader lock.
9912 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9914 MonoError prepare_error;
9917 if (mono_class_has_failure (klass))
9920 mono_error_init (&prepare_error);
9922 va_start (args, fmt);
9923 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9926 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9927 mono_error_cleanup (&prepare_error);
9928 return mono_class_set_failure (klass, box);
9932 * mono_class_get_exception_data:
9934 * Return the exception_data property of KLASS.
9936 * LOCKING: Acquires the loader lock.
9939 mono_class_get_exception_data (const MonoClass *klass)
9941 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9945 * mono_classes_init:
9947 * Initialize the resources used by this module.
9950 mono_classes_init (void)
9952 mono_os_mutex_init (&classes_mutex);
9954 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9956 mono_counters_register ("Inflated methods size",
9957 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9958 mono_counters_register ("Inflated classes",
9959 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9960 mono_counters_register ("Inflated classes size",
9961 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9962 mono_counters_register ("MonoClass size",
9963 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9964 mono_counters_register ("MonoClassExt size",
9965 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9969 * mono_classes_cleanup:
9971 * Free the resources used by this module.
9974 mono_classes_cleanup (void)
9976 mono_native_tls_free (setup_fields_tls_id);
9978 if (global_interface_bitset)
9979 mono_bitset_free (global_interface_bitset);
9980 global_interface_bitset = NULL;
9981 mono_os_mutex_destroy (&classes_mutex);
9985 * mono_class_get_exception_for_failure:
9986 * @klass: class in which the failure was detected
9988 * Return a constructed MonoException than the caller can then throw
9989 * using mono_raise_exception - or NULL if no failure is present (or
9990 * doesn't result in an exception).
9993 mono_class_get_exception_for_failure (MonoClass *klass)
9995 if (!mono_class_has_failure (klass))
9997 MonoError unboxed_error;
9998 mono_error_init (&unboxed_error);
9999 mono_error_set_for_class_failure (&unboxed_error, klass);
10000 return mono_error_convert_to_exception (&unboxed_error);
10004 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10006 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10007 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10009 if (outer_klass == inner_klass)
10011 inner_klass = inner_klass->nested_in;
10012 } while (inner_klass);
10017 mono_class_get_generic_type_definition (MonoClass *klass)
10019 return klass->generic_class ? klass->generic_class->container_class : klass;
10023 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10025 * Generic instantiations are ignored for all super types of @klass.
10027 * Visibility checks ignoring generic instantiations.
10030 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10033 klass = mono_class_get_generic_type_definition (klass);
10034 parent = mono_class_get_generic_type_definition (parent);
10035 mono_class_setup_supertypes (klass);
10037 for (i = 0; i < klass->idepth; ++i) {
10038 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10044 * Subtype can only access parent members with family protection if the site object
10045 * is subclass of Subtype. For example:
10046 * class A { protected int x; }
10048 * void valid_access () {
10052 * void invalid_access () {
10059 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10061 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10064 if (context_klass == NULL)
10066 /*if access_klass is not member_klass context_klass must be type compat*/
10067 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10073 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10076 if (accessing == accessed)
10078 if (!accessed || !accessing)
10081 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10082 * anywhere so untrusted friends are not safe to access platform's code internals */
10083 if (mono_security_core_clr_enabled ()) {
10084 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10088 mono_assembly_load_friends (accessed);
10089 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10090 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10091 /* Be conservative with checks */
10092 if (!friend_->name)
10094 if (strcmp (accessing->aname.name, friend_->name))
10096 if (friend_->public_key_token [0]) {
10097 if (!accessing->aname.public_key_token [0])
10099 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10108 * If klass is a generic type or if it is derived from a generic type, return the
10109 * MonoClass of the generic definition
10110 * Returns NULL if not found
10113 get_generic_definition_class (MonoClass *klass)
10116 if (klass->generic_class && klass->generic_class->container_class)
10117 return klass->generic_class->container_class;
10118 klass = klass->parent;
10124 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10127 for (i = 0; i < ginst->type_argc; ++i) {
10128 MonoType *type = ginst->type_argv[i];
10129 switch (type->type) {
10130 case MONO_TYPE_SZARRAY:
10131 if (!can_access_type (access_klass, type->data.klass))
10134 case MONO_TYPE_ARRAY:
10135 if (!can_access_type (access_klass, type->data.array->eklass))
10138 case MONO_TYPE_PTR:
10139 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10142 case MONO_TYPE_CLASS:
10143 case MONO_TYPE_VALUETYPE:
10144 case MONO_TYPE_GENERICINST:
10145 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10155 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10159 if (access_klass == member_klass)
10162 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10165 if (access_klass->element_class && !access_klass->enumtype)
10166 access_klass = access_klass->element_class;
10168 if (member_klass->element_class && !member_klass->enumtype)
10169 member_klass = member_klass->element_class;
10171 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10173 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10176 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10179 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10182 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10185 /*Non nested type with nested visibility. We just fail it.*/
10186 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10189 switch (access_level) {
10190 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10191 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10193 case TYPE_ATTRIBUTE_PUBLIC:
10196 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10199 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10200 return is_nesting_type (member_klass, access_klass);
10202 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10203 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10205 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10206 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10208 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10209 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10210 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10212 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10213 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10214 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10219 /* FIXME: check visibility of type, too */
10221 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10223 MonoClass *member_generic_def;
10224 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10227 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10228 access_klass->generic_container) &&
10229 (member_generic_def = get_generic_definition_class (member_klass))) {
10230 MonoClass *access_container;
10232 if (access_klass->generic_container)
10233 access_container = access_klass;
10235 access_container = access_klass->generic_class->container_class;
10237 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10241 /* Partition I 8.5.3.2 */
10242 /* the access level values are the same for fields and methods */
10243 switch (access_level) {
10244 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10245 /* same compilation unit */
10246 return access_klass->image == member_klass->image;
10247 case FIELD_ATTRIBUTE_PRIVATE:
10248 return access_klass == member_klass;
10249 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10250 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10251 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10254 case FIELD_ATTRIBUTE_ASSEMBLY:
10255 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10256 case FIELD_ATTRIBUTE_FAMILY:
10257 if (is_valid_family_access (access_klass, member_klass, context_klass))
10260 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10261 if (is_valid_family_access (access_klass, member_klass, context_klass))
10263 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10264 case FIELD_ATTRIBUTE_PUBLIC:
10271 * mono_method_can_access_field:
10272 * @method: Method that will attempt to access the field
10273 * @field: the field to access
10275 * Used to determine if a method is allowed to access the specified field.
10277 * Returns: TRUE if the given @method is allowed to access the @field while following
10278 * the accessibility rules of the CLI.
10281 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10283 /* FIXME: check all overlapping fields */
10284 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10286 MonoClass *nested = method->klass->nested_in;
10288 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10291 nested = nested->nested_in;
10298 * mono_method_can_access_method:
10299 * @method: Method that will attempt to access the other method
10300 * @called: the method that we want to probe for accessibility.
10302 * Used to determine if the @method is allowed to access the specified @called method.
10304 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10305 * the accessibility rules of the CLI.
10308 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10310 method = mono_method_get_method_definition (method);
10311 called = mono_method_get_method_definition (called);
10312 return mono_method_can_access_method_full (method, called, NULL);
10316 * mono_method_can_access_method_full:
10317 * @method: The caller method
10318 * @called: The called method
10319 * @context_klass: The static type on stack of the owner @called object used
10321 * This function must be used with instance calls, as they have more strict family accessibility.
10322 * It can be used with static methods, but context_klass should be NULL.
10324 * Returns: TRUE if caller have proper visibility and acessibility to @called
10327 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10329 /* Wrappers are except from access checks */
10330 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10333 MonoClass *access_class = method->klass;
10334 MonoClass *member_class = called->klass;
10335 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10337 MonoClass *nested = access_class->nested_in;
10339 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10342 nested = nested->nested_in;
10349 can = can_access_type (access_class, member_class);
10351 MonoClass *nested = access_class->nested_in;
10353 can = can_access_type (nested, member_class);
10356 nested = nested->nested_in;
10363 if (called->is_inflated) {
10364 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10365 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10374 * mono_method_can_access_field_full:
10375 * @method: The caller method
10376 * @field: The accessed field
10377 * @context_klass: The static type on stack of the owner @field object used
10379 * This function must be used with instance fields, as they have more strict family accessibility.
10380 * It can be used with static fields, but context_klass should be NULL.
10382 * Returns: TRUE if caller have proper visibility and acessibility to @field
10385 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10387 MonoClass *access_class = method->klass;
10388 MonoClass *member_class = field->parent;
10389 /* FIXME: check all overlapping fields */
10390 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10392 MonoClass *nested = access_class->nested_in;
10394 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10397 nested = nested->nested_in;
10404 can = can_access_type (access_class, member_class);
10406 MonoClass *nested = access_class->nested_in;
10408 can = can_access_type (nested, member_class);
10411 nested = nested->nested_in;
10421 * mono_class_can_access_class:
10422 * @source_class: The source class
10423 * @target_class: The accessed class
10425 * This function returns is @target_class is visible to @source_class
10427 * Returns: TRUE if source have proper visibility and acessibility to target
10430 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10432 return can_access_type (source_class, target_class);
10436 * mono_type_is_valid_enum_basetype:
10437 * @type: The MonoType to check
10439 * Returns: TRUE if the type can be used as the basetype of an enum
10441 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10442 switch (type->type) {
10445 case MONO_TYPE_BOOLEAN:
10448 case MONO_TYPE_CHAR:
10462 * mono_class_is_valid_enum:
10463 * @klass: An enum class to be validated
10465 * This method verify the required properties an enum should have.
10467 * Returns: TRUE if the informed enum class is valid
10469 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10470 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10471 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10473 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10474 MonoClassField * field;
10475 gpointer iter = NULL;
10476 gboolean found_base_field = FALSE;
10478 g_assert (klass->enumtype);
10479 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10480 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10484 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10487 while ((field = mono_class_get_fields (klass, &iter))) {
10488 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10489 if (found_base_field)
10491 found_base_field = TRUE;
10492 if (!mono_type_is_valid_enum_basetype (field->type))
10497 if (!found_base_field)
10500 if (klass->method.count > 0)
10507 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10509 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10513 * mono_class_setup_interface_id:
10515 * Initializes MonoClass::interface_id if required.
10517 * LOCKING: Acquires the loader lock.
10520 mono_class_setup_interface_id (MonoClass *klass)
10522 mono_loader_lock ();
10523 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10524 klass->interface_id = mono_get_unique_iid (klass);
10525 mono_loader_unlock ();
10529 * mono_class_alloc_ext:
10531 * Allocate klass->ext if not already done.
10534 mono_class_alloc_ext (MonoClass *klass)
10541 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10542 mono_image_lock (klass->image);
10543 mono_memory_barrier ();
10546 class_ext_size += sizeof (MonoClassExt);
10547 mono_image_unlock (klass->image);
10551 * mono_class_setup_interfaces:
10553 * Initialize klass->interfaces/interfaces_count.
10554 * LOCKING: Acquires the loader lock.
10555 * This function can fail the type.
10558 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10560 int i, interface_count;
10561 MonoClass **interfaces;
10563 mono_error_init (error);
10565 if (klass->interfaces_inited)
10568 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10569 MonoType *args [1];
10571 /* generic IList, ICollection, IEnumerable */
10572 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10573 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10575 args [0] = &klass->element_class->byval_arg;
10576 interfaces [0] = mono_class_bind_generic_parameters (
10577 mono_defaults.generic_ilist_class, 1, args, FALSE);
10578 if (interface_count > 1)
10579 interfaces [1] = mono_class_bind_generic_parameters (
10580 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10581 } else if (klass->generic_class) {
10582 MonoClass *gklass = klass->generic_class->container_class;
10584 mono_class_setup_interfaces (gklass, error);
10585 if (!mono_error_ok (error)) {
10586 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10590 interface_count = gklass->interface_count;
10591 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10592 for (i = 0; i < interface_count; i++) {
10593 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10594 if (!mono_error_ok (error)) {
10595 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10600 interface_count = 0;
10604 mono_image_lock (klass->image);
10606 if (!klass->interfaces_inited) {
10607 klass->interface_count = interface_count;
10608 klass->interfaces = interfaces;
10610 mono_memory_barrier ();
10612 klass->interfaces_inited = TRUE;
10615 mono_image_unlock (klass->image);
10619 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10621 MonoClass *klass = field->parent;
10622 MonoImage *image = klass->image;
10623 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10624 int field_idx = field - klass->fields;
10626 mono_error_init (error);
10629 MonoClassField *gfield = >d->fields [field_idx];
10630 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10631 if (!mono_error_ok (error)) {
10632 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10635 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10636 if (!mono_error_ok (error)) {
10637 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10641 guint32 cols [MONO_FIELD_SIZE];
10642 MonoGenericContainer *container = NULL;
10643 int idx = klass->field.first + field_idx;
10645 /*FIXME, in theory we do not lazy load SRE fields*/
10646 g_assert (!image_is_dynamic (image));
10648 if (klass->generic_container) {
10649 container = klass->generic_container;
10651 container = gtd->generic_container;
10652 g_assert (container);
10655 /* klass->field.first and idx points into the fieldptr table */
10656 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10658 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10659 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10660 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10664 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10666 mono_metadata_decode_value (sig, &sig);
10667 /* FIELD signature == 0x06 */
10668 g_assert (*sig == 0x06);
10670 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10671 if (!field->type) {
10672 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10678 mono_field_resolve_flags (MonoClassField *field)
10680 MonoClass *klass = field->parent;
10681 MonoImage *image = klass->image;
10682 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10683 int field_idx = field - klass->fields;
10687 MonoClassField *gfield = >d->fields [field_idx];
10688 return mono_field_get_flags (gfield);
10690 int idx = klass->field.first + field_idx;
10692 /*FIXME, in theory we do not lazy load SRE fields*/
10693 g_assert (!image_is_dynamic (image));
10695 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10700 * mono_class_get_fields_lazy:
10701 * @klass: the MonoClass to act on
10703 * This routine is an iterator routine for retrieving the fields in a class.
10704 * Only minimal information about fields are loaded. Accessors must be used
10705 * for all MonoClassField returned.
10707 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10708 * iterate over all of the elements. When no more values are
10709 * available, the return value is NULL.
10711 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10714 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10716 MonoClassField* field;
10720 mono_class_setup_basic_field_info (klass);
10721 if (!klass->fields)
10723 /* start from the first */
10724 if (klass->field.count) {
10725 *iter = &klass->fields [0];
10726 return (MonoClassField *)*iter;
10732 field = (MonoClassField *)*iter;
10734 if (field < &klass->fields [klass->field.count]) {
10736 return (MonoClassField *)*iter;
10742 mono_class_full_name (MonoClass *klass)
10744 return mono_type_full_name (&klass->byval_arg);
10747 /* Declare all shared lazy type lookup functions */
10748 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)