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/assembly.h>
22 #include <mono/metadata/metadata.h>
23 #include <mono/metadata/metadata-internals.h>
24 #include <mono/metadata/profiler-private.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class-internals.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
31 #include <mono/metadata/debug-helpers.h>
32 #include <mono/metadata/reflection.h>
33 #include <mono/metadata/exception.h>
34 #include <mono/metadata/security-manager.h>
35 #include <mono/metadata/security-core-clr.h>
36 #include <mono/metadata/attrdefs.h>
37 #include <mono/metadata/gc-internals.h>
38 #include <mono/metadata/verify-internals.h>
39 #include <mono/metadata/mono-debug.h>
40 #include <mono/utils/mono-counters.h>
41 #include <mono/utils/mono-string.h>
42 #include <mono/utils/mono-error-internals.h>
43 #include <mono/utils/mono-logger-internals.h>
44 #include <mono/utils/mono-memory-model.h>
45 #include <mono/utils/atomic.h>
46 #include <mono/utils/bsearch.h>
47 #include <mono/utils/checked-build.h>
51 gboolean mono_print_vtable = FALSE;
52 gboolean mono_align_small_structs = FALSE;
55 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
56 guint32 classes_size, class_ext_size;
58 /* Low level lock which protects data structures in this module */
59 static mono_mutex_t classes_mutex;
61 /* Function supplied by the runtime to find classes by name using information from the AOT file */
62 static MonoGetClassFromName get_class_from_name = NULL;
64 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
65 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
66 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
67 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
68 static int generic_array_methods (MonoClass *klass);
69 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
71 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
72 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
73 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
74 static guint32 mono_field_resolve_flags (MonoClassField *field);
75 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
76 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
79 We use gclass recording to allow recursive system f types to be referenced by a parent.
81 Given the following type hierarchy:
83 class TextBox : TextBoxBase<TextBox> {}
84 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
85 class TextInput<T> : Input<T> where T: TextInput<T> {}
88 The runtime tries to load TextBoxBase<>.
89 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
90 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
91 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
93 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
94 at this point, iow, both are registered in the type map and both and a NULL parent. This means
95 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
97 To fix that what we do is to record all generic instantes created while resolving the parent of
98 any generic type definition and, after resolved, correct the parent field if needed.
101 static int record_gclass_instantiation;
102 static GSList *gclass_recorded_list;
103 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
108 mono_locks_os_acquire (&classes_mutex, ClassesLock);
112 classes_unlock (void)
114 mono_locks_os_release (&classes_mutex, ClassesLock);
118 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
121 enable_gclass_recording (void)
123 ++record_gclass_instantiation;
127 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
130 disable_gclass_recording (gclass_record_func func, void *user_data)
132 GSList **head = &gclass_recorded_list;
134 g_assert (record_gclass_instantiation > 0);
135 --record_gclass_instantiation;
138 GSList *node = *head;
139 if (func ((MonoClass*)node->data, user_data)) {
141 g_slist_free_1 (node);
147 /* We automatically discard all recorded gclasses when disabled. */
148 if (!record_gclass_instantiation && gclass_recorded_list) {
149 g_slist_free (gclass_recorded_list);
150 gclass_recorded_list = NULL;
155 * mono_class_from_typeref:
156 * @image: a MonoImage
157 * @type_token: a TypeRef token
159 * Creates the MonoClass* structure representing the type defined by
160 * the typeref token valid inside @image.
161 * Returns: The MonoClass* representing the typeref token, NULL ifcould
165 mono_class_from_typeref (MonoImage *image, guint32 type_token)
168 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
169 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
174 * mono_class_from_typeref_checked:
175 * @image: a MonoImage
176 * @type_token: a TypeRef token
177 * @error: error return code, if any.
179 * Creates the MonoClass* structure representing the type defined by
180 * the typeref token valid inside @image.
182 * Returns: The MonoClass* representing the typeref token, NULL if it could
183 * not be loaded with the @error value filled with the information about the
187 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
189 guint32 cols [MONO_TYPEREF_SIZE];
190 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
192 const char *name, *nspace;
193 MonoClass *res = NULL;
196 mono_error_init (error);
198 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
201 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
203 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
204 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
206 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
207 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
208 case MONO_RESOLUTION_SCOPE_MODULE:
210 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
211 This is not the observed behavior of existing implementations.
212 The defacto behavior is that it's just a typedef in disguise.
214 /* a typedef in disguise */
215 res = mono_class_from_name_checked (image, nspace, name, error);
218 case MONO_RESOLUTION_SCOPE_MODULEREF:
219 module = mono_image_load_module (image, idx);
221 res = mono_class_from_name_checked (module, nspace, name, error);
224 case MONO_RESOLUTION_SCOPE_TYPEREF: {
225 MonoClass *enclosing;
228 if (idx == mono_metadata_token_index (type_token)) {
229 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
233 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
234 return_val_if_nok (error, NULL);
236 if (enclosing->nested_classes_inited && enclosing->ext) {
237 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
238 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
239 res = (MonoClass *)tmp->data;
240 if (strcmp (res->name, name) == 0)
244 /* Don't call mono_class_init as we might've been called by it recursively */
245 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
247 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
248 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
249 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
251 if (strcmp (nname, name) == 0)
252 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
254 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
257 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
260 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
264 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
265 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
269 if (!image->references || !image->references [idx - 1])
270 mono_assembly_load_reference (image, idx - 1);
271 g_assert (image->references [idx - 1]);
273 /* If the assembly did not load, register this as a type load exception */
274 if (image->references [idx - 1] == REFERENCE_MISSING){
275 MonoAssemblyName aname;
278 mono_assembly_get_assemblyref (image, idx - 1, &aname);
279 human_name = mono_stringify_assembly_name (&aname);
280 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
284 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
287 /* Generic case, should be avoided for when a better error is possible. */
288 if (!res && mono_error_ok (error)) {
289 char *name = mono_class_name_from_token (image, type_token);
290 char *assembly = mono_assembly_name_from_token (image, type_token);
291 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
298 mono_image_memdup (MonoImage *image, void *data, guint size)
300 void *res = mono_image_alloc (image, size);
301 memcpy (res, data, size);
305 /* Copy everything mono_metadata_free_array free. */
307 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
310 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
312 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
314 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
316 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
318 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
320 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
325 /* Copy everything mono_metadata_free_method_signature free. */
327 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
331 sig = mono_metadata_signature_dup_full (image, sig);
333 sig->ret = mono_metadata_type_dup (image, sig->ret);
334 for (i = 0; i < sig->param_count; ++i)
335 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
341 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
343 MonoAssembly *ta = klass->image->assembly;
346 name = mono_stringify_assembly_name (&ta->aname);
347 g_string_append_printf (str, ", %s", name);
352 mono_type_name_check_byref (MonoType *type, GString *str)
355 g_string_append_c (str, '&');
359 * mono_identifier_escape_type_name_chars:
360 * @str: a destination string
361 * @identifier: an IDENTIFIER in internal form
365 * The displayed form of the identifier is appended to str.
367 * The displayed form of an identifier has the characters ,+&*[]\
368 * that have special meaning in type names escaped with a preceeding
369 * backslash (\) character.
372 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
378 // reserve space for common case: there will be no escaped characters.
379 g_string_set_size(str, n + strlen(identifier));
380 g_string_set_size(str, n);
382 for (const char* s = identifier; *s != 0 ; s++) {
391 g_string_append_c (str, '\\');
392 g_string_append_c (str, *s);
395 g_string_append_c (str, *s);
403 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
404 MonoTypeNameFormat format)
408 switch (type->type) {
409 case MONO_TYPE_ARRAY: {
410 int i, rank = type->data.array->rank;
411 MonoTypeNameFormat nested_format;
413 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
414 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
416 mono_type_get_name_recurse (
417 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
418 g_string_append_c (str, '[');
420 g_string_append_c (str, '*');
421 for (i = 1; i < rank; i++)
422 g_string_append_c (str, ',');
423 g_string_append_c (str, ']');
425 mono_type_name_check_byref (type, str);
427 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
428 _mono_type_get_assembly_name (type->data.array->eklass, str);
431 case MONO_TYPE_SZARRAY: {
432 MonoTypeNameFormat nested_format;
434 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
435 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
437 mono_type_get_name_recurse (
438 &type->data.klass->byval_arg, str, FALSE, nested_format);
439 g_string_append (str, "[]");
441 mono_type_name_check_byref (type, str);
443 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
444 _mono_type_get_assembly_name (type->data.klass, str);
447 case MONO_TYPE_PTR: {
448 MonoTypeNameFormat nested_format;
450 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
451 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
453 mono_type_get_name_recurse (
454 type->data.type, str, FALSE, nested_format);
455 g_string_append_c (str, '*');
457 mono_type_name_check_byref (type, str);
459 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
460 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
465 if (!mono_generic_param_info (type->data.generic_param))
466 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
468 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
470 mono_type_name_check_byref (type, str);
474 klass = mono_class_from_mono_type (type);
475 if (klass->nested_in) {
476 mono_type_get_name_recurse (
477 &klass->nested_in->byval_arg, str, TRUE, format);
478 if (format == MONO_TYPE_NAME_FORMAT_IL)
479 g_string_append_c (str, '.');
481 g_string_append_c (str, '+');
482 } else if (*klass->name_space) {
483 if (format == MONO_TYPE_NAME_FORMAT_IL)
484 g_string_append (str, klass->name_space);
486 mono_identifier_escape_type_name_chars (str, klass->name_space);
487 g_string_append_c (str, '.');
489 if (format == MONO_TYPE_NAME_FORMAT_IL) {
490 char *s = strchr (klass->name, '`');
491 int len = s ? s - klass->name : strlen (klass->name);
492 g_string_append_len (str, klass->name, len);
494 mono_identifier_escape_type_name_chars (str, klass->name);
498 if (klass->generic_class) {
499 MonoGenericClass *gclass = klass->generic_class;
500 MonoGenericInst *inst = gclass->context.class_inst;
501 MonoTypeNameFormat nested_format;
504 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
505 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
507 if (format == MONO_TYPE_NAME_FORMAT_IL)
508 g_string_append_c (str, '<');
510 g_string_append_c (str, '[');
511 for (i = 0; i < inst->type_argc; i++) {
512 MonoType *t = inst->type_argv [i];
515 g_string_append_c (str, ',');
516 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
517 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
518 g_string_append_c (str, '[');
519 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
520 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
521 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
522 g_string_append_c (str, ']');
524 if (format == MONO_TYPE_NAME_FORMAT_IL)
525 g_string_append_c (str, '>');
527 g_string_append_c (str, ']');
528 } else if (klass->generic_container &&
529 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
530 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
533 if (format == MONO_TYPE_NAME_FORMAT_IL)
534 g_string_append_c (str, '<');
536 g_string_append_c (str, '[');
537 for (i = 0; i < klass->generic_container->type_argc; i++) {
539 g_string_append_c (str, ',');
540 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
542 if (format == MONO_TYPE_NAME_FORMAT_IL)
543 g_string_append_c (str, '>');
545 g_string_append_c (str, ']');
548 mono_type_name_check_byref (type, str);
550 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
551 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
552 _mono_type_get_assembly_name (klass, str);
558 * mono_type_get_name_full:
560 * @format: the format for the return string.
563 * Returns: The string representation in a number of formats:
565 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
566 * returned in the formatrequired by System.Reflection, this is the
567 * inverse of mono_reflection_parse_type ().
569 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
570 * be used by the IL assembler.
572 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
574 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
577 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
581 result = g_string_new ("");
583 mono_type_get_name_recurse (type, result, FALSE, format);
585 return g_string_free (result, FALSE);
589 * mono_type_get_full_name:
592 * Returns: The string representation for type as required by System.Reflection.
593 * The inverse of mono_reflection_parse_type ().
596 mono_type_get_full_name (MonoClass *klass)
598 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
602 * mono_type_get_name:
605 * Returns: The string representation for type as it would be represented in IL code.
608 mono_type_get_name (MonoType *type)
610 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
614 * mono_type_get_underlying_type:
617 * Returns: The MonoType for the underlying integer type if @type
618 * is an enum and byref is false, otherwise the type itself.
621 mono_type_get_underlying_type (MonoType *type)
623 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
624 return mono_class_enum_basetype (type->data.klass);
625 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
626 return mono_class_enum_basetype (type->data.generic_class->container_class);
631 * mono_class_is_open_constructed_type:
634 * Returns: TRUE if type represents a generics open constructed type.
635 * IOW, not all type parameters required for the instantiation have
636 * been provided or it's a generic type definition.
638 * An open constructed type means it's a non realizable type. Not to
639 * be mixed up with an abstract type - we can't cast or dispatch to
640 * an open type, for example.
643 mono_class_is_open_constructed_type (MonoType *t)
649 case MONO_TYPE_SZARRAY:
650 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
651 case MONO_TYPE_ARRAY:
652 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
654 return mono_class_is_open_constructed_type (t->data.type);
655 case MONO_TYPE_GENERICINST:
656 return t->data.generic_class->context.class_inst->is_open;
657 case MONO_TYPE_CLASS:
658 case MONO_TYPE_VALUETYPE:
659 return t->data.klass->generic_container != NULL;
666 This is a simple function to catch the most common bad instances of generic types.
667 Specially those that might lead to further failures in the runtime.
670 is_valid_generic_argument (MonoType *type)
672 switch (type->type) {
674 //case MONO_TYPE_TYPEDBYREF:
682 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
684 mono_error_init (error);
686 switch (type->type) {
687 case MONO_TYPE_MVAR: {
689 int num = mono_type_get_generic_param_num (type);
690 MonoGenericInst *inst = context->method_inst;
693 if (num >= inst->type_argc) {
694 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
695 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
696 num, info ? info->name : "", inst->type_argc);
700 if (!is_valid_generic_argument (inst->type_argv [num])) {
701 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
702 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
703 num, info ? info->name : "", inst->type_argv [num]->type);
707 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
708 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
709 * ->byref and ->attrs from @type are propagated to the returned type.
711 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
712 nt->byref = type->byref;
713 nt->attrs = type->attrs;
716 case MONO_TYPE_VAR: {
718 int num = mono_type_get_generic_param_num (type);
719 MonoGenericInst *inst = context->class_inst;
722 if (num >= inst->type_argc) {
723 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
724 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
725 num, info ? info->name : "", inst->type_argc);
728 if (!is_valid_generic_argument (inst->type_argv [num])) {
729 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
730 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
731 num, info ? info->name : "", inst->type_argv [num]->type);
734 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
735 nt->byref = type->byref;
736 nt->attrs = type->attrs;
739 case MONO_TYPE_SZARRAY: {
740 MonoClass *eclass = type->data.klass;
741 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
742 if (!inflated || !mono_error_ok (error))
744 nt = mono_metadata_type_dup (image, type);
745 nt->data.klass = mono_class_from_mono_type (inflated);
746 mono_metadata_free_type (inflated);
749 case MONO_TYPE_ARRAY: {
750 MonoClass *eclass = type->data.array->eklass;
751 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
752 if (!inflated || !mono_error_ok (error))
754 nt = mono_metadata_type_dup (image, type);
755 nt->data.array->eklass = mono_class_from_mono_type (inflated);
756 mono_metadata_free_type (inflated);
759 case MONO_TYPE_GENERICINST: {
760 MonoGenericClass *gclass = type->data.generic_class;
761 MonoGenericInst *inst;
763 if (!gclass->context.class_inst->is_open)
766 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
767 return_val_if_nok (error, NULL);
769 if (inst != gclass->context.class_inst)
770 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
772 if (gclass == type->data.generic_class)
775 nt = mono_metadata_type_dup (image, type);
776 nt->data.generic_class = gclass;
779 case MONO_TYPE_CLASS:
780 case MONO_TYPE_VALUETYPE: {
781 MonoClass *klass = type->data.klass;
782 MonoGenericContainer *container = klass->generic_container;
783 MonoGenericInst *inst;
784 MonoGenericClass *gclass = NULL;
790 /* We can't use context->class_inst directly, since it can have more elements */
791 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
792 return_val_if_nok (error, NULL);
794 if (inst == container->context.class_inst)
797 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
799 nt = mono_metadata_type_dup (image, type);
800 nt->type = MONO_TYPE_GENERICINST;
801 nt->data.generic_class = gclass;
811 mono_generic_class_get_context (MonoGenericClass *gclass)
813 return &gclass->context;
817 mono_class_get_context (MonoClass *klass)
819 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
823 * mono_class_get_generic_container:
825 * Return the generic container of KLASS which should be a generic type definition.
827 MonoGenericContainer*
828 mono_class_get_generic_container (MonoClass *klass)
830 g_assert (klass->is_generic);
832 return klass->generic_container;
836 * mono_class_get_generic_class:
838 * Return the MonoGenericClass of KLASS, which should be a generic instance.
841 mono_class_get_generic_class (MonoClass *klass)
843 g_assert (klass->is_inflated);
845 return klass->generic_class;
849 * mono_class_inflate_generic_type_with_mempool:
850 * @mempool: a mempool
852 * @context: a generics context
853 * @error: error context
855 * The same as mono_class_inflate_generic_type, but allocates the MonoType
856 * from mempool if it is non-NULL. If it is NULL, the MonoType is
857 * allocated on the heap and is owned by the caller.
858 * The returned type can potentially be the same as TYPE, so it should not be
859 * modified by the caller, and it should be freed using mono_metadata_free_type ().
862 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
864 MonoType *inflated = NULL;
865 mono_error_init (error);
868 inflated = inflate_generic_type (image, type, context, error);
869 return_val_if_nok (error, NULL);
872 MonoType *shared = mono_metadata_get_shared_type (type);
877 return mono_metadata_type_dup (image, type);
881 mono_stats.inflated_type_count++;
886 * mono_class_inflate_generic_type:
888 * @context: a generics context
890 * If @type is a generic type and @context is not NULL, instantiate it using the
891 * generics context @context.
893 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
894 * on the heap and is owned by the caller. Returns NULL on error.
896 * @deprecated Please use mono_class_inflate_generic_type_checked instead
899 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
903 result = mono_class_inflate_generic_type_checked (type, context, &error);
904 mono_error_cleanup (&error);
909 * mono_class_inflate_generic_type:
911 * @context: a generics context
912 * @error: error context to use
914 * If @type is a generic type and @context is not NULL, instantiate it using the
915 * generics context @context.
917 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
918 * on the heap and is owned by the caller.
921 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
923 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
927 * mono_class_inflate_generic_type_no_copy:
929 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
933 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
935 MonoType *inflated = NULL;
937 mono_error_init (error);
939 inflated = inflate_generic_type (image, type, context, error);
940 return_val_if_nok (error, NULL);
946 mono_stats.inflated_type_count++;
951 * mono_class_inflate_generic_class:
953 * Inflate the class @gklass with @context. Set @error on failure.
956 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
961 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
962 return_val_if_nok (error, NULL);
964 res = mono_class_from_mono_type (inflated);
965 mono_metadata_free_type (inflated);
970 static MonoGenericContext
971 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
973 MonoGenericInst *class_inst = NULL;
974 MonoGenericInst *method_inst = NULL;
975 MonoGenericContext res = { NULL, NULL };
977 mono_error_init (error);
979 if (context->class_inst) {
980 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
981 if (!mono_error_ok (error))
985 if (context->method_inst) {
986 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
987 if (!mono_error_ok (error))
991 res.class_inst = class_inst;
992 res.method_inst = method_inst;
998 * mono_class_inflate_generic_method:
999 * @method: a generic method
1000 * @context: a generics context
1002 * Instantiate the generic method @method using the generics context @context.
1004 * Returns: The new instantiated method
1007 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1009 return mono_class_inflate_generic_method_full (method, NULL, context);
1013 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1015 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1019 * mono_class_inflate_generic_method_full:
1021 * Instantiate method @method with the generic context @context.
1022 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1023 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1026 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1029 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1030 if (!mono_error_ok (&error))
1031 /*FIXME do proper error handling - on this case, kill this function. */
1032 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1038 * mono_class_inflate_generic_method_full_checked:
1039 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1042 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1045 MonoMethodInflated *iresult, *cached;
1046 MonoMethodSignature *sig;
1047 MonoGenericContext tmp_context;
1049 mono_error_init (error);
1051 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1052 while (method->is_inflated) {
1053 MonoGenericContext *method_context = mono_method_get_context (method);
1054 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1056 tmp_context = inflate_generic_context (method_context, context, error);
1057 return_val_if_nok (error, NULL);
1059 context = &tmp_context;
1061 if (mono_metadata_generic_context_equal (method_context, context))
1064 method = imethod->declaring;
1068 * A method only needs to be inflated if the context has argument for which it is
1071 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1072 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1075 if (!((method->is_generic && context->method_inst) ||
1076 (method->klass->generic_container && context->class_inst)))
1079 iresult = g_new0 (MonoMethodInflated, 1);
1080 iresult->context = *context;
1081 iresult->declaring = method;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 /* This can happen with some callers like mono_object_get_virtual_method () */
1094 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = NULL;
1097 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1100 mono_image_set_lock (set);
1101 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1102 mono_image_set_unlock (set);
1106 return (MonoMethod*)cached;
1109 mono_stats.inflated_method_count++;
1111 inflated_methods_size += sizeof (MonoMethodInflated);
1113 sig = mono_method_signature (method);
1115 char *name = mono_type_get_full_name (method->klass);
1116 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1122 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1124 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1127 result = (MonoMethod *) iresult;
1128 result->is_inflated = TRUE;
1129 result->is_generic = FALSE;
1130 result->sre_method = FALSE;
1131 result->signature = NULL;
1133 if (iresult->context.method_inst) {
1134 /* Set the generic_container of the result to the generic_container of method */
1135 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1137 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1138 result->is_generic = 1;
1139 mono_method_set_generic_container (result, generic_container);
1143 if (!klass_hint || !klass_hint->generic_class ||
1144 klass_hint->generic_class->container_class != method->klass ||
1145 klass_hint->generic_class->context.class_inst != context->class_inst)
1148 if (method->klass->generic_container)
1149 result->klass = klass_hint;
1151 if (!result->klass) {
1152 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1153 if (!mono_error_ok (error))
1156 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1158 mono_metadata_free_type (inflated);
1162 * FIXME: This should hold, but it doesn't:
1164 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1165 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1166 * g_assert (result->is_generic);
1169 * Fixing this here causes other things to break, hence a very
1170 * ugly hack in mini-trampolines.c - see
1171 * is_generic_method_definition().
1175 mono_image_set_lock (set);
1176 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1178 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1179 iresult->owner = set;
1182 mono_image_set_unlock (set);
1184 return (MonoMethod*)cached;
1192 * mono_get_inflated_method:
1194 * Obsolete. We keep it around since it's mentioned in the public API.
1197 mono_get_inflated_method (MonoMethod *method)
1203 * mono_method_get_context_general:
1205 * @uninflated: handle uninflated methods?
1207 * Returns the generic context of a method or NULL if it doesn't have
1208 * one. For an inflated method that's the context stored in the
1209 * method. Otherwise it's in the method's generic container or in the
1210 * generic container of the method's class.
1213 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1215 if (method->is_inflated) {
1216 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1217 return &imethod->context;
1221 if (method->is_generic)
1222 return &(mono_method_get_generic_container (method)->context);
1223 if (method->klass->generic_container)
1224 return &method->klass->generic_container->context;
1229 * mono_method_get_context:
1232 * Returns the generic context for method if it's inflated, otherwise
1236 mono_method_get_context (MonoMethod *method)
1238 return mono_method_get_context_general (method, FALSE);
1242 * mono_method_get_generic_container:
1244 * Returns the generic container of METHOD, which should be a generic method definition.
1245 * Returns NULL if METHOD is not a generic method definition.
1246 * LOCKING: Acquires the loader lock.
1248 MonoGenericContainer*
1249 mono_method_get_generic_container (MonoMethod *method)
1251 MonoGenericContainer *container;
1253 if (!method->is_generic)
1256 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1257 g_assert (container);
1263 * mono_method_set_generic_container:
1265 * Sets the generic container of METHOD to CONTAINER.
1266 * LOCKING: Acquires the image lock.
1269 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1271 g_assert (method->is_generic);
1273 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1277 * mono_class_find_enum_basetype:
1278 * @class: The enum class
1280 * Determine the basetype of an enum by iterating through its fields. We do this
1281 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1284 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1286 MonoGenericContainer *container = NULL;
1287 MonoImage *m = klass->image;
1288 const int top = klass->field.count;
1291 g_assert (klass->enumtype);
1293 mono_error_init (error);
1295 if (klass->generic_container)
1296 container = klass->generic_container;
1297 else if (klass->generic_class) {
1298 MonoClass *gklass = klass->generic_class->container_class;
1300 container = gklass->generic_container;
1301 g_assert (container);
1305 * Fetch all the field information.
1307 for (i = 0; i < top; i++){
1309 guint32 cols [MONO_FIELD_SIZE];
1310 int idx = klass->field.first + i;
1313 /* klass->field.first and idx points into the fieldptr table */
1314 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1316 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1319 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1320 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1324 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1325 mono_metadata_decode_value (sig, &sig);
1326 /* FIELD signature == 0x06 */
1328 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1332 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1336 if (klass->generic_class) {
1337 //FIXME do we leak here?
1338 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1339 if (!mono_error_ok (error))
1341 ftype->attrs = cols [MONO_FIELD_FLAGS];
1346 mono_error_set_type_load_class (error, klass, "Could not find base type");
1353 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1356 mono_type_has_exceptions (MonoType *type)
1358 switch (type->type) {
1359 case MONO_TYPE_CLASS:
1360 case MONO_TYPE_VALUETYPE:
1361 case MONO_TYPE_SZARRAY:
1362 return mono_class_has_failure (type->data.klass);
1363 case MONO_TYPE_ARRAY:
1364 return mono_class_has_failure (type->data.array->eklass);
1365 case MONO_TYPE_GENERICINST:
1366 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1375 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1379 mono_class_alloc (MonoClass *klass, int size)
1381 if (klass->generic_class)
1382 return mono_image_set_alloc (klass->generic_class->owner, size);
1384 return mono_image_alloc (klass->image, size);
1388 mono_class_alloc0 (MonoClass *klass, int size)
1392 res = mono_class_alloc (klass, size);
1393 memset (res, 0, size);
1397 #define mono_class_new0(klass,struct_type, n_structs) \
1398 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1401 * mono_class_setup_basic_field_info:
1402 * @class: The class to initialize
1404 * Initializes the klass->fields.
1405 * LOCKING: Assumes the loader lock is held.
1408 mono_class_setup_basic_field_info (MonoClass *klass)
1410 MonoClassField *field;
1418 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1419 image = klass->image;
1420 top = klass->field.count;
1422 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1424 * This happens when a generic instance of an unfinished generic typebuilder
1425 * is used as an element type for creating an array type. We can't initialize
1426 * the fields of this class using the fields of gklass, since gklass is not
1427 * finished yet, fields could be added to it later.
1433 mono_class_setup_basic_field_info (gtd);
1435 top = gtd->field.count;
1436 klass->field.first = gtd->field.first;
1437 klass->field.count = gtd->field.count;
1440 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1443 * Fetch all the field information.
1445 for (i = 0; i < top; i++){
1446 field = &klass->fields [i];
1447 field->parent = klass;
1450 field->name = mono_field_get_name (>d->fields [i]);
1452 int idx = klass->field.first + i;
1453 /* klass->field.first and idx points into the fieldptr table */
1454 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1455 /* The name is needed for fieldrefs */
1456 field->name = mono_metadata_string_heap (image, name_idx);
1462 * mono_class_setup_fields:
1463 * @class: The class to initialize
1465 * Initializes the klass->fields.
1466 * LOCKING: Assumes the loader lock is held.
1469 mono_class_setup_fields (MonoClass *klass)
1472 MonoImage *m = klass->image;
1474 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1475 int i, blittable = TRUE;
1476 guint32 real_size = 0;
1477 guint32 packing_size = 0;
1479 gboolean explicit_size;
1480 MonoClassField *field;
1481 MonoGenericContainer *container = NULL;
1482 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1485 * FIXME: We have a race condition here. It's possible that this function returns
1486 * to its caller with `instance_size` set to `0` instead of the actual size. This
1487 * is not a problem when the function is called recursively on the same class,
1488 * because the size will be initialized by the outer invocation. What follows is a
1489 * description of how it can occur in other cases, too. There it is a problem,
1490 * because it can lead to the GC being asked to allocate an object of size `0`,
1491 * which SGen chokes on. The race condition is triggered infrequently by
1492 * `tests/sgen-suspend.cs`.
1494 * This function is called for a class whenever one of its subclasses is inited.
1495 * For example, it's called for every subclass of Object. What it does is this:
1497 * if (klass->setup_fields_called)
1500 * klass->instance_size = 0;
1502 * klass->setup_fields_called = 1;
1503 * ... critical point
1504 * klass->instance_size = actual_instance_size;
1506 * The last two steps are sometimes reversed, but that only changes the way in which
1507 * the race condition works.
1509 * Assume thread A goes through this function and makes it to the critical point.
1510 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1511 * immediately, but `instance_size` is incorrect.
1513 * The other case looks like this:
1515 * if (klass->setup_fields_called)
1517 * ... critical point X
1518 * klass->instance_size = 0;
1519 * ... critical point Y
1520 * klass->instance_size = actual_instance_size;
1522 * klass->setup_fields_called = 1;
1524 * Assume thread A goes through the function and makes it to critical point X. Now
1525 * thread B runs through the whole of the function, returning, assuming
1526 * `instance_size` is set. At that point thread A gets to run and makes it to
1527 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1530 if (klass->setup_fields_called)
1533 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1535 * This happens when a generic instance of an unfinished generic typebuilder
1536 * is used as an element type for creating an array type. We can't initialize
1537 * the fields of this class using the fields of gklass, since gklass is not
1538 * finished yet, fields could be added to it later.
1543 mono_class_setup_basic_field_info (klass);
1544 top = klass->field.count;
1547 mono_class_setup_fields (gtd);
1548 if (mono_class_has_failure (gtd)) {
1549 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1556 klass->sizes.class_size = 0;
1558 if (klass->parent) {
1559 /* For generic instances, klass->parent might not have been initialized */
1560 mono_class_init (klass->parent);
1561 if (!klass->parent->size_inited) {
1562 mono_class_setup_fields (klass->parent);
1563 if (mono_class_has_failure (klass->parent)) {
1564 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1568 instance_size += klass->parent->instance_size;
1569 klass->min_align = klass->parent->min_align;
1570 /* we use |= since it may have been set already */
1571 klass->has_references |= klass->parent->has_references;
1572 blittable = klass->parent->blittable;
1574 instance_size = sizeof (MonoObject);
1575 klass->min_align = 1;
1578 /* We can't really enable 16 bytes alignment until the GC supports it.
1579 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1580 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1581 Bug #506144 is an example of this issue.
1583 if (klass->simd_type)
1584 klass->min_align = 16;
1586 /* Get the real size */
1587 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1589 if (explicit_size) {
1590 if ((packing_size & 0xffffff00) != 0) {
1591 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1592 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1595 klass->packing_size = packing_size;
1596 real_size += instance_size;
1600 if (explicit_size && real_size) {
1601 instance_size = MAX (real_size, instance_size);
1603 klass->blittable = blittable;
1604 if (!klass->instance_size)
1605 klass->instance_size = instance_size;
1606 mono_memory_barrier ();
1607 klass->size_inited = 1;
1608 klass->fields_inited = 1;
1609 klass->setup_fields_called = 1;
1613 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1616 /* Prevent infinite loops if the class references itself */
1617 klass->setup_fields_called = 1;
1619 if (klass->generic_container) {
1620 container = klass->generic_container;
1622 container = gtd->generic_container;
1623 g_assert (container);
1627 * Fetch all the field information.
1629 for (i = 0; i < top; i++){
1630 int idx = klass->field.first + i;
1631 field = &klass->fields [i];
1633 field->parent = klass;
1636 mono_field_resolve_type (field, &error);
1637 if (!mono_error_ok (&error)) {
1638 /*mono_field_resolve_type already failed class*/
1639 mono_error_cleanup (&error);
1643 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1644 g_assert (field->type);
1647 if (mono_field_is_deleted (field))
1650 MonoClassField *gfield = >d->fields [i];
1651 field->offset = gfield->offset;
1653 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1655 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1656 field->offset = offset;
1658 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1659 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1662 if (field->offset < -1) { /*-1 is used to encode special static fields */
1663 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1666 if (klass->generic_container) {
1667 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1673 /* Only do these checks if we still think this type is blittable */
1674 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1675 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1678 MonoClass *field_class = mono_class_from_mono_type (field->type);
1680 mono_class_setup_fields (field_class);
1681 if (mono_class_has_failure (field_class)) {
1682 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1686 if (!field_class || !field_class->blittable)
1691 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1692 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1693 blittable = klass->element_class->blittable;
1696 if (mono_type_has_exceptions (field->type)) {
1697 char *class_name = mono_type_get_full_name (klass);
1698 char *type_name = mono_type_full_name (field->type);
1700 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1701 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1702 g_free (class_name);
1706 /* The def_value of fields is compute lazily during vtable creation */
1709 if (klass == mono_defaults.string_class)
1712 klass->blittable = blittable;
1714 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1715 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1718 if (explicit_size && real_size) {
1719 instance_size = MAX (real_size, instance_size);
1722 if (mono_class_has_failure (klass))
1724 mono_class_layout_fields (klass, instance_size);
1726 /*valuetypes can't be neither bigger than 1Mb or empty. */
1727 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1728 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1730 mono_memory_barrier ();
1731 klass->fields_inited = 1;
1735 * mono_class_setup_fields_locking:
1736 * @class: The class to initialize
1738 * Initializes the klass->fields array of fields.
1739 * Aquires the loader lock.
1742 mono_class_setup_fields_locking (MonoClass *klass)
1744 /* This can be checked without locks */
1745 if (klass->fields_inited)
1747 mono_loader_lock ();
1748 mono_class_setup_fields (klass);
1749 mono_loader_unlock ();
1753 * mono_class_has_references:
1755 * Returns whenever @klass->has_references is set, initializing it if needed.
1756 * Aquires the loader lock.
1759 mono_class_has_references (MonoClass *klass)
1761 if (klass->init_pending) {
1762 /* Be conservative */
1765 mono_class_init (klass);
1767 return klass->has_references;
1772 * mono_type_get_basic_type_from_generic:
1775 * Returns a closed type corresponding to the possibly open type
1779 mono_type_get_basic_type_from_generic (MonoType *type)
1781 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1782 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1783 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1784 return &mono_defaults.object_class->byval_arg;
1789 type_has_references (MonoClass *klass, MonoType *ftype)
1791 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)))))
1793 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1794 MonoGenericParam *gparam = ftype->data.generic_param;
1796 if (gparam->gshared_constraint)
1797 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1803 * mono_class_layout_fields:
1805 * @instance_size: base instance size
1807 * Compute the placement of fields inside an object or struct, according to
1808 * the layout rules and set the following fields in @class:
1809 * - has_references (if the class contains instance references firled or structs that contain references)
1810 * - has_static_refs (same, but for static fields)
1811 * - instance_size (size of the object in memory)
1812 * - class_size (size needed for the static fields)
1813 * - size_inited (flag set when the instance_size is set)
1815 * LOCKING: this is supposed to be called with the loader lock held.
1818 mono_class_layout_fields (MonoClass *klass, int instance_size)
1821 const int top = klass->field.count;
1822 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1823 guint32 pass, passes, real_size;
1824 gboolean gc_aware_layout = FALSE;
1825 gboolean has_static_fields = FALSE;
1826 MonoClassField *field;
1829 * When we do generic sharing we need to have layout
1830 * information for open generic classes (either with a generic
1831 * context containing type variables or with a generic
1832 * container), so we don't return in that case anymore.
1836 * Enable GC aware auto layout: in this mode, reference
1837 * fields are grouped together inside objects, increasing collector
1839 * Requires that all classes whose layout is known to native code be annotated
1840 * with [StructLayout (LayoutKind.Sequential)]
1841 * Value types have gc_aware_layout disabled by default, as per
1842 * what the default is for other runtimes.
1844 /* corlib is missing [StructLayout] directives in many places */
1845 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1846 if (!klass->valuetype)
1847 gc_aware_layout = TRUE;
1850 /* Compute klass->has_references */
1852 * Process non-static fields first, since static fields might recursively
1853 * refer to the class itself.
1855 for (i = 0; i < top; i++) {
1858 field = &klass->fields [i];
1860 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1861 ftype = mono_type_get_underlying_type (field->type);
1862 ftype = mono_type_get_basic_type_from_generic (ftype);
1863 if (type_has_references (klass, ftype))
1864 klass->has_references = TRUE;
1868 for (i = 0; i < top; i++) {
1871 field = &klass->fields [i];
1873 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1874 ftype = mono_type_get_underlying_type (field->type);
1875 ftype = mono_type_get_basic_type_from_generic (ftype);
1876 if (type_has_references (klass, ftype))
1877 klass->has_static_refs = TRUE;
1881 for (i = 0; i < top; i++) {
1884 field = &klass->fields [i];
1886 ftype = mono_type_get_underlying_type (field->type);
1887 ftype = mono_type_get_basic_type_from_generic (ftype);
1888 if (type_has_references (klass, ftype)) {
1889 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1890 klass->has_static_refs = TRUE;
1892 klass->has_references = TRUE;
1897 * Compute field layout and total size (not considering static fields)
1900 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1901 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1903 if (gc_aware_layout)
1908 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1911 if (klass->parent) {
1912 mono_class_setup_fields (klass->parent);
1913 if (mono_class_has_failure (klass->parent)) {
1914 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1917 real_size = klass->parent->instance_size;
1919 real_size = sizeof (MonoObject);
1922 for (pass = 0; pass < passes; ++pass) {
1923 for (i = 0; i < top; i++){
1928 field = &klass->fields [i];
1930 if (mono_field_is_deleted (field))
1932 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1935 ftype = mono_type_get_underlying_type (field->type);
1936 ftype = mono_type_get_basic_type_from_generic (ftype);
1937 if (gc_aware_layout) {
1938 if (type_has_references (klass, ftype)) {
1947 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1948 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1949 /* This field is a hack inserted by MCS to empty structures */
1953 size = mono_type_size (field->type, &align);
1955 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1956 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1957 /* if the field has managed references, we need to force-align it
1960 if (type_has_references (klass, ftype))
1961 align = MAX (align, sizeof (gpointer));
1963 klass->min_align = MAX (align, klass->min_align);
1964 field->offset = real_size;
1966 field->offset += align - 1;
1967 field->offset &= ~(align - 1);
1969 /*TypeBuilders produce all sort of weird things*/
1970 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1971 real_size = field->offset + size;
1974 instance_size = MAX (real_size, instance_size);
1976 if (instance_size & (klass->min_align - 1)) {
1977 instance_size += klass->min_align - 1;
1978 instance_size &= ~(klass->min_align - 1);
1982 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1986 for (i = 0; i < top; i++) {
1991 field = &klass->fields [i];
1994 * There must be info about all the fields in a type if it
1995 * uses explicit layout.
1997 if (mono_field_is_deleted (field))
1999 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2002 size = mono_type_size (field->type, &align);
2003 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2004 klass->min_align = MAX (align, klass->min_align);
2007 * When we get here, field->offset is already set by the
2008 * loader (for either runtime fields or fields loaded from metadata).
2009 * The offset is from the start of the object: this works for both
2010 * classes and valuetypes.
2012 field->offset += sizeof (MonoObject);
2013 ftype = mono_type_get_underlying_type (field->type);
2014 ftype = mono_type_get_basic_type_from_generic (ftype);
2015 if (type_has_references (klass, ftype)) {
2016 if (field->offset % sizeof (gpointer)) {
2017 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2024 real_size = MAX (real_size, size + field->offset);
2027 if (klass->has_references) {
2028 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2030 /* Check for overlapping reference and non-reference fields */
2031 for (i = 0; i < top; i++) {
2034 field = &klass->fields [i];
2036 if (mono_field_is_deleted (field))
2038 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2040 ftype = mono_type_get_underlying_type (field->type);
2041 if (MONO_TYPE_IS_REFERENCE (ftype))
2042 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2044 for (i = 0; i < top; i++) {
2045 field = &klass->fields [i];
2047 if (mono_field_is_deleted (field))
2049 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2052 // FIXME: Too much code does this
2054 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2055 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field->offset);
2056 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2060 g_free (ref_bitmap);
2063 instance_size = MAX (real_size, instance_size);
2064 if (instance_size & (klass->min_align - 1)) {
2065 instance_size += klass->min_align - 1;
2066 instance_size &= ~(klass->min_align - 1);
2072 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2074 * This leads to all kinds of problems with nested structs, so only
2075 * enable it when a MONO_DEBUG property is set.
2077 * For small structs, set min_align to at least the struct size to improve
2078 * performance, and since the JIT memset/memcpy code assumes this and generates
2079 * unaligned accesses otherwise. See #78990 for a testcase.
2081 if (mono_align_small_structs) {
2082 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2083 klass->min_align = MAX (klass->min_align, instance_size - sizeof (MonoObject));
2087 if (klass->instance_size && !klass->image->dynamic) {
2088 /* Might be already set using cached info */
2089 g_assert (klass->instance_size == instance_size);
2091 klass->instance_size = instance_size;
2093 mono_memory_barrier ();
2094 klass->size_inited = 1;
2097 * Compute static field layout and size
2099 for (i = 0; i < top; i++){
2103 field = &klass->fields [i];
2105 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2107 if (mono_field_is_deleted (field))
2110 if (mono_type_has_exceptions (field->type)) {
2111 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2115 has_static_fields = TRUE;
2117 size = mono_type_size (field->type, &align);
2118 field->offset = klass->sizes.class_size;
2119 /*align is always non-zero here*/
2120 field->offset += align - 1;
2121 field->offset &= ~(align - 1);
2122 klass->sizes.class_size = field->offset + size;
2125 if (has_static_fields && klass->sizes.class_size == 0)
2126 /* Simplify code which depends on class_size != 0 if the class has static fields */
2127 klass->sizes.class_size = 8;
2131 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2135 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2136 method->klass = klass;
2137 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2138 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2139 method->signature = sig;
2140 method->name = name;
2143 if (name [0] == '.') {
2144 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2146 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2152 * mono_class_setup_methods:
2155 * Initializes the 'methods' array in CLASS.
2156 * Calling this method should be avoided if possible since it allocates a lot
2157 * of long-living MonoMethod structures.
2158 * Methods belonging to an interface are assigned a sequential slot starting
2161 * On failure this function sets klass->exception_type
2164 mono_class_setup_methods (MonoClass *klass)
2167 MonoMethod **methods;
2172 if (klass->generic_class) {
2174 MonoClass *gklass = klass->generic_class->container_class;
2176 mono_class_init (gklass);
2177 if (!mono_class_has_failure (gklass))
2178 mono_class_setup_methods (gklass);
2179 if (mono_class_has_failure (gklass)) {
2180 /* FIXME make exception_data less opaque so it's possible to dup it here */
2181 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2185 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2186 count = gklass->method.count;
2187 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2189 for (i = 0; i < count; i++) {
2190 methods [i] = mono_class_inflate_generic_method_full_checked (
2191 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2192 if (!mono_error_ok (&error)) {
2193 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2194 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2197 mono_error_cleanup (&error);
2201 } else if (klass->rank) {
2203 MonoMethod *amethod;
2204 MonoMethodSignature *sig;
2205 int count_generic = 0, first_generic = 0;
2207 gboolean jagged_ctor = FALSE;
2209 count = 3 + (klass->rank > 1? 2: 1);
2211 mono_class_setup_interfaces (klass, &error);
2212 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2214 if (klass->rank == 1 && klass->element_class->rank) {
2216 klass->method.count ++;
2219 if (klass->interface_count) {
2220 count_generic = generic_array_methods (klass);
2221 first_generic = count;
2222 count += klass->interface_count * count_generic;
2225 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2227 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2228 sig->ret = &mono_defaults.void_class->byval_arg;
2229 sig->pinvoke = TRUE;
2230 sig->hasthis = TRUE;
2231 for (i = 0; i < klass->rank; ++i)
2232 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2234 amethod = create_array_method (klass, ".ctor", sig);
2235 methods [method_num++] = amethod;
2236 if (klass->rank > 1) {
2237 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2238 sig->ret = &mono_defaults.void_class->byval_arg;
2239 sig->pinvoke = TRUE;
2240 sig->hasthis = TRUE;
2241 for (i = 0; i < klass->rank * 2; ++i)
2242 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2244 amethod = create_array_method (klass, ".ctor", sig);
2245 methods [method_num++] = amethod;
2249 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2250 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2251 sig->ret = &mono_defaults.void_class->byval_arg;
2252 sig->pinvoke = TRUE;
2253 sig->hasthis = TRUE;
2254 for (i = 0; i < klass->rank + 1; ++i)
2255 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2256 amethod = create_array_method (klass, ".ctor", sig);
2257 methods [method_num++] = amethod;
2260 /* element Get (idx11, [idx2, ...]) */
2261 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2262 sig->ret = &klass->element_class->byval_arg;
2263 sig->pinvoke = TRUE;
2264 sig->hasthis = TRUE;
2265 for (i = 0; i < klass->rank; ++i)
2266 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2267 amethod = create_array_method (klass, "Get", sig);
2268 methods [method_num++] = amethod;
2269 /* element& Address (idx11, [idx2, ...]) */
2270 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2271 sig->ret = &klass->element_class->this_arg;
2272 sig->pinvoke = TRUE;
2273 sig->hasthis = TRUE;
2274 for (i = 0; i < klass->rank; ++i)
2275 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2276 amethod = create_array_method (klass, "Address", sig);
2277 methods [method_num++] = amethod;
2278 /* void Set (idx11, [idx2, ...], element) */
2279 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2280 sig->ret = &mono_defaults.void_class->byval_arg;
2281 sig->pinvoke = TRUE;
2282 sig->hasthis = TRUE;
2283 for (i = 0; i < klass->rank; ++i)
2284 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2285 sig->params [i] = &klass->element_class->byval_arg;
2286 amethod = create_array_method (klass, "Set", sig);
2287 methods [method_num++] = amethod;
2289 for (i = 0; i < klass->interface_count; i++)
2290 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2294 count = klass->method.count;
2295 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2296 for (i = 0; i < count; ++i) {
2297 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2298 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2300 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2301 mono_error_cleanup (&error);
2306 if (MONO_CLASS_IS_INTERFACE (klass)) {
2308 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2309 for (i = 0; i < count; ++i) {
2310 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2311 methods [i]->slot = slot++;
2315 mono_image_lock (klass->image);
2317 if (!klass->methods) {
2318 klass->method.count = count;
2320 /* Needed because of the double-checking locking pattern */
2321 mono_memory_barrier ();
2323 klass->methods = methods;
2326 mono_image_unlock (klass->image);
2330 * mono_class_get_method_by_index:
2332 * Returns klass->methods [index], initializing klass->methods if neccesary.
2334 * LOCKING: Acquires the loader lock.
2337 mono_class_get_method_by_index (MonoClass *klass, int index)
2340 /* Avoid calling setup_methods () if possible */
2341 if (klass->generic_class && !klass->methods) {
2342 MonoClass *gklass = klass->generic_class->container_class;
2345 m = mono_class_inflate_generic_method_full_checked (
2346 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2347 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2349 * If setup_methods () is called later for this class, no duplicates are created,
2350 * since inflate_generic_method guarantees that only one instance of a method
2351 * is created for each context.
2354 mono_class_setup_methods (klass);
2355 g_assert (m == klass->methods [index]);
2359 mono_class_setup_methods (klass);
2360 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2362 g_assert (index >= 0 && index < klass->method.count);
2363 return klass->methods [index];
2368 * mono_class_get_inflated_method:
2370 * Given an inflated class CLASS and a method METHOD which should be a method of
2371 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2374 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2376 MonoClass *gklass = klass->generic_class->container_class;
2379 g_assert (method->klass == gklass);
2381 mono_class_setup_methods (gklass);
2382 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2384 for (i = 0; i < gklass->method.count; ++i) {
2385 if (gklass->methods [i] == method) {
2386 if (klass->methods) {
2387 return klass->methods [i];
2390 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2391 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2401 * mono_class_get_vtable_entry:
2403 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2404 * LOCKING: Acquires the loader lock.
2407 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2411 if (klass->rank == 1) {
2413 * szarrays do not overwrite any methods of Array, so we can avoid
2414 * initializing their vtables in some cases.
2416 mono_class_setup_vtable (klass->parent);
2417 if (offset < klass->parent->vtable_size)
2418 return klass->parent->vtable [offset];
2421 if (klass->generic_class) {
2423 MonoClass *gklass = klass->generic_class->container_class;
2424 mono_class_setup_vtable (gklass);
2425 m = gklass->vtable [offset];
2427 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2428 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2430 mono_class_setup_vtable (klass);
2431 if (mono_class_has_failure (klass))
2433 m = klass->vtable [offset];
2440 * mono_class_get_vtable_size:
2442 * Return the vtable size for KLASS.
2445 mono_class_get_vtable_size (MonoClass *klass)
2447 mono_class_setup_vtable (klass);
2449 return klass->vtable_size;
2453 * mono_class_setup_properties:
2455 * Initialize klass->ext.property and klass->ext.properties.
2457 * This method can fail the class.
2460 mono_class_setup_properties (MonoClass *klass)
2462 guint startm, endm, i, j;
2463 guint32 cols [MONO_PROPERTY_SIZE];
2464 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2465 MonoProperty *properties;
2469 if (klass->ext && klass->ext->properties)
2472 if (klass->generic_class) {
2473 MonoClass *gklass = klass->generic_class->container_class;
2475 mono_class_init (gklass);
2476 mono_class_setup_properties (gklass);
2477 if (mono_class_has_failure (gklass)) {
2478 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2482 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2484 for (i = 0; i < gklass->ext->property.count; i++) {
2486 MonoProperty *prop = &properties [i];
2488 *prop = gklass->ext->properties [i];
2491 prop->get = mono_class_inflate_generic_method_full_checked (
2492 prop->get, klass, mono_class_get_context (klass), &error);
2494 prop->set = mono_class_inflate_generic_method_full_checked (
2495 prop->set, klass, mono_class_get_context (klass), &error);
2497 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2498 prop->parent = klass;
2501 first = gklass->ext->property.first;
2502 count = gklass->ext->property.count;
2504 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2505 count = last - first;
2508 mono_class_setup_methods (klass);
2509 if (mono_class_has_failure (klass))
2513 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2514 for (i = first; i < last; ++i) {
2515 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2516 properties [i - first].parent = klass;
2517 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2518 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2520 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2521 for (j = startm; j < endm; ++j) {
2524 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2526 if (klass->image->uncompressed_metadata) {
2528 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2529 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2530 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2532 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2535 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2536 case METHOD_SEMANTIC_SETTER:
2537 properties [i - first].set = method;
2539 case METHOD_SEMANTIC_GETTER:
2540 properties [i - first].get = method;
2549 mono_class_alloc_ext (klass);
2551 mono_image_lock (klass->image);
2553 if (klass->ext->properties) {
2554 /* We leak 'properties' which was allocated from the image mempool */
2555 mono_image_unlock (klass->image);
2559 klass->ext->property.first = first;
2560 klass->ext->property.count = count;
2562 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2563 mono_memory_barrier ();
2565 /* Leave this assignment as the last op in the function */
2566 klass->ext->properties = properties;
2568 mono_image_unlock (klass->image);
2572 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2574 MonoMethod **om, **retval;
2577 for (om = methods, count = 0; *om; ++om, ++count)
2580 retval = g_new0 (MonoMethod*, count + 1);
2582 for (om = methods, count = 0; *om; ++om, ++count) {
2584 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2585 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2591 /*This method can fail the class.*/
2593 mono_class_setup_events (MonoClass *klass)
2596 guint startm, endm, i, j;
2597 guint32 cols [MONO_EVENT_SIZE];
2598 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2602 if (klass->ext && klass->ext->events)
2605 if (klass->generic_class) {
2606 MonoClass *gklass = klass->generic_class->container_class;
2607 MonoGenericContext *context = NULL;
2609 mono_class_setup_events (gklass);
2610 if (mono_class_has_failure (gklass)) {
2611 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2615 first = gklass->ext->event.first;
2616 count = gklass->ext->event.count;
2618 events = mono_class_new0 (klass, MonoEvent, count);
2621 context = mono_class_get_context (klass);
2623 for (i = 0; i < count; i++) {
2625 MonoEvent *event = &events [i];
2626 MonoEvent *gevent = &gklass->ext->events [i];
2628 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2630 event->parent = klass;
2631 event->name = gevent->name;
2632 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2633 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2634 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2635 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2636 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2637 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2639 #ifndef MONO_SMALL_CONFIG
2640 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2642 event->attrs = gevent->attrs;
2645 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2646 count = last - first;
2649 mono_class_setup_methods (klass);
2650 if (mono_class_has_failure (klass)) {
2651 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2656 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2657 for (i = first; i < last; ++i) {
2658 MonoEvent *event = &events [i - first];
2660 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2661 event->parent = klass;
2662 event->attrs = cols [MONO_EVENT_FLAGS];
2663 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2665 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2666 for (j = startm; j < endm; ++j) {
2669 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2671 if (klass->image->uncompressed_metadata) {
2673 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2674 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2675 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2677 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2680 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2681 case METHOD_SEMANTIC_ADD_ON:
2682 event->add = method;
2684 case METHOD_SEMANTIC_REMOVE_ON:
2685 event->remove = method;
2687 case METHOD_SEMANTIC_FIRE:
2688 event->raise = method;
2690 case METHOD_SEMANTIC_OTHER: {
2691 #ifndef MONO_SMALL_CONFIG
2694 if (event->other == NULL) {
2695 event->other = g_new0 (MonoMethod*, 2);
2697 while (event->other [n])
2699 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2701 event->other [n] = method;
2702 /* NULL terminated */
2703 event->other [n + 1] = NULL;
2714 mono_class_alloc_ext (klass);
2716 mono_image_lock (klass->image);
2718 if (klass->ext->events) {
2719 mono_image_unlock (klass->image);
2723 klass->ext->event.first = first;
2724 klass->ext->event.count = count;
2726 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2727 mono_memory_barrier ();
2729 /* Leave this assignment as the last op in the function */
2730 klass->ext->events = events;
2732 mono_image_unlock (klass->image);
2736 * Global pool of interface IDs, represented as a bitset.
2737 * LOCKING: Protected by the classes lock.
2739 static MonoBitSet *global_interface_bitset = NULL;
2742 * mono_unload_interface_ids:
2743 * @bitset: bit set of interface IDs
2745 * When an image is unloaded, the interface IDs associated with
2746 * the image are put back in the global pool of IDs so the numbers
2750 mono_unload_interface_ids (MonoBitSet *bitset)
2753 mono_bitset_sub (global_interface_bitset, bitset);
2758 mono_unload_interface_id (MonoClass *klass)
2760 if (global_interface_bitset && klass->interface_id) {
2762 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2768 * mono_get_unique_iid:
2771 * Assign a unique integer ID to the interface represented by @class.
2772 * The ID will positive and as small as possible.
2773 * LOCKING: Acquires the classes lock.
2774 * Returns: The new ID.
2777 mono_get_unique_iid (MonoClass *klass)
2781 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2785 if (!global_interface_bitset) {
2786 global_interface_bitset = mono_bitset_new (128, 0);
2789 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2791 int old_size = mono_bitset_size (global_interface_bitset);
2792 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2793 mono_bitset_free (global_interface_bitset);
2794 global_interface_bitset = new_set;
2797 mono_bitset_set (global_interface_bitset, iid);
2798 /* set the bit also in the per-image set */
2799 if (!klass->generic_class) {
2800 if (klass->image->interface_bitset) {
2801 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2802 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2803 mono_bitset_free (klass->image->interface_bitset);
2804 klass->image->interface_bitset = new_set;
2807 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2809 mono_bitset_set (klass->image->interface_bitset, iid);
2814 #ifndef MONO_SMALL_CONFIG
2815 if (mono_print_vtable) {
2817 char *type_name = mono_type_full_name (&klass->byval_arg);
2818 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2819 generic_id = klass->generic_class->context.class_inst->id;
2820 g_assert (generic_id != 0);
2824 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2829 g_assert (iid <= 65535);
2834 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2839 mono_class_setup_interfaces (klass, error);
2840 return_if_nok (error);
2842 for (i = 0; i < klass->interface_count; i++) {
2843 ic = klass->interfaces [i];
2846 *res = g_ptr_array_new ();
2847 g_ptr_array_add (*res, ic);
2848 mono_class_init (ic);
2849 if (mono_class_has_failure (ic)) {
2850 mono_error_set_type_load_class (error, ic, "Error Loading class");
2854 collect_implemented_interfaces_aux (ic, res, error);
2855 return_if_nok (error);
2860 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2862 GPtrArray *res = NULL;
2864 collect_implemented_interfaces_aux (klass, &res, error);
2865 if (!mono_error_ok (error)) {
2867 g_ptr_array_free (res, TRUE);
2874 compare_interface_ids (const void *p_key, const void *p_element) {
2875 const MonoClass *key = (const MonoClass *)p_key;
2876 const MonoClass *element = *(const MonoClass **)p_element;
2878 return (key->interface_id - element->interface_id);
2881 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2883 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2884 MonoClass **result = (MonoClass **)mono_binary_search (
2886 klass->interfaces_packed,
2887 klass->interface_offsets_count,
2888 sizeof (MonoClass *),
2889 compare_interface_ids);
2891 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2898 * mono_class_interface_offset_with_variance:
2900 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2901 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2903 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2905 * FIXME figure out MS disambiguation rules and fix this function.
2908 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2909 int i = mono_class_interface_offset (klass, itf);
2910 *non_exact_match = FALSE;
2914 if (!mono_class_has_variant_generic_params (itf))
2917 for (i = 0; i < klass->interface_offsets_count; i++) {
2918 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2919 *non_exact_match = TRUE;
2920 return klass->interface_offsets_packed [i];
2928 print_implemented_interfaces (MonoClass *klass) {
2931 GPtrArray *ifaces = NULL;
2933 int ancestor_level = 0;
2935 name = mono_type_get_full_name (klass);
2936 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2939 for (i = 0; i < klass->interface_offsets_count; i++)
2940 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2941 klass->interfaces_packed [i]->interface_id,
2942 klass->interface_offsets_packed [i],
2943 klass->interfaces_packed [i]->method.count,
2944 klass->interfaces_packed [i]->name_space,
2945 klass->interfaces_packed [i]->name );
2946 printf ("Interface flags: ");
2947 for (i = 0; i <= klass->max_interface_id; i++)
2948 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2949 printf ("(%d,T)", i);
2951 printf ("(%d,F)", i);
2953 printf ("Dump interface flags:");
2954 #ifdef COMPRESSED_INTERFACE_BITMAP
2956 const uint8_t* p = klass->interface_bitmap;
2957 i = klass->max_interface_id;
2959 printf (" %d x 00 %02X", p [0], p [1]);
2965 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2966 printf (" %02X", klass->interface_bitmap [i]);
2969 while (klass != NULL) {
2970 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2971 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2972 if (!mono_error_ok (&error)) {
2973 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2974 mono_error_cleanup (&error);
2975 } else if (ifaces) {
2976 for (i = 0; i < ifaces->len; i++) {
2977 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2978 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2979 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2981 mono_class_interface_offset (klass, ic),
2986 g_ptr_array_free (ifaces, TRUE);
2989 klass = klass->parent;
2994 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2997 args [0] = &arg0->byval_arg;
2999 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3003 array_class_get_if_rank (MonoClass *klass, guint rank)
3005 return rank ? mono_array_class_get (klass, rank) : klass;
3009 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3011 valuetype_types [0] = eclass;
3012 if (eclass == mono_defaults.int16_class)
3013 valuetype_types [1] = mono_defaults.uint16_class;
3014 else if (eclass == mono_defaults.uint16_class)
3015 valuetype_types [1] = mono_defaults.int16_class;
3016 else if (eclass == mono_defaults.int32_class)
3017 valuetype_types [1] = mono_defaults.uint32_class;
3018 else if (eclass == mono_defaults.uint32_class)
3019 valuetype_types [1] = mono_defaults.int32_class;
3020 else if (eclass == mono_defaults.int64_class)
3021 valuetype_types [1] = mono_defaults.uint64_class;
3022 else if (eclass == mono_defaults.uint64_class)
3023 valuetype_types [1] = mono_defaults.int64_class;
3024 else if (eclass == mono_defaults.byte_class)
3025 valuetype_types [1] = mono_defaults.sbyte_class;
3026 else if (eclass == mono_defaults.sbyte_class)
3027 valuetype_types [1] = mono_defaults.byte_class;
3028 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3029 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3032 /* this won't be needed once bug #325495 is completely fixed
3033 * though we'll need something similar to know which interfaces to allow
3034 * in arrays when they'll be lazyly created
3036 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3037 * MS returns diferrent types based on which instance is called. For example:
3038 * object obj = new byte[10][];
3039 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3040 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3043 * Fixing this should kill quite some code, save some bits and improve compatibility.
3046 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3048 MonoClass *eclass = klass->element_class;
3049 static MonoClass* generic_icollection_class = NULL;
3050 static MonoClass* generic_ienumerable_class = NULL;
3051 static MonoClass* generic_ienumerator_class = NULL;
3052 static MonoClass* generic_ireadonlylist_class = NULL;
3053 static MonoClass* generic_ireadonlycollection_class = NULL;
3054 MonoClass *valuetype_types[2] = { NULL, NULL };
3055 MonoClass **interfaces = NULL;
3056 int i, nifaces, interface_count, real_count, original_rank;
3058 gboolean internal_enumerator;
3059 gboolean eclass_is_valuetype;
3061 if (!mono_defaults.generic_ilist_class) {
3065 internal_enumerator = FALSE;
3066 eclass_is_valuetype = FALSE;
3067 original_rank = eclass->rank;
3068 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3069 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3071 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3073 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3074 original_rank = eclass->rank;
3076 eclass = eclass->element_class;
3077 internal_enumerator = TRUE;
3078 *is_enumerator = TRUE;
3086 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3087 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3089 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3091 if (!generic_icollection_class) {
3092 generic_icollection_class = mono_class_load_from_name (mono_defaults.corlib,
3093 "System.Collections.Generic", "ICollection`1");
3094 generic_ienumerable_class = mono_class_load_from_name (mono_defaults.corlib,
3095 "System.Collections.Generic", "IEnumerable`1");
3096 generic_ienumerator_class = mono_class_load_from_name (mono_defaults.corlib,
3097 "System.Collections.Generic", "IEnumerator`1");
3098 generic_ireadonlylist_class = mono_class_load_from_name (mono_defaults.corlib,
3099 "System.Collections.Generic", "IReadOnlyList`1");
3100 generic_ireadonlycollection_class = mono_class_load_from_name (mono_defaults.corlib,
3101 "System.Collections.Generic", "IReadOnlyCollection`1");
3104 mono_class_init (eclass);
3107 * Arrays in 2.0 need to implement a number of generic interfaces
3108 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3109 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3110 * We collect the types needed to build the
3111 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3112 * the generic interfaces needed to implement.
3114 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3115 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3117 if (eclass->valuetype) {
3118 nifaces = generic_ireadonlylist_class ? 5 : 3;
3119 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3121 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3122 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3123 if (internal_enumerator) {
3125 if (valuetype_types [1])
3129 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3130 interfaces [0] = valuetype_types [0];
3131 if (valuetype_types [1])
3132 interfaces [nifaces] = valuetype_types [1];
3134 eclass_is_valuetype = TRUE;
3137 int idepth = eclass->idepth;
3138 if (!internal_enumerator)
3140 nifaces = generic_ireadonlylist_class ? 2 : 3;
3142 // FIXME: This doesn't seem to work/required for generic params
3143 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3144 mono_class_setup_interface_offsets (eclass);
3146 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3147 /* we add object for interfaces and the supertypes for the other
3148 * types. The last of the supertypes is the element class itself which we
3149 * already created the explicit interfaces for (so we include it for IEnumerator
3150 * and exclude it for arrays).
3152 if (MONO_CLASS_IS_INTERFACE (eclass))
3155 interface_count += idepth;
3156 if (eclass->rank && eclass->element_class->valuetype) {
3157 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3158 if (valuetype_types [1])
3161 /* IList, ICollection, IEnumerable, IReadOnlyList */
3162 interface_count *= nifaces;
3163 real_count = interface_count;
3164 if (internal_enumerator) {
3165 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3166 if (valuetype_types [1])
3169 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3170 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3171 interfaces [0] = mono_defaults.object_class;
3175 for (i = 0; i < idepth; i++) {
3176 mono_class_init (eclass->supertypes [i]);
3177 interfaces [j] = eclass->supertypes [i];
3181 if (all_interfaces) {
3182 for (i = 0; i < eclass->interface_offsets_count; i++) {
3183 interfaces [j] = eclass->interfaces_packed [i];
3187 for (i = 0; i < eclass->interface_count; i++) {
3188 interfaces [j] = eclass->interfaces [i];
3192 if (valuetype_types [1]) {
3193 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3198 /* instantiate the generic interfaces */
3199 for (i = 0; i < interface_count; i += nifaces) {
3200 MonoClass *iface = interfaces [i];
3202 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3203 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3205 if (eclass->valuetype) {
3206 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3207 if (generic_ireadonlylist_class) {
3208 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3209 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3212 if (!generic_ireadonlylist_class)
3213 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3216 if (internal_enumerator) {
3218 /* instantiate IEnumerator<iface> */
3219 for (i = 0; i < interface_count; i++) {
3220 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3222 j = interface_count;
3223 if (!eclass_is_valuetype) {
3224 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3225 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3228 for (i = 0; i < eclass->idepth; i++) {
3229 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3233 for (i = 0; i < eclass->interface_offsets_count; i++) {
3234 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3238 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3240 if (valuetype_types [1])
3241 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3245 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3246 for (i = 0; i < real_count; ++i) {
3247 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3248 g_print ("%s implements %s\n", type_name, name);
3259 find_array_interface (MonoClass *klass, const char *name)
3262 for (i = 0; i < klass->interface_count; ++i) {
3263 if (strcmp (klass->interfaces [i]->name, name) == 0)
3270 * Return the number of virtual methods.
3271 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3272 * Return -1 on failure.
3273 * FIXME It would be nice if this information could be cached somewhere.
3276 count_virtual_methods (MonoClass *klass)
3280 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3282 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3283 mono_class_setup_methods (klass);
3284 if (mono_class_has_failure (klass))
3287 for (i = 0; i < klass->method.count; ++i) {
3288 flags = klass->methods [i]->flags;
3289 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3293 for (i = 0; i < klass->method.count; ++i) {
3294 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3296 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3304 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3312 m = (l + num_ifaces) / 2;
3313 if (interfaces_full [m] == ic)
3315 if (l == num_ifaces)
3317 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3326 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3328 int i = find_interface (num_ifaces, interfaces_full, ic);
3330 return interface_offsets_full [i];
3335 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3337 int i = find_interface (num_ifaces, interfaces_full, ic);
3341 interface_offsets_full [i] = offset;
3344 for (i = 0; i < num_ifaces; ++i) {
3345 if (interfaces_full [i]) {
3347 if (interfaces_full [i]->interface_id < ic->interface_id)
3350 while (end < num_ifaces && interfaces_full [end]) end++;
3351 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3352 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3354 interfaces_full [i] = ic;
3355 interface_offsets_full [i] = offset;
3361 #ifdef COMPRESSED_INTERFACE_BITMAP
3364 * Compressed interface bitmap design.
3366 * Interface bitmaps take a large amount of memory, because their size is
3367 * linear with the maximum interface id assigned in the process (each interface
3368 * is assigned a unique id as it is loaded). The number of interface classes
3369 * is high because of the many implicit interfaces implemented by arrays (we'll
3370 * need to lazy-load them in the future).
3371 * Most classes implement a very small number of interfaces, so the bitmap is
3372 * sparse. This bitmap needs to be checked by interface casts, so access to the
3373 * needed bit must be fast and doable with few jit instructions.
3375 * The current compression format is as follows:
3376 * *) it is a sequence of one or more two-byte elements
3377 * *) the first byte in the element is the count of empty bitmap bytes
3378 * at the current bitmap position
3379 * *) the second byte in the element is an actual bitmap byte at the current
3382 * As an example, the following compressed bitmap bytes:
3383 * 0x07 0x01 0x00 0x7
3384 * correspond to the following bitmap:
3385 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3387 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3388 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3389 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3393 * mono_compress_bitmap:
3394 * @dest: destination buffer
3395 * @bitmap: bitmap buffer
3396 * @size: size of @bitmap in bytes
3398 * This is a mono internal function.
3399 * The @bitmap data is compressed into a format that is small but
3400 * still searchable in few instructions by the JIT and runtime.
3401 * The compressed data is stored in the buffer pointed to by the
3402 * @dest array. Passing a #NULL value for @dest allows to just compute
3403 * the size of the buffer.
3404 * This compression algorithm assumes the bits set in the bitmap are
3405 * few and far between, like in interface bitmaps.
3406 * Returns: The size of the compressed bitmap in bytes.
3409 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3413 const uint8_t *end = bitmap + size;
3414 while (bitmap < end) {
3415 if (*bitmap || numz == 255) {
3439 * mono_class_interface_match:
3440 * @bitmap: a compressed bitmap buffer
3441 * @id: the index to check in the bitmap
3443 * This is a mono internal function.
3444 * Checks if a bit is set in a compressed interface bitmap. @id must
3445 * be already checked for being smaller than the maximum id encoded in the
3448 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3452 mono_class_interface_match (const uint8_t *bitmap, int id)
3455 id -= bitmap [0] * 8;
3459 return bitmap [1] & (1 << id);
3468 * LOCKING: this is supposed to be called with the loader lock held.
3469 * Return -1 on failure and set exception_type
3472 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3476 int i, j, max_iid, num_ifaces;
3477 MonoClass **interfaces_full = NULL;
3478 int *interface_offsets_full = NULL;
3480 GPtrArray **ifaces_array = NULL;
3481 int interface_offsets_count;
3482 MonoClass **array_interfaces = NULL;
3483 int num_array_interfaces;
3484 int is_enumerator = FALSE;
3486 mono_class_setup_supertypes (klass);
3488 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3489 * implicit interfaces have the property that they are assigned the same slot in the
3490 * vtables for compatible interfaces
3492 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3494 /* compute maximum number of slots and maximum interface id */
3496 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3497 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3498 for (j = 0; j < klass->idepth; j++) {
3499 k = klass->supertypes [j];
3500 num_ifaces += k->interface_count;
3501 for (i = 0; i < k->interface_count; i++) {
3502 ic = k->interfaces [i];
3505 mono_class_init (ic);
3507 if (max_iid < ic->interface_id)
3508 max_iid = ic->interface_id;
3510 ifaces = mono_class_get_implemented_interfaces (k, &error);
3511 if (!mono_error_ok (&error)) {
3512 char *name = mono_type_get_full_name (k);
3513 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3515 mono_error_cleanup (&error);
3520 num_ifaces += ifaces->len;
3521 for (i = 0; i < ifaces->len; ++i) {
3522 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3523 if (max_iid < ic->interface_id)
3524 max_iid = ic->interface_id;
3526 ifaces_array [j] = ifaces;
3530 for (i = 0; i < num_array_interfaces; ++i) {
3531 ic = array_interfaces [i];
3532 mono_class_init (ic);
3533 if (max_iid < ic->interface_id)
3534 max_iid = ic->interface_id;
3537 if (MONO_CLASS_IS_INTERFACE (klass)) {
3539 if (max_iid < klass->interface_id)
3540 max_iid = klass->interface_id;
3542 klass->max_interface_id = max_iid;
3543 /* compute vtable offset for interfaces */
3544 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3545 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3547 for (i = 0; i < num_ifaces; i++) {
3548 interface_offsets_full [i] = -1;
3551 /* skip the current class */
3552 for (j = 0; j < klass->idepth - 1; j++) {
3553 k = klass->supertypes [j];
3554 ifaces = ifaces_array [j];
3557 for (i = 0; i < ifaces->len; ++i) {
3559 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3561 /*Force the sharing of interface offsets between parent and subtypes.*/
3562 io = mono_class_interface_offset (k, ic);
3564 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3569 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3570 ifaces = ifaces_array [klass->idepth - 1];
3572 for (i = 0; i < ifaces->len; ++i) {
3574 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3575 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3577 count = count_virtual_methods (ic);
3579 char *name = mono_type_get_full_name (ic);
3580 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3589 if (MONO_CLASS_IS_INTERFACE (klass))
3590 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3592 if (num_array_interfaces) {
3593 if (is_enumerator) {
3594 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3595 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3596 g_assert (ienumerator_offset >= 0);
3597 for (i = 0; i < num_array_interfaces; ++i) {
3598 ic = array_interfaces [i];
3599 if (strcmp (ic->name, "IEnumerator`1") == 0)
3600 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3602 g_assert_not_reached ();
3603 /*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);*/
3606 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3607 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3608 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3609 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3610 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3611 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3612 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3613 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3614 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3615 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3616 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3617 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3618 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3619 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3620 for (i = 0; i < num_array_interfaces; ++i) {
3622 ic = array_interfaces [i];
3623 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3624 offset = ilist_offset;
3625 else if (strcmp (ic->name, "ICollection`1") == 0)
3626 offset = icollection_offset;
3627 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3628 offset = ienumerable_offset;
3629 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3630 offset = ireadonlylist_offset;
3631 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3632 offset = ireadonlycollection_offset;
3634 g_assert_not_reached ();
3635 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3636 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3641 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3642 if (interface_offsets_full [i] != -1) {
3643 interface_offsets_count ++;
3648 * We might get called multiple times:
3649 * - mono_class_init ()
3650 * - mono_class_setup_vtable ().
3651 * - mono_class_setup_interface_offsets ().
3652 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3653 * means we have to overwrite those when called from other places (#4440).
3655 if (klass->interfaces_packed) {
3657 g_assert (klass->interface_offsets_count == interface_offsets_count);
3661 klass->interface_offsets_count = interface_offsets_count;
3662 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3663 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3664 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3665 #ifdef COMPRESSED_INTERFACE_BITMAP
3666 bitmap = g_malloc0 (bsize);
3668 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3670 for (i = 0; i < interface_offsets_count; i++) {
3671 int id = interfaces_full [i]->interface_id;
3672 bitmap [id >> 3] |= (1 << (id & 7));
3673 klass->interfaces_packed [i] = interfaces_full [i];
3674 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3675 /*if (num_array_interfaces)
3676 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]);*/
3678 #ifdef COMPRESSED_INTERFACE_BITMAP
3679 i = mono_compress_bitmap (NULL, bitmap, bsize);
3680 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3681 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3684 klass->interface_bitmap = bitmap;
3689 g_free (interfaces_full);
3690 g_free (interface_offsets_full);
3691 g_free (array_interfaces);
3692 for (i = 0; i < klass->idepth; i++) {
3693 ifaces = ifaces_array [i];
3695 g_ptr_array_free (ifaces, TRUE);
3697 g_free (ifaces_array);
3699 //printf ("JUST DONE: ");
3700 //print_implemented_interfaces (klass);
3706 * Setup interface offsets for interfaces.
3708 * - klass->max_interface_id
3709 * - klass->interface_offsets_count
3710 * - klass->interfaces_packed
3711 * - klass->interface_offsets_packed
3712 * - klass->interface_bitmap
3714 * This function can fail @class.
3717 mono_class_setup_interface_offsets (MonoClass *klass)
3719 mono_loader_lock ();
3721 setup_interface_offsets (klass, 0, FALSE);
3723 mono_loader_unlock ();
3726 /*Checks if @klass has @parent as one of it's parents type gtd
3730 * Bar<T> : Foo<Bar<Bar<T>>>
3734 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3736 klass = mono_class_get_generic_type_definition (klass);
3737 parent = mono_class_get_generic_type_definition (parent);
3738 mono_class_setup_supertypes (klass);
3739 mono_class_setup_supertypes (parent);
3741 return klass->idepth >= parent->idepth &&
3742 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3746 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3748 MonoGenericInst *ginst;
3750 if (!klass->generic_class) {
3751 mono_class_setup_vtable_full (klass, in_setup);
3752 return !mono_class_has_failure (klass);
3755 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3756 if (mono_class_has_failure (klass->generic_class->container_class)) {
3757 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3761 ginst = klass->generic_class->context.class_inst;
3762 for (i = 0; i < ginst->type_argc; ++i) {
3764 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3766 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3767 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3768 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3770 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3771 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3779 * mono_class_setup_vtable:
3781 * Creates the generic vtable of CLASS.
3782 * Initializes the following fields in MonoClass:
3785 * Plus all the fields initialized by setup_interface_offsets ().
3786 * If there is an error during vtable construction, klass->exception_type is set.
3788 * LOCKING: Acquires the loader lock.
3791 mono_class_setup_vtable (MonoClass *klass)
3793 mono_class_setup_vtable_full (klass, NULL);
3797 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3800 MonoMethod **overrides;
3801 MonoGenericContext *context;
3809 if (MONO_CLASS_IS_INTERFACE (klass)) {
3810 /* This sets method->slot for all methods if this is an interface */
3811 mono_class_setup_methods (klass);
3815 if (mono_class_has_failure (klass))
3818 if (g_list_find (in_setup, klass))
3821 mono_loader_lock ();
3823 if (klass->vtable) {
3824 mono_loader_unlock ();
3828 mono_stats.generic_vtable_count ++;
3829 in_setup = g_list_prepend (in_setup, klass);
3831 if (klass->generic_class) {
3832 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3833 mono_loader_unlock ();
3834 g_list_remove (in_setup, klass);
3838 context = mono_class_get_context (klass);
3839 type_token = klass->generic_class->container_class->type_token;
3841 context = (MonoGenericContext *) klass->generic_container;
3842 type_token = klass->type_token;
3845 if (image_is_dynamic (klass->image)) {
3846 /* Generic instances can have zero method overrides without causing any harm.
3847 * This is true since we don't do layout all over again for them, we simply inflate
3848 * the layout of the parent.
3850 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3851 if (!is_ok (&error)) {
3852 mono_loader_unlock ();
3853 g_list_remove (in_setup, klass);
3854 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf("Could not load list of method overrides due to %s", mono_error_get_message (&error)));
3855 mono_error_cleanup (&error);
3859 /* The following call fails if there are missing methods in the type */
3860 /* FIXME it's probably a good idea to avoid this for generic instances. */
3861 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3865 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3867 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3871 mono_loader_unlock ();
3872 g_list_remove (in_setup, klass);
3877 #define DEBUG_INTERFACE_VTABLE_CODE 0
3878 #define TRACE_INTERFACE_VTABLE_CODE 0
3879 #define VERIFY_INTERFACE_VTABLE_CODE 0
3880 #define VTABLE_SELECTOR (1)
3882 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3883 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3884 if (!(VTABLE_SELECTOR)) break; \
3888 #define DEBUG_INTERFACE_VTABLE(stmt)
3891 #if TRACE_INTERFACE_VTABLE_CODE
3892 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3893 if (!(VTABLE_SELECTOR)) break; \
3897 #define TRACE_INTERFACE_VTABLE(stmt)
3900 #if VERIFY_INTERFACE_VTABLE_CODE
3901 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3902 if (!(VTABLE_SELECTOR)) break; \
3906 #define VERIFY_INTERFACE_VTABLE(stmt)
3910 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3912 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3916 GString *res = g_string_new ("");
3918 g_string_append_c (res, '(');
3919 for (i = 0; i < sig->param_count; ++i) {
3921 g_string_append_c (res, ',');
3922 mono_type_get_desc (res, sig->params [i], include_namespace);
3924 g_string_append (res, ")=>");
3925 if (sig->ret != NULL) {
3926 mono_type_get_desc (res, sig->ret, include_namespace);
3928 g_string_append (res, "NULL");
3931 g_string_free (res, FALSE);
3935 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3936 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3937 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3938 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3946 is_wcf_hack_disabled (void)
3948 static gboolean disabled;
3949 static gboolean inited = FALSE;
3951 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3958 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3960 MonoMethodSignature *cmsig, *imsig;
3961 if (strcmp (im->name, cm->name) == 0) {
3962 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3963 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3966 if (! slot_is_empty) {
3967 if (require_newslot) {
3968 if (! interface_is_explicitly_implemented_by_class) {
3969 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3972 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3973 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3977 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3980 cmsig = mono_method_signature (cm);
3981 imsig = mono_method_signature (im);
3982 if (!cmsig || !imsig) {
3983 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3987 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3988 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3989 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3990 TRACE_INTERFACE_VTABLE (printf ("]"));
3993 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3994 if (mono_security_core_clr_enabled ())
3995 mono_security_core_clr_check_override (klass, cm, im);
3997 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3998 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3999 char *body_name = mono_method_full_name (cm, TRUE);
4000 char *decl_name = mono_method_full_name (im, TRUE);
4001 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4009 MonoClass *ic = im->klass;
4010 const char *ic_name_space = ic->name_space;
4011 const char *ic_name = ic->name;
4014 if (! require_newslot) {
4015 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4018 if (cm->klass->rank == 0) {
4019 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4022 cmsig = mono_method_signature (cm);
4023 imsig = mono_method_signature (im);
4024 if (!cmsig || !imsig) {
4025 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4029 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4030 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4031 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4032 TRACE_INTERFACE_VTABLE (printf ("]"));
4035 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4036 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4039 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4040 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4043 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))) {
4044 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4048 subname = strstr (cm->name, ic_name_space);
4049 if (subname != cm->name) {
4050 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4053 subname += strlen (ic_name_space);
4054 if (subname [0] != '.') {
4055 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4059 if (strstr (subname, ic_name) != subname) {
4060 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4063 subname += strlen (ic_name);
4064 if (subname [0] != '.') {
4065 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4069 if (strcmp (subname, im->name) != 0) {
4070 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4074 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4075 if (mono_security_core_clr_enabled ())
4076 mono_security_core_clr_check_override (klass, cm, im);
4078 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4079 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4080 char *body_name = mono_method_full_name (cm, TRUE);
4081 char *decl_name = mono_method_full_name (im, TRUE);
4082 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4092 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4094 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4095 MonoMethod *method = key;
4096 MonoMethod *override = value;
4097 MonoClass *method_class = mono_method_get_class (method);
4098 MonoClass *override_class = mono_method_get_class (override);
4100 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4101 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4102 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4105 print_overrides (GHashTable *override_map, const char *message) {
4107 printf ("Override map \"%s\" START:\n", message);
4108 g_hash_table_foreach (override_map, foreach_override, NULL);
4109 printf ("Override map \"%s\" END.\n", message);
4111 printf ("Override map \"%s\" EMPTY.\n", message);
4115 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4116 char *full_name = mono_type_full_name (&klass->byval_arg);
4120 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4122 if (print_interfaces) {
4123 print_implemented_interfaces (klass);
4124 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4127 if (klass->parent) {
4128 parent_size = klass->parent->vtable_size;
4132 for (i = 0; i < size; ++i) {
4133 MonoMethod *cm = vtable [i];
4134 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4135 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4137 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4145 #if VERIFY_INTERFACE_VTABLE_CODE
4147 mono_method_try_get_vtable_index (MonoMethod *method)
4149 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4150 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4151 if (imethod->declaring->is_generic)
4152 return imethod->declaring->slot;
4154 return method->slot;
4158 mono_class_verify_vtable (MonoClass *klass)
4161 char *full_name = mono_type_full_name (&klass->byval_arg);
4163 printf ("*** Verifying VTable of class '%s' \n", full_name);
4167 if (!klass->methods)
4170 for (i = 0; i < klass->method.count; ++i) {
4171 MonoMethod *cm = klass->methods [i];
4174 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4178 full_name = mono_method_full_name (cm, TRUE);
4180 slot = mono_method_try_get_vtable_index (cm);
4182 if (slot >= klass->vtable_size) {
4183 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4187 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4188 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4189 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4190 g_free (other_name);
4193 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4200 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4202 char *method_signature;
4205 for (index = 0; index < onum; ++index) {
4206 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4207 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4209 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4210 type_name = mono_type_full_name (&klass->byval_arg);
4211 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4212 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4213 g_free (method_signature);
4215 mono_class_setup_methods (klass);
4216 if (mono_class_has_failure (klass)) {
4217 char *name = mono_type_get_full_name (klass);
4218 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4222 for (index = 0; index < klass->method.count; ++index) {
4223 MonoMethod *cm = klass->methods [index];
4224 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4226 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4227 g_free (method_signature);
4232 mono_method_get_method_definition (MonoMethod *method)
4234 while (method->is_inflated)
4235 method = ((MonoMethodInflated*)method)->declaring;
4240 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4244 for (i = 0; i < onum; ++i) {
4245 MonoMethod *decl = overrides [i * 2];
4246 MonoMethod *body = overrides [i * 2 + 1];
4248 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4249 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4253 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4254 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4255 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4257 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4261 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4262 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4263 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4265 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4269 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4270 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type"));
4274 body = mono_method_get_method_definition (body);
4275 decl = mono_method_get_method_definition (decl);
4277 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4278 char *body_name = mono_method_full_name (body, TRUE);
4279 char *decl_name = mono_method_full_name (decl, TRUE);
4280 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4290 mono_class_need_stelemref_method (MonoClass *klass)
4292 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4296 * LOCKING: this is supposed to be called with the loader lock held.
4299 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4303 MonoMethod **vtable;
4304 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4305 GPtrArray *ifaces = NULL;
4306 GHashTable *override_map = NULL;
4308 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4309 int first_non_interface_slot;
4311 GSList *virt_methods = NULL, *l;
4312 int stelemref_slot = 0;
4317 if (overrides && !verify_class_overrides (klass, overrides, onum))
4320 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4321 if (!mono_error_ok (&error)) {
4322 char *name = mono_type_get_full_name (klass);
4323 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4325 mono_error_cleanup (&error);
4327 } else if (ifaces) {
4328 for (i = 0; i < ifaces->len; i++) {
4329 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4330 max_vtsize += ic->method.count;
4332 g_ptr_array_free (ifaces, TRUE);
4336 if (klass->parent) {
4337 mono_class_init (klass->parent);
4338 mono_class_setup_vtable_full (klass->parent, in_setup);
4340 if (mono_class_has_failure (klass->parent)) {
4341 char *name = mono_type_get_full_name (klass->parent);
4342 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4347 max_vtsize += klass->parent->vtable_size;
4348 cur_slot = klass->parent->vtable_size;
4351 max_vtsize += klass->method.count;
4353 /*Array have a slot for stelemref*/
4354 if (mono_class_need_stelemref_method (klass)) {
4355 stelemref_slot = cur_slot;
4360 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4361 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4363 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4365 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4366 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4369 max_iid = klass->max_interface_id;
4370 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4372 /* Optimized version for generic instances */
4373 if (klass->generic_class) {
4375 MonoClass *gklass = klass->generic_class->container_class;
4378 mono_class_setup_vtable_full (gklass, in_setup);
4379 if (mono_class_has_failure (gklass)) {
4380 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4384 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4385 klass->vtable_size = gklass->vtable_size;
4386 for (i = 0; i < gklass->vtable_size; ++i)
4387 if (gklass->vtable [i]) {
4388 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4389 if (!mono_error_ok (&error)) {
4390 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4391 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4393 mono_error_cleanup (&error);
4397 tmp [i]->slot = gklass->vtable [i]->slot;
4399 mono_memory_barrier ();
4400 klass->vtable = tmp;
4402 /* Have to set method->slot for abstract virtual methods */
4403 if (klass->methods && gklass->methods) {
4404 for (i = 0; i < klass->method.count; ++i)
4405 if (klass->methods [i]->slot == -1)
4406 klass->methods [i]->slot = gklass->methods [i]->slot;
4412 if (klass->parent && klass->parent->vtable_size) {
4413 MonoClass *parent = klass->parent;
4416 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4418 // Also inherit parent interface vtables, just as a starting point.
4419 // This is needed otherwise bug-77127.exe fails when the property methods
4420 // have different names in the iterface and the class, because for child
4421 // classes the ".override" information is not used anymore.
4422 for (i = 0; i < parent->interface_offsets_count; i++) {
4423 MonoClass *parent_interface = parent->interfaces_packed [i];
4424 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4425 /*FIXME this is now dead code as this condition will never hold true.
4426 Since interface offsets are inherited then the offset of an interface implemented
4427 by a parent will never be the out of it's vtable boundary.
4429 if (interface_offset >= parent->vtable_size) {
4430 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4433 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4434 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4435 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4436 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4437 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4438 parent_interface_offset + j, parent_interface_offset, j,
4439 interface_offset + j, interface_offset, j));
4446 /*Array have a slot for stelemref*/
4447 if (mono_class_need_stelemref_method (klass)) {
4448 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4450 method->slot = stelemref_slot;
4452 g_assert (method->slot == stelemref_slot);
4454 vtable [stelemref_slot] = method;
4457 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4458 /* override interface methods */
4459 for (i = 0; i < onum; i++) {
4460 MonoMethod *decl = overrides [i*2];
4461 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4463 dslot = mono_method_get_vtable_slot (decl);
4465 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4469 dslot += mono_class_interface_offset (klass, decl->klass);
4470 vtable [dslot] = overrides [i*2 + 1];
4471 vtable [dslot]->slot = dslot;
4473 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4475 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4477 if (mono_security_core_clr_enabled ())
4478 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4481 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4482 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4485 * Create a list of virtual methods to avoid calling
4486 * mono_class_get_virtual_methods () which is slow because of the metadata
4490 gpointer iter = NULL;
4493 virt_methods = NULL;
4494 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4495 virt_methods = g_slist_prepend (virt_methods, cm);
4497 if (mono_class_has_failure (klass))
4501 // Loop on all implemented interfaces...
4502 for (i = 0; i < klass->interface_offsets_count; i++) {
4503 MonoClass *parent = klass->parent;
4505 gboolean interface_is_explicitly_implemented_by_class;
4508 ic = klass->interfaces_packed [i];
4509 ic_offset = mono_class_interface_offset (klass, ic);
4511 mono_class_setup_methods (ic);
4512 if (mono_class_has_failure (ic))
4515 // Check if this interface is explicitly implemented (instead of just inherited)
4516 if (parent != NULL) {
4517 int implemented_interfaces_index;
4518 interface_is_explicitly_implemented_by_class = FALSE;
4519 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4520 if (ic == klass->interfaces [implemented_interfaces_index]) {
4521 interface_is_explicitly_implemented_by_class = TRUE;
4526 interface_is_explicitly_implemented_by_class = TRUE;
4529 // Loop on all interface methods...
4530 for (im_index = 0; im_index < ic->method.count; im_index++) {
4531 MonoMethod *im = ic->methods [im_index];
4532 int im_slot = ic_offset + im->slot;
4533 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4535 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4538 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4540 // If there is an explicit implementation, just use it right away,
4541 // otherwise look for a matching method
4542 if (override_im == NULL) {
4546 // First look for a suitable method among the class methods
4547 for (l = virt_methods; l; l = l->next) {
4548 cm = (MonoMethod *)l->data;
4549 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)));
4550 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4551 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4552 vtable [im_slot] = cm;
4553 /* Why do we need this? */
4558 TRACE_INTERFACE_VTABLE (printf ("\n"));
4559 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4563 // If the slot is still empty, look in all the inherited virtual methods...
4564 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4565 MonoClass *parent = klass->parent;
4566 // Reverse order, so that last added methods are preferred
4567 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4568 MonoMethod *cm = parent->vtable [cm_index];
4570 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));
4571 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4572 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4573 vtable [im_slot] = cm;
4574 /* Why do we need this? */
4580 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4582 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4586 g_assert (vtable [im_slot] == override_im);
4591 // If the class is not abstract, check that all its interface slots are full.
4592 // The check is done here and not directly at the end of the loop above because
4593 // it can happen (for injected generic array interfaces) that the same slot is
4594 // processed multiple times (those interfaces have overlapping slots), and it
4595 // will not always be the first pass the one that fills the slot.
4596 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4597 for (i = 0; i < klass->interface_offsets_count; i++) {
4601 ic = klass->interfaces_packed [i];
4602 ic_offset = mono_class_interface_offset (klass, ic);
4604 for (im_index = 0; im_index < ic->method.count; im_index++) {
4605 MonoMethod *im = ic->methods [im_index];
4606 int im_slot = ic_offset + im->slot;
4608 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4611 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4612 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4613 if (vtable [im_slot] == NULL) {
4614 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4621 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4622 for (l = virt_methods; l; l = l->next) {
4623 cm = (MonoMethod *)l->data;
4625 * If the method is REUSE_SLOT, we must check in the
4626 * base class for a method to override.
4628 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4630 for (k = klass->parent; k ; k = k->parent) {
4635 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4636 MonoMethodSignature *cmsig, *m1sig;
4638 cmsig = mono_method_signature (cm);
4639 m1sig = mono_method_signature (m1);
4641 if (!cmsig || !m1sig) {
4642 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4646 if (!strcmp(cm->name, m1->name) &&
4647 mono_metadata_signature_equal (cmsig, m1sig)) {
4649 if (mono_security_core_clr_enabled ())
4650 mono_security_core_clr_check_override (klass, cm, m1);
4652 slot = mono_method_get_vtable_slot (m1);
4656 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4657 char *body_name = mono_method_full_name (cm, TRUE);
4658 char *decl_name = mono_method_full_name (m1, TRUE);
4659 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4665 g_assert (cm->slot < max_vtsize);
4667 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4668 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4669 mono_method_full_name (m1, 1), m1,
4670 mono_method_full_name (cm, 1), cm));
4671 g_hash_table_insert (override_map, m1, cm);
4675 if (mono_class_has_failure (k))
4685 /*Non final newslot methods must be given a non-interface vtable slot*/
4686 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4690 cm->slot = cur_slot++;
4692 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4693 vtable [cm->slot] = cm;
4696 /* override non interface methods */
4697 for (i = 0; i < onum; i++) {
4698 MonoMethod *decl = overrides [i*2];
4699 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4700 g_assert (decl->slot != -1);
4701 vtable [decl->slot] = overrides [i*2 + 1];
4702 overrides [i * 2 + 1]->slot = decl->slot;
4704 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4705 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4706 mono_method_full_name (decl, 1), decl,
4707 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4708 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4710 if (mono_security_core_clr_enabled ())
4711 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4716 * If a method occupies more than one place in the vtable, and it is
4717 * overriden, then change the other occurances too.
4722 for (i = 0; i < max_vtsize; ++i)
4724 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4726 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4731 g_hash_table_destroy (override_map);
4732 override_map = NULL;
4735 g_slist_free (virt_methods);
4736 virt_methods = NULL;
4738 /* Ensure that all vtable slots are filled with concrete instance methods */
4739 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4740 for (i = 0; i < cur_slot; ++i) {
4741 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4742 char *type_name = mono_type_get_full_name (klass);
4743 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4744 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4746 g_free (method_name);
4752 if (klass->generic_class) {
4753 MonoClass *gklass = klass->generic_class->container_class;
4755 mono_class_init (gklass);
4757 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4759 /* Check that the vtable_size value computed in mono_class_init () is correct */
4760 if (klass->vtable_size)
4761 g_assert (cur_slot == klass->vtable_size);
4762 klass->vtable_size = cur_slot;
4765 /* Try to share the vtable with our parent. */
4766 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4767 mono_memory_barrier ();
4768 klass->vtable = klass->parent->vtable;
4770 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4771 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4772 mono_memory_barrier ();
4773 klass->vtable = tmp;
4776 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4777 if (mono_print_vtable) {
4780 print_implemented_interfaces (klass);
4782 for (i = 0; i <= max_iid; i++)
4783 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4786 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4787 klass->vtable_size, icount);
4789 for (i = 0; i < cur_slot; ++i) {
4794 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4795 mono_method_full_name (cm, TRUE));
4801 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4802 klass->name, max_iid);
4804 for (i = 0; i < klass->interface_count; i++) {
4805 ic = klass->interfaces [i];
4806 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4807 mono_class_interface_offset (klass, ic),
4808 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4811 for (k = klass->parent; k ; k = k->parent) {
4812 for (i = 0; i < k->interface_count; i++) {
4813 ic = k->interfaces [i];
4814 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4815 mono_class_interface_offset (klass, ic),
4816 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4822 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4827 char *name = mono_type_get_full_name (klass);
4828 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4831 g_hash_table_destroy (override_map);
4833 g_slist_free (virt_methods);
4838 * mono_method_get_vtable_slot:
4840 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4841 * LOCKING: Acquires the loader lock.
4843 * FIXME Use proper MonoError machinery here.
4846 mono_method_get_vtable_slot (MonoMethod *method)
4848 if (method->slot == -1) {
4849 mono_class_setup_vtable (method->klass);
4850 if (mono_class_has_failure (method->klass))
4852 if (method->slot == -1) {
4856 if (!method->klass->generic_class) {
4857 g_assert (method->is_inflated);
4858 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4861 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4862 g_assert (method->klass->generic_class);
4863 gklass = method->klass->generic_class->container_class;
4864 mono_class_setup_methods (method->klass);
4865 g_assert (method->klass->methods);
4866 for (i = 0; i < method->klass->method.count; ++i) {
4867 if (method->klass->methods [i] == method)
4870 g_assert (i < method->klass->method.count);
4871 g_assert (gklass->methods);
4872 method->slot = gklass->methods [i]->slot;
4874 g_assert (method->slot != -1);
4876 return method->slot;
4880 * mono_method_get_vtable_index:
4883 * Returns the index into the runtime vtable to access the method or,
4884 * in the case of a virtual generic method, the virtual generic method
4885 * thunk. Returns -1 on failure.
4887 * FIXME Use proper MonoError machinery here.
4890 mono_method_get_vtable_index (MonoMethod *method)
4892 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4893 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4894 if (imethod->declaring->is_generic)
4895 return mono_method_get_vtable_slot (imethod->declaring);
4897 return mono_method_get_vtable_slot (method);
4900 static MonoMethod *default_ghc = NULL;
4901 static MonoMethod *default_finalize = NULL;
4902 static int finalize_slot = -1;
4903 static int ghc_slot = -1;
4906 initialize_object_slots (MonoClass *klass)
4911 if (klass == mono_defaults.object_class) {
4912 mono_class_setup_vtable (klass);
4913 for (i = 0; i < klass->vtable_size; ++i) {
4914 MonoMethod *cm = klass->vtable [i];
4916 if (!strcmp (cm->name, "GetHashCode"))
4918 else if (!strcmp (cm->name, "Finalize"))
4922 g_assert (ghc_slot > 0);
4923 default_ghc = klass->vtable [ghc_slot];
4925 g_assert (finalize_slot > 0);
4926 default_finalize = klass->vtable [finalize_slot];
4931 MonoMethod *array_method;
4933 } GenericArrayMethodInfo;
4935 static int generic_array_method_num = 0;
4936 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4939 generic_array_methods (MonoClass *klass)
4941 int i, count_generic = 0;
4942 GList *list = NULL, *tmp;
4943 if (generic_array_method_num)
4944 return generic_array_method_num;
4945 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4946 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4947 for (i = 0; i < klass->parent->method.count; i++) {
4948 MonoMethod *m = klass->parent->methods [i];
4949 if (!strncmp (m->name, "InternalArray__", 15)) {
4951 list = g_list_prepend (list, m);
4954 list = g_list_reverse (list);
4955 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4957 for (tmp = list; tmp; tmp = tmp->next) {
4958 const char *mname, *iname;
4960 MonoMethod *m = (MonoMethod *)tmp->data;
4961 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4962 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4964 generic_array_method_info [i].array_method = m;
4965 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4966 iname = "System.Collections.Generic.ICollection`1.";
4967 mname = m->name + 27;
4968 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4969 iname = "System.Collections.Generic.IEnumerable`1.";
4970 mname = m->name + 27;
4971 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4972 iname = "System.Collections.Generic.IReadOnlyList`1.";
4973 mname = m->name + strlen (ireadonlylist_prefix);
4974 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4975 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4976 mname = m->name + strlen (ireadonlycollection_prefix);
4977 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4978 iname = "System.Collections.Generic.IList`1.";
4979 mname = m->name + 15;
4981 g_assert_not_reached ();
4984 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4985 strcpy (name, iname);
4986 strcpy (name + strlen (iname), mname);
4987 generic_array_method_info [i].name = name;
4990 /*g_print ("array generic methods: %d\n", count_generic);*/
4992 generic_array_method_num = count_generic;
4994 return generic_array_method_num;
4998 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5000 MonoGenericContext tmp_context;
5003 tmp_context.class_inst = NULL;
5004 tmp_context.method_inst = iface->generic_class->context.class_inst;
5005 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5007 for (i = 0; i < generic_array_method_num; i++) {
5009 MonoMethod *m = generic_array_method_info [i].array_method;
5010 MonoMethod *inflated;
5012 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5013 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5014 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5019 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5021 int null_length = strlen ("(null)");
5022 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5023 char *s = (char *)mono_image_alloc (image, len);
5026 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5027 g_assert (result == len - 1);
5034 * @class: the class to initialize
5036 * Compute the instance_size, class_size and other infos that cannot be
5037 * computed at mono_class_get() time. Also compute vtable_size if possible.
5038 * Returns TRUE on success or FALSE if there was a problem in loading
5039 * the type (incorrect assemblies, missing assemblies, methods, etc).
5041 * LOCKING: Acquires the loader lock.
5044 mono_class_init (MonoClass *klass)
5047 MonoCachedClassInfo cached_info;
5048 gboolean has_cached_info;
5052 /* Double-checking locking pattern */
5053 if (klass->inited || mono_class_has_failure (klass))
5054 return !mono_class_has_failure (klass);
5056 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5058 /* We do everything inside the lock to prevent races */
5059 mono_loader_lock ();
5061 if (klass->inited || mono_class_has_failure (klass)) {
5062 mono_loader_unlock ();
5063 /* Somebody might have gotten in before us */
5064 return !mono_class_has_failure (klass);
5067 if (klass->init_pending) {
5068 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5072 klass->init_pending = 1;
5074 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5075 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5080 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5081 MonoClass *element_class = klass->element_class;
5082 if (!element_class->inited)
5083 mono_class_init (element_class);
5084 if (mono_class_has_failure (element_class)) {
5085 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5090 mono_stats.initialized_class_count++;
5092 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5093 MonoClass *gklass = klass->generic_class->container_class;
5095 mono_stats.generic_class_count++;
5097 klass->method = gklass->method;
5098 klass->field = gklass->field;
5100 mono_class_init (gklass);
5101 // FIXME: Why is this needed ?
5102 if (!mono_class_has_failure (gklass))
5103 mono_class_setup_methods (gklass);
5104 if (mono_class_has_failure (gklass)) {
5105 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5109 if (MONO_CLASS_IS_INTERFACE (klass))
5110 klass->interface_id = mono_get_unique_iid (klass);
5113 if (klass->parent && !klass->parent->inited)
5114 mono_class_init (klass->parent);
5116 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5118 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5119 klass->nested_classes_inited = TRUE;
5122 * Computes the size used by the fields, and their locations
5124 if (has_cached_info) {
5125 klass->instance_size = cached_info.instance_size;
5126 klass->sizes.class_size = cached_info.class_size;
5127 klass->packing_size = cached_info.packing_size;
5128 klass->min_align = cached_info.min_align;
5129 klass->blittable = cached_info.blittable;
5130 klass->has_references = cached_info.has_references;
5131 klass->has_static_refs = cached_info.has_static_refs;
5132 klass->no_special_static_fields = cached_info.no_special_static_fields;
5135 if (!klass->size_inited){
5136 mono_class_setup_fields (klass);
5137 if (mono_class_has_failure (klass))
5141 /* Initialize arrays */
5143 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5145 if (klass->interface_count) {
5146 int count_generic = generic_array_methods (klass);
5147 klass->method.count += klass->interface_count * count_generic;
5151 mono_class_setup_supertypes (klass);
5154 initialize_object_slots (klass);
5157 * Initialize the rest of the data without creating a generic vtable if possible.
5158 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5159 * also avoid computing a generic vtable.
5161 if (has_cached_info) {
5163 klass->vtable_size = cached_info.vtable_size;
5164 klass->has_finalize = cached_info.has_finalize;
5165 klass->has_finalize_inited = TRUE;
5166 klass->ghcimpl = cached_info.ghcimpl;
5167 klass->has_cctor = cached_info.has_cctor;
5168 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5169 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5170 * The first slot if for array with.
5172 static int szarray_vtable_size[2] = { 0 };
5174 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5177 if (!szarray_vtable_size [slot]) {
5178 mono_class_setup_vtable (klass);
5179 szarray_vtable_size [slot] = klass->vtable_size;
5181 klass->vtable_size = szarray_vtable_size[slot];
5183 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5184 MonoClass *gklass = klass->generic_class->container_class;
5186 /* Generic instance case */
5187 klass->ghcimpl = gklass->ghcimpl;
5188 klass->has_cctor = gklass->has_cctor;
5190 mono_class_setup_vtable (gklass);
5191 if (mono_class_has_failure (gklass)) {
5192 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5196 klass->vtable_size = gklass->vtable_size;
5200 /* ghcimpl is not currently used
5202 if (klass->parent) {
5203 MonoMethod *cmethod = klass->vtable [ghc_slot];
5204 if (cmethod->is_inflated)
5205 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5206 if (cmethod == default_ghc) {
5212 /* C# doesn't allow interfaces to have cctors */
5213 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5214 MonoMethod *cmethod = NULL;
5216 if (klass->type_token && !image_is_dynamic(klass->image)) {
5217 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5218 /* The find_method function ignores the 'flags' argument */
5219 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5220 klass->has_cctor = 1;
5222 mono_class_setup_methods (klass);
5223 if (mono_class_has_failure (klass))
5226 for (i = 0; i < klass->method.count; ++i) {
5227 MonoMethod *method = klass->methods [i];
5228 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5229 (strcmp (".cctor", method->name) == 0)) {
5230 klass->has_cctor = 1;
5238 if (klass->parent) {
5239 int first_iface_slot;
5240 /* This will compute klass->parent->vtable_size for some classes */
5241 mono_class_init (klass->parent);
5242 if (mono_class_has_failure (klass->parent)) {
5243 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5246 if (!klass->parent->vtable_size) {
5247 /* FIXME: Get rid of this somehow */
5248 mono_class_setup_vtable (klass->parent);
5249 if (mono_class_has_failure (klass->parent)) {
5250 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5254 first_iface_slot = klass->parent->vtable_size;
5255 if (mono_class_need_stelemref_method (klass))
5257 setup_interface_offsets (klass, first_iface_slot, TRUE);
5259 setup_interface_offsets (klass, 0, TRUE);
5262 if (mono_security_core_clr_enabled ())
5263 mono_security_core_clr_check_inheritance (klass);
5265 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5266 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5271 /* Because of the double-checking locking pattern */
5272 mono_memory_barrier ();
5274 klass->init_pending = 0;
5276 mono_loader_unlock ();
5278 return !mono_class_has_failure (klass);
5282 * mono_class_has_finalizer:
5284 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5288 mono_class_has_finalizer (MonoClass *klass)
5290 gboolean has_finalize = FALSE;
5292 if (klass->has_finalize_inited)
5293 return klass->has_finalize;
5295 /* Interfaces and valuetypes are not supposed to have finalizers */
5296 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5297 MonoMethod *cmethod = NULL;
5299 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5300 } else if (klass->generic_class) {
5301 MonoClass *gklass = klass->generic_class->container_class;
5303 has_finalize = mono_class_has_finalizer (gklass);
5304 } else if (klass->parent && klass->parent->has_finalize) {
5305 has_finalize = TRUE;
5307 if (klass->parent) {
5309 * Can't search in metadata for a method named Finalize, because that
5310 * ignores overrides.
5312 mono_class_setup_vtable (klass);
5313 if (mono_class_has_failure (klass))
5316 cmethod = klass->vtable [finalize_slot];
5320 g_assert (klass->vtable_size > finalize_slot);
5322 if (klass->parent) {
5323 if (cmethod->is_inflated)
5324 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5325 if (cmethod != default_finalize)
5326 has_finalize = TRUE;
5332 mono_image_lock (klass->image);
5334 if (!klass->has_finalize_inited) {
5335 klass->has_finalize = has_finalize ? 1 : 0;
5337 mono_memory_barrier ();
5338 klass->has_finalize_inited = TRUE;
5341 mono_image_unlock (klass->image);
5343 return klass->has_finalize;
5347 mono_is_corlib_image (MonoImage *image)
5349 /* FIXME: allow the dynamic case for our compilers and with full trust */
5350 if (image_is_dynamic (image))
5351 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5353 return image == mono_defaults.corlib;
5357 * LOCKING: this assumes the loader lock is held
5360 mono_class_setup_mono_type (MonoClass *klass)
5362 const char *name = klass->name;
5363 const char *nspace = klass->name_space;
5364 gboolean is_corlib = mono_is_corlib_image (klass->image);
5366 klass->this_arg.byref = 1;
5367 klass->this_arg.data.klass = klass;
5368 klass->this_arg.type = MONO_TYPE_CLASS;
5369 klass->byval_arg.data.klass = klass;
5370 klass->byval_arg.type = MONO_TYPE_CLASS;
5372 if (is_corlib && !strcmp (nspace, "System")) {
5373 if (!strcmp (name, "ValueType")) {
5375 * do not set the valuetype bit for System.ValueType.
5376 * klass->valuetype = 1;
5378 klass->blittable = TRUE;
5379 } else if (!strcmp (name, "Enum")) {
5381 * do not set the valuetype bit for System.Enum.
5382 * klass->valuetype = 1;
5384 klass->valuetype = 0;
5385 klass->enumtype = 0;
5386 } else if (!strcmp (name, "Object")) {
5387 klass->byval_arg.type = MONO_TYPE_OBJECT;
5388 klass->this_arg.type = MONO_TYPE_OBJECT;
5389 } else if (!strcmp (name, "String")) {
5390 klass->byval_arg.type = MONO_TYPE_STRING;
5391 klass->this_arg.type = MONO_TYPE_STRING;
5392 } else if (!strcmp (name, "TypedReference")) {
5393 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5394 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5398 if (klass->valuetype) {
5399 int t = MONO_TYPE_VALUETYPE;
5401 if (is_corlib && !strcmp (nspace, "System")) {
5404 if (!strcmp (name, "Boolean")) {
5405 t = MONO_TYPE_BOOLEAN;
5406 } else if (!strcmp(name, "Byte")) {
5408 klass->blittable = TRUE;
5412 if (!strcmp (name, "Char")) {
5417 if (!strcmp (name, "Double")) {
5419 klass->blittable = TRUE;
5423 if (!strcmp (name, "Int32")) {
5425 klass->blittable = TRUE;
5426 } else if (!strcmp(name, "Int16")) {
5428 klass->blittable = TRUE;
5429 } else if (!strcmp(name, "Int64")) {
5431 klass->blittable = TRUE;
5432 } else if (!strcmp(name, "IntPtr")) {
5434 klass->blittable = TRUE;
5438 if (!strcmp (name, "Single")) {
5440 klass->blittable = TRUE;
5441 } else if (!strcmp(name, "SByte")) {
5443 klass->blittable = TRUE;
5447 if (!strcmp (name, "UInt32")) {
5449 klass->blittable = TRUE;
5450 } else if (!strcmp(name, "UInt16")) {
5452 klass->blittable = TRUE;
5453 } else if (!strcmp(name, "UInt64")) {
5455 klass->blittable = TRUE;
5456 } else if (!strcmp(name, "UIntPtr")) {
5458 klass->blittable = TRUE;
5462 if (!strcmp (name, "TypedReference")) {
5463 t = MONO_TYPE_TYPEDBYREF;
5464 klass->blittable = TRUE;
5468 if (!strcmp (name, "Void")) {
5476 klass->byval_arg.type = (MonoTypeEnum)t;
5477 klass->this_arg.type = (MonoTypeEnum)t;
5480 if (MONO_CLASS_IS_INTERFACE (klass))
5481 klass->interface_id = mono_get_unique_iid (klass);
5487 * COM initialization is delayed until needed.
5488 * However when a [ComImport] attribute is present on a type it will trigger
5489 * the initialization. This is not a problem unless the BCL being executed
5490 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5493 init_com_from_comimport (MonoClass *klass)
5495 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5496 if (mono_security_core_clr_enabled ()) {
5497 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5498 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5499 /* but it can not be made available for application (i.e. user code) since all COM calls
5500 * are considered native calls. In this case we fail with a TypeLoadException (just like
5501 * Silverlight 2 does */
5502 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5507 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5509 #endif /*DISABLE_COM*/
5512 * LOCKING: this assumes the loader lock is held
5515 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5517 gboolean system_namespace;
5518 gboolean is_corlib = mono_is_corlib_image (klass->image);
5520 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5522 /* if root of the hierarchy */
5523 if (system_namespace && !strcmp (klass->name, "Object")) {
5524 klass->parent = NULL;
5525 klass->instance_size = sizeof (MonoObject);
5528 if (!strcmp (klass->name, "<Module>")) {
5529 klass->parent = NULL;
5530 klass->instance_size = 0;
5534 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5535 /* Imported COM Objects always derive from __ComObject. */
5537 if (MONO_CLASS_IS_IMPORT (klass)) {
5538 init_com_from_comimport (klass);
5539 if (parent == mono_defaults.object_class)
5540 parent = mono_class_get_com_object_class ();
5544 /* set the parent to something useful and safe, but mark the type as broken */
5545 parent = mono_defaults.object_class;
5546 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5549 klass->parent = parent;
5551 if (parent->generic_class && !parent->name) {
5553 * If the parent is a generic instance, we may get
5554 * called before it is fully initialized, especially
5555 * before it has its name.
5560 #ifndef DISABLE_REMOTING
5561 klass->marshalbyref = parent->marshalbyref;
5562 klass->contextbound = parent->contextbound;
5565 klass->delegate = parent->delegate;
5567 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5568 mono_class_set_is_com_object (klass);
5570 if (system_namespace) {
5571 #ifndef DISABLE_REMOTING
5572 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5573 klass->marshalbyref = 1;
5575 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5576 klass->contextbound = 1;
5578 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5579 klass->delegate = 1;
5582 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5583 (strcmp (klass->parent->name_space, "System") == 0)))
5584 klass->valuetype = 1;
5585 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5586 klass->valuetype = klass->enumtype = 1;
5588 /*klass->enumtype = klass->parent->enumtype; */
5590 /* initialize com types if COM interfaces are present */
5592 if (MONO_CLASS_IS_IMPORT (klass))
5593 init_com_from_comimport (klass);
5595 klass->parent = NULL;
5601 * mono_class_setup_supertypes:
5604 * Build the data structure needed to make fast type checks work.
5605 * This currently sets two fields in @class:
5606 * - idepth: distance between @class and System.Object in the type
5608 * - supertypes: array of classes: each element has a class in the hierarchy
5609 * starting from @class up to System.Object
5611 * LOCKING: This function is atomic, in case of contention we waste memory.
5614 mono_class_setup_supertypes (MonoClass *klass)
5617 MonoClass **supertypes;
5619 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5623 if (klass->parent && !klass->parent->supertypes)
5624 mono_class_setup_supertypes (klass->parent);
5626 klass->idepth = klass->parent->idepth + 1;
5630 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5631 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5633 if (klass->parent) {
5634 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5637 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5638 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5640 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5643 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5647 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5649 MonoClass *gtd = (MonoClass*)user_data;
5650 /* Only try to fix generic instances of @gtd */
5651 if (gclass->generic_class->container_class != gtd)
5654 /* Check if the generic instance has no parent. */
5655 if (gtd->parent && !gclass->parent)
5656 mono_generic_class_setup_parent (gclass, gtd);
5662 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5664 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5665 mono_error_set_type_load_class (error, klass, msg);
5669 * mono_class_create_from_typedef:
5670 * @image: image where the token is valid
5671 * @type_token: typedef token
5672 * @error: used to return any error found while creating the type
5674 * Create the MonoClass* representing the specified type token.
5675 * @type_token must be a TypeDef token.
5677 * FIXME: don't return NULL on failure, just the the caller figure it out.
5680 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5682 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5683 MonoClass *klass, *parent = NULL;
5684 guint32 cols [MONO_TYPEDEF_SIZE];
5685 guint32 cols_next [MONO_TYPEDEF_SIZE];
5686 guint tidx = mono_metadata_token_index (type_token);
5687 MonoGenericContext *context = NULL;
5688 const char *name, *nspace;
5690 MonoClass **interfaces;
5691 guint32 field_last, method_last;
5692 guint32 nesting_tokeen;
5694 mono_error_init (error);
5696 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5697 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5701 mono_loader_lock ();
5703 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5704 mono_loader_unlock ();
5708 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5710 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5711 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5713 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5716 klass->name_space = nspace;
5718 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5720 klass->image = image;
5721 klass->type_token = type_token;
5722 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5724 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5726 classes_size += sizeof (MonoClass);
5729 * Check whether we're a generic type definition.
5731 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5732 if (klass->generic_container) {
5733 klass->is_generic = 1;
5734 klass->generic_container->owner.klass = klass;
5735 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5736 context = &klass->generic_container->context;
5739 if (klass->generic_container)
5740 enable_gclass_recording ();
5742 if (cols [MONO_TYPEDEF_EXTENDS]) {
5744 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5746 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5747 /*WARNING: this must satisfy mono_metadata_type_hash*/
5748 klass->this_arg.byref = 1;
5749 klass->this_arg.data.klass = klass;
5750 klass->this_arg.type = MONO_TYPE_CLASS;
5751 klass->byval_arg.data.klass = klass;
5752 klass->byval_arg.type = MONO_TYPE_CLASS;
5754 parent = mono_class_get_checked (image, parent_token, error);
5755 if (parent && context) /* Always inflate */
5756 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5758 if (parent == NULL) {
5759 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5760 goto parent_failure;
5763 for (tmp = parent; tmp; tmp = tmp->parent) {
5765 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5766 goto parent_failure;
5768 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5769 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5770 goto parent_failure;
5775 mono_class_setup_parent (klass, parent);
5777 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5778 mono_class_setup_mono_type (klass);
5780 if (klass->generic_container)
5781 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5784 * This might access klass->byval_arg for recursion generated by generic constraints,
5785 * so it has to come after setup_mono_type ().
5787 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5788 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5789 if (!mono_error_ok (error)) {
5790 /*FIXME implement a mono_class_set_failure_from_mono_error */
5791 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5792 mono_loader_unlock ();
5793 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5798 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5802 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5806 klass->cast_class = klass->element_class = klass;
5808 if (!klass->enumtype) {
5809 if (!mono_metadata_interfaces_from_typedef_full (
5810 image, type_token, &interfaces, &icount, FALSE, context, error)){
5812 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5813 mono_loader_unlock ();
5814 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5818 klass->interfaces = interfaces;
5819 klass->interface_count = icount;
5820 klass->interfaces_inited = 1;
5823 /*g_print ("Load class %s\n", name);*/
5826 * Compute the field and method lists
5828 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5829 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5831 if (tt->rows > tidx){
5832 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5833 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5834 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5836 field_last = image->tables [MONO_TABLE_FIELD].rows;
5837 method_last = image->tables [MONO_TABLE_METHOD].rows;
5840 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5841 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5842 klass->field.count = field_last - klass->field.first;
5844 klass->field.count = 0;
5846 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5847 klass->method.count = method_last - klass->method.first;
5849 klass->method.count = 0;
5851 /* reserve space to store vector pointer in arrays */
5852 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5853 klass->instance_size += 2 * sizeof (gpointer);
5854 g_assert (klass->field.count == 0);
5857 if (klass->enumtype) {
5858 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5859 if (!enum_basetype) {
5860 /*set it to a default value as the whole runtime can't handle this to be null*/
5861 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5862 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5863 mono_loader_unlock ();
5864 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5867 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5871 * If we're a generic type definition, load the constraints.
5872 * We must do this after the class has been constructed to make certain recursive scenarios
5875 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5876 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5877 mono_loader_unlock ();
5878 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5882 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5883 if (!strncmp (name, "Vector", 6))
5884 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");
5887 mono_loader_unlock ();
5889 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5894 mono_class_setup_mono_type (klass);
5895 mono_loader_unlock ();
5896 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5900 /** Is klass a Nullable<T> ginst? */
5902 mono_class_is_nullable (MonoClass *klass)
5904 return klass->generic_class != NULL &&
5905 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5909 /** if klass is T? return T */
5911 mono_class_get_nullable_param (MonoClass *klass)
5913 g_assert (mono_class_is_nullable (klass));
5914 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5918 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5922 MonoGenericClass *gclass = klass->generic_class;
5924 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5925 if (!mono_error_ok (&error)) {
5926 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5927 klass->parent = mono_defaults.object_class;
5928 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5929 mono_error_cleanup (&error);
5933 mono_class_setup_parent (klass, klass->parent);
5935 if (klass->enumtype) {
5936 klass->cast_class = gtd->cast_class;
5937 klass->element_class = gtd->element_class;
5943 * Create the `MonoClass' for an instantiation of a generic type.
5944 * We only do this if we actually need it.
5947 mono_generic_class_get_class (MonoGenericClass *gclass)
5949 MonoClass *klass, *gklass;
5951 if (gclass->cached_class)
5952 return gclass->cached_class;
5954 mono_loader_lock ();
5955 if (gclass->cached_class) {
5956 mono_loader_unlock ();
5957 return gclass->cached_class;
5960 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5962 gklass = gclass->container_class;
5964 if (record_gclass_instantiation > 0)
5965 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5967 if (gklass->nested_in) {
5968 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5969 klass->nested_in = gklass->nested_in;
5972 klass->name = gklass->name;
5973 klass->name_space = gklass->name_space;
5975 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5977 klass->image = gklass->image;
5978 klass->flags = gklass->flags;
5979 klass->type_token = gklass->type_token;
5980 klass->field.count = gklass->field.count;
5982 klass->is_inflated = 1;
5983 klass->generic_class = gclass;
5985 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5986 klass->this_arg.type = klass->byval_arg.type;
5987 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5988 klass->this_arg.byref = TRUE;
5989 klass->enumtype = gklass->enumtype;
5990 klass->valuetype = gklass->valuetype;
5992 klass->cast_class = klass->element_class = klass;
5994 if (mono_class_is_nullable (klass))
5995 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5998 * We're not interested in the nested classes of a generic instance.
5999 * We use the generic type definition to look for nested classes.
6002 mono_generic_class_setup_parent (klass, gklass);
6004 if (gclass->is_dynamic) {
6006 * 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.
6007 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6008 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6010 if (!gklass->wastypebuilder)
6013 mono_class_setup_supertypes (klass);
6015 if (klass->enumtype) {
6017 * For enums, gklass->fields might not been set, but instance_size etc. is
6018 * already set in mono_reflection_create_internal_class (). For non-enums,
6019 * these will be computed normally in mono_class_layout_fields ().
6021 klass->instance_size = gklass->instance_size;
6022 klass->sizes.class_size = gklass->sizes.class_size;
6023 mono_memory_barrier ();
6024 klass->size_inited = 1;
6028 mono_memory_barrier ();
6029 gclass->cached_class = klass;
6031 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6033 inflated_classes ++;
6034 inflated_classes_size += sizeof (MonoClass);
6036 mono_loader_unlock ();
6042 get_image_for_container (MonoGenericContainer *container)
6045 if (container->is_anonymous) {
6046 result = container->owner.image;
6049 if (container->is_method) {
6050 MonoMethod *method = container->owner.method;
6051 g_assert_checked (method);
6052 klass = method->klass;
6054 klass = container->owner.klass;
6056 g_assert_checked (klass);
6057 result = klass->image;
6064 get_image_for_generic_param (MonoGenericParam *param)
6066 MonoGenericContainer *container = mono_generic_param_owner (param);
6067 g_assert_checked (container);
6068 return get_image_for_container (container);
6071 // Make a string in the designated image consisting of a single integer.
6072 #define INT_STRING_SIZE 16
6074 make_generic_name_string (MonoImage *image, int num)
6076 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6077 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6081 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6082 // pinfo is derived from param by the caller for us.
6084 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6086 MonoClass *klass, **ptr;
6088 MonoGenericContainer *container = mono_generic_param_owner (param);
6089 g_assert_checked (container);
6091 MonoImage *image = get_image_for_container (container);
6092 gboolean is_mvar = container->is_method;
6093 gboolean is_anonymous = container->is_anonymous;
6095 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6096 classes_size += sizeof (MonoClass);
6099 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6101 int n = mono_generic_param_num (param);
6102 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6106 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6107 } else if (is_mvar) {
6108 MonoMethod *omethod = container->owner.method;
6109 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6111 MonoClass *oklass = container->owner.klass;
6112 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6115 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6117 // Count non-NULL items in pinfo->constraints
6120 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6124 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6125 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6127 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6128 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6130 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6133 if (count - pos > 0) {
6134 klass->interface_count = count - pos;
6135 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6136 klass->interfaces_inited = TRUE;
6137 for (i = pos; i < count; i++)
6138 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6141 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6143 klass->inited = TRUE;
6144 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6145 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6146 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6148 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6149 klass->this_arg.type = klass->byval_arg.type;
6150 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6151 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6152 klass->this_arg.byref = TRUE;
6154 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6155 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6157 /*Init these fields to sane values*/
6158 klass->min_align = 1;
6160 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6161 * constrained to, the JIT depends on this.
6163 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6164 mono_memory_barrier ();
6165 klass->size_inited = 1;
6166 klass->setup_fields_called = 1;
6168 mono_class_setup_supertypes (klass);
6170 if (count - pos > 0) {
6171 mono_class_setup_vtable (klass->parent);
6172 if (mono_class_has_failure (klass->parent))
6173 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6175 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6181 #define FAST_CACHE_SIZE 16
6184 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6185 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6186 * we cache the MonoClasses.
6187 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6188 * LOCKING: Takes the image lock depending on @take_lock.
6191 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6193 int n = mono_generic_param_num (param);
6194 MonoImage *image = get_image_for_generic_param (param);
6195 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6196 MonoClass *klass = NULL;
6201 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6202 // For high numbers or constraints we have to use pointer hashes.
6203 if (param->gshared_constraint) {
6204 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6207 mono_image_lock (image);
6208 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6210 mono_image_unlock (image);
6215 if (n < FAST_CACHE_SIZE) {
6217 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6219 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6221 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6224 mono_image_lock (image);
6225 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6227 mono_image_unlock (image);
6234 * LOCKING: Image lock (param->image) must be held
6237 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6239 int n = mono_generic_param_num (param);
6240 MonoImage *image = get_image_for_generic_param (param);
6241 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6245 if (param->gshared_constraint) {
6246 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6248 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6249 mono_memory_barrier ();
6251 image->mvar_cache_constrained = ht;
6253 image->var_cache_constrained = ht;
6255 g_hash_table_insert (ht, param, klass);
6256 } else if (n < FAST_CACHE_SIZE) {
6258 /* Requires locking to avoid droping an already published class */
6259 if (!image->mvar_cache_fast)
6260 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6261 image->mvar_cache_fast [n] = klass;
6263 if (!image->var_cache_fast)
6264 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6265 image->var_cache_fast [n] = klass;
6268 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6270 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6272 ht = g_hash_table_new (NULL, NULL);
6273 mono_memory_barrier ();
6275 image->mvar_cache_slow = ht;
6277 image->var_cache_slow = ht;
6280 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6285 * LOCKING: Acquires the image lock (@image).
6288 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6290 MonoImage *image = get_image_for_generic_param (param);
6291 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6292 MonoClass *klass, *klass2;
6294 // If a klass already exists for this object and is cached, return it.
6295 if (pinfo) // Non-anonymous
6296 klass = pinfo->pklass;
6298 klass = get_anon_gparam_class (param, TRUE);
6303 // Create a new klass
6304 klass = make_generic_param_class (param, pinfo);
6306 // Now we need to cache the klass we created.
6307 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6308 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6309 // and allow our newly-created klass object to just leak.
6310 mono_memory_barrier ();
6312 mono_image_lock (image);
6314 // Here "klass2" refers to the klass potentially created by the other thread.
6315 if (pinfo) // Repeat check from above
6316 klass2 = pinfo->pklass;
6318 klass2 = get_anon_gparam_class (param, FALSE);
6325 pinfo->pklass = klass;
6327 set_anon_gparam_class (param, klass);
6329 mono_image_unlock (image);
6331 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6333 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6335 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6341 * mono_class_from_generic_parameter:
6342 * @param: Parameter to find/construct a class for.
6343 * @arg2: Is ignored.
6344 * @arg3: Is ignored.
6347 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6349 return mono_class_from_generic_parameter_internal (param);
6354 mono_ptr_class_get (MonoType *type)
6357 MonoClass *el_class;
6361 el_class = mono_class_from_mono_type (type);
6362 image = el_class->image;
6364 mono_image_lock (image);
6365 if (image->ptr_cache) {
6366 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6367 mono_image_unlock (image);
6371 mono_image_unlock (image);
6373 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6375 classes_size += sizeof (MonoClass);
6377 result->parent = NULL; /* no parent for PTR types */
6378 result->name_space = el_class->name_space;
6379 name = g_strdup_printf ("%s*", el_class->name);
6380 result->name = mono_image_strdup (image, name);
6383 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6385 result->image = el_class->image;
6386 result->inited = TRUE;
6387 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6388 /* Can pointers get boxed? */
6389 result->instance_size = 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 /* Can pointers get boxed? */
6448 result->instance_size = sizeof (gpointer);
6449 result->cast_class = result->element_class = result;
6450 result->blittable = TRUE;
6452 result->byval_arg.type = MONO_TYPE_FNPTR;
6453 result->this_arg.type = result->byval_arg.type;
6454 result->this_arg.data.method = result->byval_arg.data.method = sig;
6455 result->this_arg.byref = TRUE;
6456 result->blittable = TRUE;
6458 mono_class_setup_supertypes (result);
6460 g_hash_table_insert (ptr_hash, sig, result);
6462 mono_loader_unlock ();
6464 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6470 * mono_class_from_mono_type:
6471 * @type: describes the type to return
6473 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6476 mono_class_from_mono_type (MonoType *type)
6478 switch (type->type) {
6479 case MONO_TYPE_OBJECT:
6480 return type->data.klass? type->data.klass: mono_defaults.object_class;
6481 case MONO_TYPE_VOID:
6482 return type->data.klass? type->data.klass: mono_defaults.void_class;
6483 case MONO_TYPE_BOOLEAN:
6484 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6485 case MONO_TYPE_CHAR:
6486 return type->data.klass? type->data.klass: mono_defaults.char_class;
6488 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6490 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6492 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6494 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6496 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6498 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6500 return type->data.klass? type->data.klass: mono_defaults.int_class;
6502 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6504 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6506 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6508 return type->data.klass? type->data.klass: mono_defaults.single_class;
6510 return type->data.klass? type->data.klass: mono_defaults.double_class;
6511 case MONO_TYPE_STRING:
6512 return type->data.klass? type->data.klass: mono_defaults.string_class;
6513 case MONO_TYPE_TYPEDBYREF:
6514 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6515 case MONO_TYPE_ARRAY:
6516 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6518 return mono_ptr_class_get (type->data.type);
6519 case MONO_TYPE_FNPTR:
6520 return mono_fnptr_class_get (type->data.method);
6521 case MONO_TYPE_SZARRAY:
6522 return mono_array_class_get (type->data.klass, 1);
6523 case MONO_TYPE_CLASS:
6524 case MONO_TYPE_VALUETYPE:
6525 return type->data.klass;
6526 case MONO_TYPE_GENERICINST:
6527 return mono_generic_class_get_class (type->data.generic_class);
6528 case MONO_TYPE_MVAR:
6530 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6532 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6533 g_assert_not_reached ();
6536 // Yes, this returns NULL, even if it is documented as not doing so, but there
6537 // is no way for the code to make it this far, due to the assert above.
6542 * mono_type_retrieve_from_typespec
6543 * @image: context where the image is created
6544 * @type_spec: typespec token
6545 * @context: the generic context used to evaluate generic instantiations in
6548 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6550 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6552 *did_inflate = FALSE;
6557 if (context && (context->class_inst || context->method_inst)) {
6558 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6560 if (!mono_error_ok (error)) {
6566 *did_inflate = TRUE;
6573 * mono_class_create_from_typespec
6574 * @image: context where the image is created
6575 * @type_spec: typespec token
6576 * @context: the generic context used to evaluate generic instantiations in
6579 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6582 gboolean inflated = FALSE;
6583 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6584 return_val_if_nok (error, NULL);
6585 ret = mono_class_from_mono_type (t);
6587 mono_metadata_free_type (t);
6592 * mono_bounded_array_class_get:
6593 * @element_class: element class
6594 * @rank: the dimension of the array class
6595 * @bounded: whenever the array has non-zero bounds
6597 * Returns: A class object describing the array with element type @element_type and
6601 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6605 MonoClass *parent = NULL;
6606 GSList *list, *rootlist = NULL;
6609 gboolean corlib_type = FALSE;
6611 g_assert (rank <= 255);
6614 /* bounded only matters for one-dimensional arrays */
6617 image = eclass->image;
6619 if (rank == 1 && !bounded) {
6621 * This case is very frequent not just during compilation because of calls
6622 * from mono_class_from_mono_type (), mono_array_new (),
6623 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6625 mono_os_mutex_lock (&image->szarray_cache_lock);
6626 if (!image->szarray_cache)
6627 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6628 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6629 mono_os_mutex_unlock (&image->szarray_cache_lock);
6633 mono_loader_lock ();
6635 mono_loader_lock ();
6637 if (!image->array_cache)
6638 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6640 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6641 for (; list; list = list->next) {
6642 klass = (MonoClass *)list->data;
6643 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6644 mono_loader_unlock ();
6651 /* for the building corlib use System.Array from it */
6652 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6653 parent = mono_class_load_from_name (image, "System", "Array");
6656 parent = mono_defaults.array_class;
6657 if (!parent->inited)
6658 mono_class_init (parent);
6661 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6663 klass->image = image;
6664 klass->name_space = eclass->name_space;
6665 nsize = strlen (eclass->name);
6666 name = (char *)g_malloc (nsize + 2 + rank + 1);
6667 memcpy (name, eclass->name, nsize);
6670 memset (name + nsize + 1, ',', rank - 1);
6672 name [nsize + rank] = '*';
6673 name [nsize + rank + bounded] = ']';
6674 name [nsize + rank + bounded + 1] = 0;
6675 klass->name = mono_image_strdup (image, name);
6678 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6680 classes_size += sizeof (MonoClass);
6682 klass->type_token = 0;
6683 /* all arrays are marked serializable and sealed, bug #42779 */
6684 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6685 klass->parent = parent;
6686 klass->instance_size = mono_class_instance_size (klass->parent);
6688 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6689 /*Arrays of those two types are invalid.*/
6690 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6691 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6692 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6693 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6694 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6696 /* element_size -1 is ok as this is not an instantitable type*/
6697 klass->sizes.element_size = -1;
6699 klass->sizes.element_size = mono_class_array_element_size (eclass);
6701 mono_class_setup_supertypes (klass);
6703 if (eclass->generic_class)
6704 mono_class_init (eclass);
6705 if (!eclass->size_inited)
6706 mono_class_setup_fields (eclass);
6707 if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6708 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6710 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6714 if (eclass->enumtype)
6715 klass->cast_class = eclass->element_class;
6717 klass->cast_class = eclass;
6719 switch (klass->cast_class->byval_arg.type) {
6721 klass->cast_class = mono_defaults.byte_class;
6724 klass->cast_class = mono_defaults.int16_class;
6727 #if SIZEOF_VOID_P == 4
6731 klass->cast_class = mono_defaults.int32_class;
6734 #if SIZEOF_VOID_P == 8
6738 klass->cast_class = mono_defaults.int64_class;
6744 klass->element_class = eclass;
6746 if ((rank > 1) || bounded) {
6747 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6748 klass->byval_arg.type = MONO_TYPE_ARRAY;
6749 klass->byval_arg.data.array = at;
6750 at->eklass = eclass;
6752 /* FIXME: complete.... */
6754 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6755 klass->byval_arg.data.klass = eclass;
6757 klass->this_arg = klass->byval_arg;
6758 klass->this_arg.byref = 1;
6763 klass->generic_container = eclass->generic_container;
6765 if (rank == 1 && !bounded) {
6766 MonoClass *prev_class;
6768 mono_os_mutex_lock (&image->szarray_cache_lock);
6769 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6771 /* Someone got in before us */
6774 g_hash_table_insert (image->szarray_cache, eclass, klass);
6775 mono_os_mutex_unlock (&image->szarray_cache_lock);
6777 list = g_slist_append (rootlist, klass);
6778 g_hash_table_insert (image->array_cache, eclass, list);
6781 mono_loader_unlock ();
6783 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6789 * mono_array_class_get:
6790 * @element_class: element class
6791 * @rank: the dimension of the array class
6793 * Returns: A class object describing the array with element type @element_type and
6797 mono_array_class_get (MonoClass *eclass, guint32 rank)
6799 return mono_bounded_array_class_get (eclass, rank, FALSE);
6803 * mono_class_instance_size:
6806 * Use to get the size of a class in bytes.
6808 * Returns: The size of an object instance
6811 mono_class_instance_size (MonoClass *klass)
6813 if (!klass->size_inited)
6814 mono_class_init (klass);
6816 return klass->instance_size;
6820 * mono_class_min_align:
6823 * Use to get the computed minimum alignment requirements for the specified class.
6825 * Returns: minimm alignment requirements
6828 mono_class_min_align (MonoClass *klass)
6830 if (!klass->size_inited)
6831 mono_class_init (klass);
6833 return klass->min_align;
6837 * mono_class_value_size:
6840 * This function is used for value types, and return the
6841 * space and the alignment to store that kind of value object.
6843 * Returns: the size of a value of kind @klass
6846 mono_class_value_size (MonoClass *klass, guint32 *align)
6850 /* fixme: check disable, because we still have external revereces to
6851 * mscorlib and Dummy Objects
6853 /*g_assert (klass->valuetype);*/
6855 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6858 *align = klass->min_align;
6864 * mono_class_data_size:
6867 * Returns: The size of the static class data
6870 mono_class_data_size (MonoClass *klass)
6873 mono_class_init (klass);
6874 /* This can happen with dynamically created types */
6875 if (!klass->fields_inited)
6876 mono_class_setup_fields_locking (klass);
6878 /* in arrays, sizes.class_size is unioned with element_size
6879 * and arrays have no static fields
6883 return klass->sizes.class_size;
6887 * Auxiliary routine to mono_class_get_field
6889 * Takes a field index instead of a field token.
6891 static MonoClassField *
6892 mono_class_get_field_idx (MonoClass *klass, int idx)
6894 mono_class_setup_fields_locking (klass);
6895 if (mono_class_has_failure (klass))
6899 if (klass->image->uncompressed_metadata) {
6901 * klass->field.first points to the FieldPtr table, while idx points into the
6902 * Field table, so we have to do a search.
6904 /*FIXME this is broken for types with multiple fields with the same name.*/
6905 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6908 for (i = 0; i < klass->field.count; ++i)
6909 if (mono_field_get_name (&klass->fields [i]) == name)
6910 return &klass->fields [i];
6911 g_assert_not_reached ();
6913 if (klass->field.count) {
6914 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6915 return &klass->fields [idx - klass->field.first];
6919 klass = klass->parent;
6925 * mono_class_get_field:
6926 * @class: the class to lookup the field.
6927 * @field_token: the field token
6929 * Returns: A MonoClassField representing the type and offset of
6930 * the field, or a NULL value if the field does not belong to this
6934 mono_class_get_field (MonoClass *klass, guint32 field_token)
6936 int idx = mono_metadata_token_index (field_token);
6938 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6940 return mono_class_get_field_idx (klass, idx - 1);
6944 * mono_class_get_field_from_name:
6945 * @klass: the class to lookup the field.
6946 * @name: the field name
6948 * Search the class @klass and it's parents for a field with the name @name.
6950 * Returns: The MonoClassField pointer of the named field or NULL
6953 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6955 return mono_class_get_field_from_name_full (klass, name, NULL);
6959 * mono_class_get_field_from_name_full:
6960 * @klass: the class to lookup the field.
6961 * @name: the field name
6962 * @type: the type of the fields. This optional.
6964 * Search the class @klass and it's parents for a field with the name @name and type @type.
6966 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6967 * of its generic type definition.
6969 * Returns: The MonoClassField pointer of the named field or NULL
6972 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6976 mono_class_setup_fields_locking (klass);
6977 if (mono_class_has_failure (klass))
6981 for (i = 0; i < klass->field.count; ++i) {
6982 MonoClassField *field = &klass->fields [i];
6984 if (strcmp (name, mono_field_get_name (field)) != 0)
6988 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6989 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6994 klass = klass->parent;
7000 * mono_class_get_field_token:
7001 * @field: the field we need the token of
7003 * Get the token of a field. Note that the tokesn is only valid for the image
7004 * the field was loaded from. Don't use this function for fields in dynamic types.
7006 * Returns: The token representing the field in the image it was loaded from.
7009 mono_class_get_field_token (MonoClassField *field)
7011 MonoClass *klass = field->parent;
7014 mono_class_setup_fields_locking (klass);
7019 for (i = 0; i < klass->field.count; ++i) {
7020 if (&klass->fields [i] == field) {
7021 int idx = klass->field.first + i + 1;
7023 if (klass->image->uncompressed_metadata)
7024 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7025 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7028 klass = klass->parent;
7031 g_assert_not_reached ();
7036 mono_field_get_index (MonoClassField *field)
7038 int index = field - field->parent->fields;
7040 g_assert (index >= 0 && index < field->parent->field.count);
7046 * mono_class_get_field_default_value:
7048 * Return the default value of the field as a pointer into the metadata blob.
7051 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7054 guint32 constant_cols [MONO_CONSTANT_SIZE];
7056 MonoClass *klass = field->parent;
7058 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7060 if (!klass->ext || !klass->ext->field_def_values) {
7061 MonoFieldDefaultValue *def_values;
7063 mono_class_alloc_ext (klass);
7065 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7067 mono_image_lock (klass->image);
7068 mono_memory_barrier ();
7069 if (!klass->ext->field_def_values)
7070 klass->ext->field_def_values = def_values;
7071 mono_image_unlock (klass->image);
7074 field_index = mono_field_get_index (field);
7076 if (!klass->ext->field_def_values [field_index].data) {
7077 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7081 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7083 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7084 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7085 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7088 *def_type = klass->ext->field_def_values [field_index].def_type;
7089 return klass->ext->field_def_values [field_index].data;
7093 mono_property_get_index (MonoProperty *prop)
7095 int index = prop - prop->parent->ext->properties;
7097 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7103 * mono_class_get_property_default_value:
7105 * Return the default value of the field as a pointer into the metadata blob.
7108 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7111 guint32 constant_cols [MONO_CONSTANT_SIZE];
7112 MonoClass *klass = property->parent;
7114 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7116 * We don't cache here because it is not used by C# so it's quite rare, but
7117 * we still do the lookup in klass->ext because that is where the data
7118 * is stored for dynamic assemblies.
7121 if (image_is_dynamic (klass->image)) {
7122 int prop_index = mono_property_get_index (property);
7123 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7124 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7125 return klass->ext->prop_def_values [prop_index].data;
7129 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7133 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7134 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7135 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7139 mono_class_get_event_token (MonoEvent *event)
7141 MonoClass *klass = event->parent;
7146 for (i = 0; i < klass->ext->event.count; ++i) {
7147 if (&klass->ext->events [i] == event)
7148 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7151 klass = klass->parent;
7154 g_assert_not_reached ();
7159 * mono_class_get_property_from_name:
7161 * @name: name of the property to lookup in the specified class
7163 * Use this method to lookup a property in a class
7164 * Returns: the MonoProperty with the given name, or NULL if the property
7165 * does not exist on the @klass.
7168 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7172 gpointer iter = NULL;
7173 while ((p = mono_class_get_properties (klass, &iter))) {
7174 if (! strcmp (name, p->name))
7177 klass = klass->parent;
7183 * mono_class_get_property_token:
7184 * @prop: MonoProperty to query
7186 * Returns: The ECMA token for the specified property.
7189 mono_class_get_property_token (MonoProperty *prop)
7191 MonoClass *klass = prop->parent;
7195 gpointer iter = NULL;
7196 while ((p = mono_class_get_properties (klass, &iter))) {
7197 if (&klass->ext->properties [i] == prop)
7198 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7202 klass = klass->parent;
7205 g_assert_not_reached ();
7210 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7212 const char *name, *nspace;
7213 if (image_is_dynamic (image))
7214 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7216 switch (type_token & 0xff000000){
7217 case MONO_TOKEN_TYPE_DEF: {
7218 guint32 cols [MONO_TYPEDEF_SIZE];
7219 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7220 guint tidx = mono_metadata_token_index (type_token);
7222 if (tidx > tt->rows)
7223 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7225 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7226 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7227 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7228 if (strlen (nspace) == 0)
7229 return g_strdup_printf ("%s", name);
7231 return g_strdup_printf ("%s.%s", nspace, name);
7234 case MONO_TOKEN_TYPE_REF: {
7236 guint32 cols [MONO_TYPEREF_SIZE];
7237 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7238 guint tidx = mono_metadata_token_index (type_token);
7241 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7243 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7244 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7245 mono_error_cleanup (&error);
7249 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7250 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7251 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7252 if (strlen (nspace) == 0)
7253 return g_strdup_printf ("%s", name);
7255 return g_strdup_printf ("%s.%s", nspace, name);
7258 case MONO_TOKEN_TYPE_SPEC:
7259 return g_strdup_printf ("Typespec 0x%08x", type_token);
7261 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7266 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7268 if (image_is_dynamic (image))
7269 return g_strdup_printf ("DynamicAssembly %s", image->name);
7271 switch (type_token & 0xff000000){
7272 case MONO_TOKEN_TYPE_DEF:
7273 if (image->assembly)
7274 return mono_stringify_assembly_name (&image->assembly->aname);
7275 else if (image->assembly_name)
7276 return g_strdup (image->assembly_name);
7277 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7278 case MONO_TOKEN_TYPE_REF: {
7280 MonoAssemblyName aname;
7281 guint32 cols [MONO_TYPEREF_SIZE];
7282 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7283 guint32 idx = mono_metadata_token_index (type_token);
7286 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7288 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7289 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7290 mono_error_cleanup (&error);
7293 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7295 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7296 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7297 case MONO_RESOLUTION_SCOPE_MODULE:
7299 return g_strdup ("");
7300 case MONO_RESOLUTION_SCOPE_MODULEREF:
7302 return g_strdup ("");
7303 case MONO_RESOLUTION_SCOPE_TYPEREF:
7305 return g_strdup ("");
7306 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7307 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7308 return mono_stringify_assembly_name (&aname);
7310 g_assert_not_reached ();
7314 case MONO_TOKEN_TYPE_SPEC:
7316 return g_strdup ("");
7318 g_assert_not_reached ();
7325 * mono_class_get_full:
7326 * @image: the image where the class resides
7327 * @type_token: the token for the class
7328 * @context: the generic context used to evaluate generic instantiations in
7329 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7331 * Returns: The MonoClass that represents @type_token in @image
7334 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7338 klass = mono_class_get_checked (image, type_token, &error);
7340 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7341 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7343 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7349 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7353 mono_error_init (error);
7354 klass = mono_class_get_checked (image, type_token, error);
7356 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7357 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7362 * mono_class_get_checked:
7363 * @image: the image where the class resides
7364 * @type_token: the token for the class
7365 * @error: error object to return any error
7367 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7370 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7372 MonoClass *klass = NULL;
7374 mono_error_init (error);
7376 if (image_is_dynamic (image)) {
7377 int table = mono_metadata_token_table (type_token);
7379 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7380 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7383 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7387 switch (type_token & 0xff000000){
7388 case MONO_TOKEN_TYPE_DEF:
7389 klass = mono_class_create_from_typedef (image, type_token, error);
7391 case MONO_TOKEN_TYPE_REF:
7392 klass = mono_class_from_typeref_checked (image, type_token, error);
7394 case MONO_TOKEN_TYPE_SPEC:
7395 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7398 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7402 /* Generic case, should be avoided for when a better error is possible. */
7403 if (!klass && mono_error_ok (error)) {
7404 char *name = mono_class_name_from_token (image, type_token);
7405 char *assembly = mono_assembly_name_from_token (image, type_token);
7406 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7414 * mono_type_get_checked:
7415 * @image: the image where the type resides
7416 * @type_token: the token for the type
7417 * @context: the generic context used to evaluate generic instantiations in
7418 * @error: Error handling context
7420 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7422 * Returns: The MonoType that represents @type_token in @image
7425 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7427 MonoType *type = NULL;
7428 gboolean inflated = FALSE;
7430 mono_error_init (error);
7432 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7433 if (image_is_dynamic (image)) {
7434 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7435 return_val_if_nok (error, NULL);
7436 return mono_class_get_type (klass);
7439 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7440 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7447 return mono_class_get_type (klass);
7450 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7457 MonoType *tmp = type;
7458 type = mono_class_get_type (mono_class_from_mono_type (type));
7459 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7460 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7461 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7463 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7465 if (type->type != tmp->type)
7468 mono_metadata_free_type (tmp);
7475 * @image: image where the class token will be looked up.
7476 * @type_token: a type token from the image
7478 * Returns the MonoClass with the given @type_token on the @image
7481 mono_class_get (MonoImage *image, guint32 type_token)
7483 return mono_class_get_full (image, type_token, NULL);
7487 * mono_image_init_name_cache:
7489 * Initializes the class name cache stored in image->name_cache.
7491 * LOCKING: Acquires the corresponding image lock.
7494 mono_image_init_name_cache (MonoImage *image)
7496 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7497 guint32 cols [MONO_TYPEDEF_SIZE];
7500 guint32 i, visib, nspace_index;
7501 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7503 if (image->name_cache)
7506 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7508 if (image_is_dynamic (image)) {
7509 mono_image_lock (image);
7510 if (image->name_cache) {
7511 /* Somebody initialized it before us */
7512 g_hash_table_destroy (the_name_cache);
7514 mono_atomic_store_release (&image->name_cache, the_name_cache);
7516 mono_image_unlock (image);
7520 /* Temporary hash table to avoid lookups in the nspace_table */
7521 name_cache2 = g_hash_table_new (NULL, NULL);
7523 for (i = 1; i <= t->rows; ++i) {
7524 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7525 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7527 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7528 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7530 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7532 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7533 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7535 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7536 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7537 if (!nspace_table) {
7538 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7539 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7540 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7543 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7546 /* Load type names from EXPORTEDTYPES table */
7548 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7549 guint32 cols [MONO_EXP_TYPE_SIZE];
7552 for (i = 0; i < t->rows; ++i) {
7553 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7555 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7556 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7560 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7561 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7563 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7564 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7565 if (!nspace_table) {
7566 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7567 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7568 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7571 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7575 g_hash_table_destroy (name_cache2);
7577 mono_image_lock (image);
7578 if (image->name_cache) {
7579 /* Somebody initialized it before us */
7580 g_hash_table_destroy (the_name_cache);
7582 mono_atomic_store_release (&image->name_cache, the_name_cache);
7584 mono_image_unlock (image);
7587 /*FIXME Only dynamic assemblies should allow this operation.*/
7589 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7590 const char *name, guint32 index)
7592 GHashTable *nspace_table;
7593 GHashTable *name_cache;
7596 mono_image_init_name_cache (image);
7597 mono_image_lock (image);
7599 name_cache = image->name_cache;
7600 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7601 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7602 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7605 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7606 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7608 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7610 mono_image_unlock (image);
7619 find_nocase (gpointer key, gpointer value, gpointer user_data)
7621 char *name = (char*)key;
7622 FindUserData *data = (FindUserData*)user_data;
7624 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7625 data->value = value;
7629 * mono_class_from_name_case:
7630 * @image: The MonoImage where the type is looked up in
7631 * @name_space: the type namespace
7632 * @name: the type short name.
7633 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7635 * Obtains a MonoClass with a given namespace and a given name which
7636 * is located in the given MonoImage. The namespace and name
7637 * lookups are case insensitive.
7640 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7643 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7644 mono_error_cleanup (&error);
7650 * mono_class_from_name_case:
7651 * @image: The MonoImage where the type is looked up in
7652 * @name_space: the type namespace
7653 * @name: the type short name.
7656 * Obtains a MonoClass with a given namespace and a given name which
7657 * is located in the given MonoImage. The namespace and name
7658 * lookups are case insensitive.
7660 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7661 * was not found. The @error object will contain information about the problem
7665 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7667 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7668 guint32 cols [MONO_TYPEDEF_SIZE];
7673 mono_error_init (error);
7675 if (image_is_dynamic (image)) {
7677 FindUserData user_data;
7679 mono_image_init_name_cache (image);
7680 mono_image_lock (image);
7682 user_data.key = name_space;
7683 user_data.value = NULL;
7684 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7686 if (user_data.value) {
7687 GHashTable *nspace_table = (GHashTable*)user_data.value;
7689 user_data.key = name;
7690 user_data.value = NULL;
7692 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7694 if (user_data.value)
7695 token = GPOINTER_TO_UINT (user_data.value);
7698 mono_image_unlock (image);
7701 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7707 /* add a cache if needed */
7708 for (i = 1; i <= t->rows; ++i) {
7709 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7710 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7712 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7713 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7715 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7717 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7718 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7719 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7720 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7726 return_nested_in (MonoClass *klass, char *nested)
7729 char *s = strchr (nested, '/');
7730 gpointer iter = NULL;
7737 while ((found = mono_class_get_nested_types (klass, &iter))) {
7738 if (strcmp (found->name, nested) == 0) {
7740 return return_nested_in (found, s);
7748 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7750 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7751 MonoImage *file_image;
7755 mono_error_init (error);
7758 * The EXPORTEDTYPES table only contains public types, so have to search the
7760 * Note: image->modules contains the contents of the MODULEREF table, while
7761 * the real module list is in the FILE table.
7763 for (i = 0; i < file_table->rows; i++) {
7764 guint32 cols [MONO_FILE_SIZE];
7765 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7766 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7769 file_image = mono_image_load_file_for_image (image, i + 1);
7771 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7772 if (klass || !is_ok (error))
7781 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7783 GHashTable *nspace_table;
7784 MonoImage *loaded_image;
7791 mono_error_init (error);
7793 // Checking visited images avoids stack overflows when cyclic references exist.
7794 if (g_hash_table_lookup (visited_images, image))
7797 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7799 if ((nested = strchr (name, '/'))) {
7800 int pos = nested - name;
7801 int len = strlen (name);
7804 memcpy (buf, name, len + 1);
7806 nested = buf + pos + 1;
7810 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7811 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7812 gboolean res = get_class_from_name (image, name_space, name, &klass);
7815 klass = search_modules (image, name_space, name, error);
7820 return klass ? return_nested_in (klass, nested) : NULL;
7826 mono_image_init_name_cache (image);
7827 mono_image_lock (image);
7829 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7832 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7834 mono_image_unlock (image);
7836 if (!token && image_is_dynamic (image) && image->modules) {
7837 /* Search modules as well */
7838 for (i = 0; i < image->module_count; ++i) {
7839 MonoImage *module = image->modules [i];
7841 klass = mono_class_from_name_checked (module, name_space, name, error);
7842 if (klass || !is_ok (error))
7848 klass = search_modules (image, name_space, name, error);
7849 if (klass || !is_ok (error))
7856 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7857 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7858 guint32 cols [MONO_EXP_TYPE_SIZE];
7861 idx = mono_metadata_token_index (token);
7863 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7865 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7866 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7867 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7870 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7872 return klass ? return_nested_in (klass, nested) : NULL;
7874 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7875 guint32 assembly_idx;
7877 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7879 mono_assembly_load_reference (image, assembly_idx - 1);
7880 g_assert (image->references [assembly_idx - 1]);
7881 if (image->references [assembly_idx - 1] == (gpointer)-1)
7883 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7885 return klass ? return_nested_in (klass, nested) : NULL;
7888 g_assert_not_reached ();
7892 token = MONO_TOKEN_TYPE_DEF | token;
7894 klass = mono_class_get_checked (image, token, error);
7896 return return_nested_in (klass, nested);
7901 * mono_class_from_name_checked:
7902 * @image: The MonoImage where the type is looked up in
7903 * @name_space: the type namespace
7904 * @name: the type short name.
7906 * Obtains a MonoClass with a given namespace and a given name which
7907 * is located in the given MonoImage.
7909 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7910 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7913 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7916 GHashTable *visited_images;
7918 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7920 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7922 g_hash_table_destroy (visited_images);
7928 * mono_class_from_name:
7929 * @image: The MonoImage where the type is looked up in
7930 * @name_space: the type namespace
7931 * @name: the type short name.
7933 * Obtains a MonoClass with a given namespace and a given name which
7934 * is located in the given MonoImage.
7936 * To reference nested classes, use the "/" character as a separator.
7937 * For example use "Foo/Bar" to reference the class Bar that is nested
7938 * inside Foo, like this: "class Foo { class Bar {} }".
7941 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7946 klass = mono_class_from_name_checked (image, name_space, name, &error);
7947 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7953 * mono_class_load_from_name:
7954 * @image: The MonoImage where the type is looked up in
7955 * @name_space: the type namespace
7956 * @name: the type short name.
7958 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7959 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7960 * If they are missing. Thing of System.Object or System.String.
7963 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7968 klass = mono_class_from_name_checked (image, name_space, name, &error);
7970 g_error ("Runtime critical type %s.%s not found", name_space, name);
7971 if (!mono_error_ok (&error))
7972 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7977 * mono_class_try_load_from_name:
7978 * @image: The MonoImage where the type is looked up in
7979 * @name_space: the type namespace
7980 * @name: the type short name.
7982 * This function tries to load a type, returning the class was found or NULL otherwise.
7983 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7985 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7986 * a type that we would otherwise assume to be available but was not due some error.
7990 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7995 klass = mono_class_from_name_checked (image, name_space, name, &error);
7996 if (!mono_error_ok (&error))
7997 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8003 * mono_class_is_subclass_of:
8004 * @klass: class to probe if it is a subclass of another one
8005 * @klassc: the class we suspect is the base class
8006 * @check_interfaces: whether we should perform interface checks
8008 * This method determines whether @klass is a subclass of @klassc.
8010 * If the @check_interfaces flag is set, then if @klassc is an interface
8011 * this method return TRUE if the @klass implements the interface or
8012 * if @klass is an interface, if one of its base classes is @klass.
8014 * If @check_interfaces is false then, then if @klass is not an interface
8015 * then it returns TRUE if the @klass is a subclass of @klassc.
8017 * if @klass is an interface and @klassc is System.Object, then this function
8022 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8023 gboolean check_interfaces)
8025 /* FIXME test for interfaces with variant generic arguments */
8026 mono_class_init (klass);
8027 mono_class_init (klassc);
8029 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8030 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8032 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8035 for (i = 0; i < klass->interface_count; i ++) {
8036 MonoClass *ic = klass->interfaces [i];
8041 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8046 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8049 if (klassc == mono_defaults.object_class)
8056 mono_type_is_generic_argument (MonoType *type)
8058 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8062 mono_class_has_variant_generic_params (MonoClass *klass)
8065 MonoGenericContainer *container;
8067 if (!klass->generic_class)
8070 container = klass->generic_class->container_class->generic_container;
8072 for (i = 0; i < container->type_argc; ++i)
8073 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8080 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8082 if (target == candidate)
8085 if (check_for_reference_conv &&
8086 mono_type_is_generic_argument (&target->byval_arg) &&
8087 mono_type_is_generic_argument (&candidate->byval_arg)) {
8088 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8089 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8091 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8094 if (!mono_class_is_assignable_from (target, candidate))
8100 * @container the generic container from the GTD
8101 * @klass: the class to be assigned to
8102 * @oklass: the source class
8104 * Both @klass and @oklass must be instances of the same generic interface.
8106 * Returns: TRUE if @klass can be assigned to a @klass variable
8109 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8112 MonoType **klass_argv, **oklass_argv;
8113 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8114 MonoGenericContainer *container = klass_gtd->generic_container;
8116 if (klass == oklass)
8119 /*Viable candidates are instances of the same generic interface*/
8120 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8123 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8124 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8126 for (j = 0; j < container->type_argc; ++j) {
8127 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8128 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8130 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8134 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8135 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8137 if (param1_class != param2_class) {
8138 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8139 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8141 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8142 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8152 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8154 MonoGenericParam *gparam, *ogparam;
8155 MonoGenericParamInfo *tinfo, *cinfo;
8156 MonoClass **candidate_class;
8157 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8160 if (target == candidate)
8162 if (target->byval_arg.type != candidate->byval_arg.type)
8165 gparam = target->byval_arg.data.generic_param;
8166 ogparam = candidate->byval_arg.data.generic_param;
8167 tinfo = mono_generic_param_info (gparam);
8168 cinfo = mono_generic_param_info (ogparam);
8170 class_constraint_satisfied = FALSE;
8171 valuetype_constraint_satisfied = FALSE;
8173 /*candidate must have a super set of target's special constraints*/
8174 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8175 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8177 if (cinfo->constraints) {
8178 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8179 MonoClass *cc = *candidate_class;
8181 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8182 class_constraint_satisfied = TRUE;
8183 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8184 valuetype_constraint_satisfied = TRUE;
8187 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8188 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8190 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8192 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8194 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8195 valuetype_constraint_satisfied)) {
8200 /*candidate type constraints must be a superset of target's*/
8201 if (tinfo->constraints) {
8202 MonoClass **target_class;
8203 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8204 MonoClass *tc = *target_class;
8207 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8208 * check it's constraints since it satisfy the constraint by itself.
8210 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8213 if (!cinfo->constraints)
8216 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8217 MonoClass *cc = *candidate_class;
8219 if (mono_class_is_assignable_from (tc, cc))
8223 * This happens when we have the following:
8225 * Bar<K> where K : IFace
8226 * Foo<T, U> where T : U where U : IFace
8228 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8231 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8232 if (mono_gparam_is_assignable_from (target, cc))
8236 if (!*candidate_class)
8241 /*candidate itself must have a constraint that satisfy target*/
8242 if (cinfo->constraints) {
8243 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8244 MonoClass *cc = *candidate_class;
8245 if (mono_class_is_assignable_from (target, cc))
8253 * mono_class_is_assignable_from:
8254 * @klass: the class to be assigned to
8255 * @oklass: the source class
8257 * Returns: TRUE if an instance of object oklass can be assigned to an
8258 * instance of object @klass
8261 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8264 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8266 mono_class_init (klass);
8268 if (!oklass->inited)
8269 mono_class_init (oklass);
8271 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8274 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8275 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8277 return mono_gparam_is_assignable_from (klass, oklass);
8280 if (MONO_CLASS_IS_INTERFACE (klass)) {
8281 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8282 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8283 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8287 for (i = 0; constraints [i]; ++i) {
8288 if (mono_class_is_assignable_from (klass, constraints [i]))
8296 /* interface_offsets might not be set for dynamic classes */
8297 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8299 * oklass might be a generic type parameter but they have
8300 * interface_offsets set.
8302 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8303 if (!is_ok (&error)) {
8304 mono_error_cleanup (&error);
8309 if (!oklass->interface_bitmap)
8310 /* Happens with generic instances of not-yet created dynamic types */
8312 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8315 if (mono_class_has_variant_generic_params (klass)) {
8317 mono_class_setup_interfaces (oklass, &error);
8318 if (!mono_error_ok (&error)) {
8319 mono_error_cleanup (&error);
8323 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8324 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8325 MonoClass *iface = oklass->interfaces_packed [i];
8327 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8332 } else if (klass->delegate) {
8333 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8335 }else if (klass->rank) {
8336 MonoClass *eclass, *eoclass;
8338 if (oklass->rank != klass->rank)
8341 /* vectors vs. one dimensional arrays */
8342 if (oklass->byval_arg.type != klass->byval_arg.type)
8345 eclass = klass->cast_class;
8346 eoclass = oklass->cast_class;
8349 * a is b does not imply a[] is b[] when a is a valuetype, and
8350 * b is a reference type.
8353 if (eoclass->valuetype) {
8354 if ((eclass == mono_defaults.enum_class) ||
8355 (eclass == mono_defaults.enum_class->parent) ||
8356 (eclass == mono_defaults.object_class))
8360 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8361 } else if (mono_class_is_nullable (klass)) {
8362 if (mono_class_is_nullable (oklass))
8363 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8365 return mono_class_is_assignable_from (klass->cast_class, oklass);
8366 } else if (klass == mono_defaults.object_class)
8369 return mono_class_has_parent (oklass, klass);
8372 /*Check if @oklass is variant compatible with @klass.*/
8374 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8377 MonoType **klass_argv, **oklass_argv;
8378 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8379 MonoGenericContainer *container = klass_gtd->generic_container;
8381 /*Viable candidates are instances of the same generic interface*/
8382 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8385 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8386 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8388 for (j = 0; j < container->type_argc; ++j) {
8389 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8390 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8392 if (param1_class->valuetype != param2_class->valuetype)
8396 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8397 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8399 if (param1_class != param2_class) {
8400 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8401 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8403 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8404 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8412 /*Check if @candidate implements the interface @target*/
8414 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8418 gboolean is_variant = mono_class_has_variant_generic_params (target);
8420 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8421 if (mono_class_is_variant_compatible_slow (target, candidate))
8426 if (candidate == target)
8429 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8430 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8431 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8433 if (tb && tb->interfaces) {
8434 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8435 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8436 MonoClass *iface_class;
8438 /* we can't realize the type here since it can do pretty much anything. */
8441 iface_class = mono_class_from_mono_type (iface->type);
8442 if (iface_class == target)
8444 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8446 if (mono_class_implement_interface_slow (target, iface_class))
8451 /*setup_interfaces don't mono_class_init anything*/
8452 /*FIXME this doesn't handle primitive type arrays.
8453 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8454 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8456 mono_class_setup_interfaces (candidate, &error);
8457 if (!mono_error_ok (&error)) {
8458 mono_error_cleanup (&error);
8462 for (i = 0; i < candidate->interface_count; ++i) {
8463 if (candidate->interfaces [i] == target)
8466 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8469 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8473 candidate = candidate->parent;
8474 } while (candidate);
8480 * Check if @oklass can be assigned to @klass.
8481 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8484 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8486 if (candidate == target)
8488 if (target == mono_defaults.object_class)
8491 if (mono_class_has_parent (candidate, target))
8494 /*If target is not an interface there is no need to check them.*/
8495 if (MONO_CLASS_IS_INTERFACE (target))
8496 return mono_class_implement_interface_slow (target, candidate);
8498 if (target->delegate && mono_class_has_variant_generic_params (target))
8499 return mono_class_is_variant_compatible (target, candidate, FALSE);
8502 MonoClass *eclass, *eoclass;
8504 if (target->rank != candidate->rank)
8507 /* vectors vs. one dimensional arrays */
8508 if (target->byval_arg.type != candidate->byval_arg.type)
8511 eclass = target->cast_class;
8512 eoclass = candidate->cast_class;
8515 * a is b does not imply a[] is b[] when a is a valuetype, and
8516 * b is a reference type.
8519 if (eoclass->valuetype) {
8520 if ((eclass == mono_defaults.enum_class) ||
8521 (eclass == mono_defaults.enum_class->parent) ||
8522 (eclass == mono_defaults.object_class))
8526 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8528 /*FIXME properly handle nullables */
8529 /*FIXME properly handle (M)VAR */
8534 * mono_class_get_cctor:
8535 * @klass: A MonoClass pointer
8537 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8540 mono_class_get_cctor (MonoClass *klass)
8542 MonoCachedClassInfo cached_info;
8544 if (image_is_dynamic (klass->image)) {
8546 * has_cctor is not set for these classes because mono_class_init () is
8549 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8552 if (!klass->has_cctor)
8555 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8557 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8558 if (!mono_error_ok (&error))
8559 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8563 if (klass->generic_class && !klass->methods)
8564 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8566 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8570 * mono_class_get_finalizer:
8571 * @klass: The MonoClass pointer
8573 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8576 mono_class_get_finalizer (MonoClass *klass)
8578 MonoCachedClassInfo cached_info;
8581 mono_class_init (klass);
8582 if (!mono_class_has_finalizer (klass))
8585 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8587 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8588 if (!mono_error_ok (&error))
8589 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8592 mono_class_setup_vtable (klass);
8593 return klass->vtable [finalize_slot];
8598 * mono_class_needs_cctor_run:
8599 * @klass: the MonoClass pointer
8600 * @caller: a MonoMethod describing the caller
8602 * Determines whenever the class has a static constructor and whenever it
8603 * needs to be called when executing CALLER.
8606 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8610 method = mono_class_get_cctor (klass);
8612 return (method == caller) ? FALSE : TRUE;
8618 * mono_class_array_element_size:
8621 * Returns: The number of bytes an element of type @klass
8622 * uses when stored into an array.
8625 mono_class_array_element_size (MonoClass *klass)
8627 MonoType *type = &klass->byval_arg;
8630 switch (type->type) {
8633 case MONO_TYPE_BOOLEAN:
8637 case MONO_TYPE_CHAR:
8646 case MONO_TYPE_CLASS:
8647 case MONO_TYPE_STRING:
8648 case MONO_TYPE_OBJECT:
8649 case MONO_TYPE_SZARRAY:
8650 case MONO_TYPE_ARRAY:
8651 return sizeof (gpointer);
8656 case MONO_TYPE_VALUETYPE:
8657 if (type->data.klass->enumtype) {
8658 type = mono_class_enum_basetype (type->data.klass);
8659 klass = klass->element_class;
8662 return mono_class_instance_size (klass) - sizeof (MonoObject);
8663 case MONO_TYPE_GENERICINST:
8664 type = &type->data.generic_class->container_class->byval_arg;
8667 case MONO_TYPE_MVAR: {
8670 return mono_type_size (type, &align);
8672 case MONO_TYPE_VOID:
8676 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8682 * mono_array_element_size:
8683 * @ac: pointer to a #MonoArrayClass
8685 * Returns: The size of single array element.
8688 mono_array_element_size (MonoClass *ac)
8690 g_assert (ac->rank);
8691 return ac->sizes.element_size;
8695 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8696 MonoGenericContext *context)
8699 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8700 g_assert (mono_error_ok (&error));
8705 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8706 MonoGenericContext *context, MonoError *error)
8708 mono_error_init (error);
8710 if (image_is_dynamic (image)) {
8711 MonoClass *tmp_handle_class;
8712 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8714 mono_error_assert_ok (error);
8715 g_assert (tmp_handle_class);
8717 *handle_class = tmp_handle_class;
8719 if (tmp_handle_class == mono_defaults.typehandle_class)
8720 return &((MonoClass*)obj)->byval_arg;
8725 switch (token & 0xff000000) {
8726 case MONO_TOKEN_TYPE_DEF:
8727 case MONO_TOKEN_TYPE_REF:
8728 case MONO_TOKEN_TYPE_SPEC: {
8731 *handle_class = mono_defaults.typehandle_class;
8732 type = mono_type_get_checked (image, token, context, error);
8736 mono_class_init (mono_class_from_mono_type (type));
8737 /* We return a MonoType* as handle */
8740 case MONO_TOKEN_FIELD_DEF: {
8742 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8744 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8748 *handle_class = mono_defaults.fieldhandle_class;
8749 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8753 mono_class_init (klass);
8754 return mono_class_get_field (klass, token);
8756 case MONO_TOKEN_METHOD_DEF:
8757 case MONO_TOKEN_METHOD_SPEC: {
8759 meth = mono_get_method_checked (image, token, NULL, context, error);
8761 *handle_class = mono_defaults.methodhandle_class;
8767 case MONO_TOKEN_MEMBER_REF: {
8768 guint32 cols [MONO_MEMBERREF_SIZE];
8770 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8771 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8772 mono_metadata_decode_blob_size (sig, &sig);
8773 if (*sig == 0x6) { /* it's a field */
8775 MonoClassField *field;
8776 field = mono_field_from_token_checked (image, token, &klass, context, error);
8778 *handle_class = mono_defaults.fieldhandle_class;
8782 meth = mono_get_method_checked (image, token, NULL, context, error);
8784 *handle_class = mono_defaults.methodhandle_class;
8789 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8795 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8797 MonoClass *handle_class;
8798 mono_error_init (error);
8799 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8803 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8805 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8808 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8811 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8813 get_cached_class_info = func;
8817 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8819 if (!get_cached_class_info)
8822 return get_cached_class_info (klass, res);
8826 mono_install_get_class_from_name (MonoGetClassFromName func)
8828 get_class_from_name = func;
8832 * mono_class_get_image:
8834 * Use this method to get the `MonoImage*` where this class came from.
8836 * Returns: The image where this class is defined.
8839 mono_class_get_image (MonoClass *klass)
8841 return klass->image;
8845 * mono_class_get_element_class:
8846 * @klass: the MonoClass to act on
8848 * Use this function to get the element class of an array.
8850 * Returns: The element class of an array.
8853 mono_class_get_element_class (MonoClass *klass)
8855 return klass->element_class;
8859 * mono_class_is_valuetype:
8860 * @klass: the MonoClass to act on
8862 * Use this method to determine if the provided `MonoClass*` represents a value type,
8863 * or a reference type.
8865 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8868 mono_class_is_valuetype (MonoClass *klass)
8870 return klass->valuetype;
8874 * mono_class_is_enum:
8875 * @klass: the MonoClass to act on
8877 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8879 * Returns: TRUE if the MonoClass represents an enumeration.
8882 mono_class_is_enum (MonoClass *klass)
8884 return klass->enumtype;
8888 * mono_class_enum_basetype:
8889 * @klass: the MonoClass to act on
8891 * Use this function to get the underlying type for an enumeration value.
8893 * Returns: The underlying type representation for an enumeration.
8896 mono_class_enum_basetype (MonoClass *klass)
8898 if (klass->element_class == klass)
8899 /* SRE or broken types */
8902 return &klass->element_class->byval_arg;
8906 * mono_class_get_parent
8907 * @klass: the MonoClass to act on
8909 * Returns: The parent class for this class.
8912 mono_class_get_parent (MonoClass *klass)
8914 return klass->parent;
8918 * mono_class_get_nesting_type:
8919 * @klass: the MonoClass to act on
8921 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8923 * If the return is NULL, this indicates that this class is not nested.
8925 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8928 mono_class_get_nesting_type (MonoClass *klass)
8930 return klass->nested_in;
8934 * mono_class_get_rank:
8935 * @klass: the MonoClass to act on
8937 * Returns: The rank for the array (the number of dimensions).
8940 mono_class_get_rank (MonoClass *klass)
8946 * mono_class_get_flags:
8947 * @klass: the MonoClass to act on
8949 * The type flags from the TypeDef table from the metadata.
8950 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8953 * Returns: The flags from the TypeDef table.
8956 mono_class_get_flags (MonoClass *klass)
8958 return klass->flags;
8962 * mono_class_get_name
8963 * @klass: the MonoClass to act on
8965 * Returns: The name of the class.
8968 mono_class_get_name (MonoClass *klass)
8974 * mono_class_get_namespace:
8975 * @klass: the MonoClass to act on
8977 * Returns: The namespace of the class.
8980 mono_class_get_namespace (MonoClass *klass)
8982 return klass->name_space;
8986 * mono_class_get_type:
8987 * @klass: the MonoClass to act on
8989 * This method returns the internal Type representation for the class.
8991 * Returns: The MonoType from the class.
8994 mono_class_get_type (MonoClass *klass)
8996 return &klass->byval_arg;
9000 * mono_class_get_type_token:
9001 * @klass: the MonoClass to act on
9003 * This method returns type token for the class.
9005 * Returns: The type token for the class.
9008 mono_class_get_type_token (MonoClass *klass)
9010 return klass->type_token;
9014 * mono_class_get_byref_type:
9015 * @klass: the MonoClass to act on
9020 mono_class_get_byref_type (MonoClass *klass)
9022 return &klass->this_arg;
9026 * mono_class_num_fields:
9027 * @klass: the MonoClass to act on
9029 * Returns: The number of static and instance fields in the class.
9032 mono_class_num_fields (MonoClass *klass)
9034 return klass->field.count;
9038 * mono_class_num_methods:
9039 * @klass: the MonoClass to act on
9041 * Returns: The number of methods in the class.
9044 mono_class_num_methods (MonoClass *klass)
9046 return klass->method.count;
9050 * mono_class_num_properties
9051 * @klass: the MonoClass to act on
9053 * Returns: The number of properties in the class.
9056 mono_class_num_properties (MonoClass *klass)
9058 mono_class_setup_properties (klass);
9060 return klass->ext->property.count;
9064 * mono_class_num_events:
9065 * @klass: the MonoClass to act on
9067 * Returns: The number of events in the class.
9070 mono_class_num_events (MonoClass *klass)
9072 mono_class_setup_events (klass);
9074 return klass->ext->event.count;
9078 * mono_class_get_fields:
9079 * @klass: the MonoClass to act on
9081 * This routine is an iterator routine for retrieving the fields in a class.
9083 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9084 * iterate over all of the elements. When no more values are
9085 * available, the return value is NULL.
9087 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9090 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9092 MonoClassField* field;
9096 mono_class_setup_fields_locking (klass);
9097 if (mono_class_has_failure (klass))
9099 /* start from the first */
9100 if (klass->field.count) {
9101 *iter = &klass->fields [0];
9102 return &klass->fields [0];
9108 field = (MonoClassField *)*iter;
9110 if (field < &klass->fields [klass->field.count]) {
9118 * mono_class_get_methods
9119 * @klass: the MonoClass to act on
9121 * This routine is an iterator routine for retrieving the fields in a class.
9123 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9124 * iterate over all of the elements. When no more values are
9125 * available, the return value is NULL.
9127 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9130 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9132 MonoMethod** method;
9136 mono_class_setup_methods (klass);
9139 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9140 * FIXME we should better report this error to the caller
9142 if (!klass->methods)
9144 /* start from the first */
9145 if (klass->method.count) {
9146 *iter = &klass->methods [0];
9147 return klass->methods [0];
9153 method = (MonoMethod **)*iter;
9155 if (method < &klass->methods [klass->method.count]) {
9163 * mono_class_get_virtual_methods:
9165 * Iterate over the virtual methods of KLASS.
9167 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9170 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9172 MonoMethod** method;
9175 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9177 mono_class_setup_methods (klass);
9179 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9180 * FIXME we should better report this error to the caller
9182 if (!klass->methods)
9184 /* start from the first */
9185 method = &klass->methods [0];
9187 method = (MonoMethod **)*iter;
9190 while (method < &klass->methods [klass->method.count]) {
9191 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9195 if (method < &klass->methods [klass->method.count]) {
9202 /* Search directly in metadata to avoid calling setup_methods () */
9203 MonoMethod *res = NULL;
9209 start_index = GPOINTER_TO_UINT (*iter);
9212 for (i = start_index; i < klass->method.count; ++i) {
9215 /* klass->method.first points into the methodptr table */
9216 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9218 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9222 if (i < klass->method.count) {
9224 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9225 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9227 /* Add 1 here so the if (*iter) check fails */
9228 *iter = GUINT_TO_POINTER (i + 1);
9237 * mono_class_get_properties:
9238 * @klass: the MonoClass to act on
9240 * This routine is an iterator routine for retrieving the properties in a class.
9242 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9243 * iterate over all of the elements. When no more values are
9244 * available, the return value is NULL.
9246 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9249 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9251 MonoProperty* property;
9255 mono_class_setup_properties (klass);
9256 /* start from the first */
9257 if (klass->ext->property.count) {
9258 *iter = &klass->ext->properties [0];
9259 return (MonoProperty *)*iter;
9265 property = (MonoProperty *)*iter;
9267 if (property < &klass->ext->properties [klass->ext->property.count]) {
9269 return (MonoProperty *)*iter;
9275 * mono_class_get_events:
9276 * @klass: the MonoClass to act on
9278 * This routine is an iterator routine for retrieving the properties in a class.
9280 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9281 * iterate over all of the elements. When no more values are
9282 * available, the return value is NULL.
9284 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9287 mono_class_get_events (MonoClass* klass, gpointer *iter)
9293 mono_class_setup_events (klass);
9294 /* start from the first */
9295 if (klass->ext->event.count) {
9296 *iter = &klass->ext->events [0];
9297 return (MonoEvent *)*iter;
9303 event = (MonoEvent *)*iter;
9305 if (event < &klass->ext->events [klass->ext->event.count]) {
9307 return (MonoEvent *)*iter;
9313 * mono_class_get_interfaces
9314 * @klass: the MonoClass to act on
9316 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9318 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9319 * iterate over all of the elements. When no more values are
9320 * available, the return value is NULL.
9322 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9325 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9333 mono_class_init (klass);
9334 if (!klass->interfaces_inited) {
9335 mono_class_setup_interfaces (klass, &error);
9336 if (!mono_error_ok (&error)) {
9337 mono_error_cleanup (&error);
9341 /* start from the first */
9342 if (klass->interface_count) {
9343 *iter = &klass->interfaces [0];
9344 return klass->interfaces [0];
9350 iface = (MonoClass **)*iter;
9352 if (iface < &klass->interfaces [klass->interface_count]) {
9360 setup_nested_types (MonoClass *klass)
9363 GList *classes, *nested_classes, *l;
9366 if (klass->nested_classes_inited)
9369 if (!klass->type_token)
9370 klass->nested_classes_inited = TRUE;
9372 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9376 guint32 cols [MONO_NESTED_CLASS_SIZE];
9377 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9378 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9379 if (!mono_error_ok (&error)) {
9380 /*FIXME don't swallow the error message*/
9381 mono_error_cleanup (&error);
9383 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9387 classes = g_list_prepend (classes, nclass);
9389 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9392 mono_class_alloc_ext (klass);
9394 nested_classes = NULL;
9395 for (l = classes; l; l = l->next)
9396 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9397 g_list_free (classes);
9399 mono_image_lock (klass->image);
9401 mono_memory_barrier ();
9402 if (!klass->nested_classes_inited) {
9403 klass->ext->nested_classes = nested_classes;
9404 mono_memory_barrier ();
9405 klass->nested_classes_inited = TRUE;
9408 mono_image_unlock (klass->image);
9412 * mono_class_get_nested_types
9413 * @klass: the MonoClass to act on
9415 * This routine is an iterator routine for retrieving the nested types of a class.
9416 * This works only if @klass is non-generic, or a generic type definition.
9418 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9419 * iterate over all of the elements. When no more values are
9420 * available, the return value is NULL.
9422 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9425 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9431 if (!klass->nested_classes_inited)
9432 setup_nested_types (klass);
9435 /* start from the first */
9436 if (klass->ext && klass->ext->nested_classes) {
9437 *iter = klass->ext->nested_classes;
9438 return (MonoClass *)klass->ext->nested_classes->data;
9440 /* no nested types */
9444 item = (GList *)*iter;
9448 return (MonoClass *)item->data;
9455 * mono_class_is_delegate
9456 * @klass: the MonoClass to act on
9458 * Returns: TRUE if the MonoClass represents a System.Delegate.
9461 mono_class_is_delegate (MonoClass *klass)
9463 return klass->delegate;
9467 * mono_class_implements_interface
9468 * @klass: The MonoClass to act on
9469 * @interface: The interface to check if @klass implements.
9471 * Returns: TRUE if @klass implements @interface.
9474 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9476 return mono_class_is_assignable_from (iface, klass);
9480 * mono_field_get_name:
9481 * @field: the MonoClassField to act on
9483 * Returns: The name of the field.
9486 mono_field_get_name (MonoClassField *field)
9492 * mono_field_get_type:
9493 * @field: the MonoClassField to act on
9495 * Returns: MonoType of the field.
9498 mono_field_get_type (MonoClassField *field)
9501 MonoType *type = mono_field_get_type_checked (field, &error);
9502 if (!mono_error_ok (&error)) {
9503 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9504 mono_error_cleanup (&error);
9511 * mono_field_get_type_checked:
9512 * @field: the MonoClassField to act on
9513 * @error: used to return any erro found while retrieving @field type
9515 * Returns: MonoType of the field.
9518 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9520 mono_error_init (error);
9522 mono_field_resolve_type (field, error);
9527 * mono_field_get_parent:
9528 * @field: the MonoClassField to act on
9530 * Returns: MonoClass where the field was defined.
9533 mono_field_get_parent (MonoClassField *field)
9535 return field->parent;
9539 * mono_field_get_flags;
9540 * @field: the MonoClassField to act on
9542 * The metadata flags for a field are encoded using the
9543 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9545 * Returns: The flags for the field.
9548 mono_field_get_flags (MonoClassField *field)
9551 return mono_field_resolve_flags (field);
9552 return field->type->attrs;
9556 * mono_field_get_offset:
9557 * @field: the MonoClassField to act on
9559 * Returns: The field offset.
9562 mono_field_get_offset (MonoClassField *field)
9564 return field->offset;
9568 mono_field_get_rva (MonoClassField *field)
9572 MonoClass *klass = field->parent;
9573 MonoFieldDefaultValue *field_def_values;
9575 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9577 if (!klass->ext || !klass->ext->field_def_values) {
9578 mono_class_alloc_ext (klass);
9580 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9582 mono_image_lock (klass->image);
9583 if (!klass->ext->field_def_values)
9584 klass->ext->field_def_values = field_def_values;
9585 mono_image_unlock (klass->image);
9588 field_index = mono_field_get_index (field);
9590 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9591 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9593 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9594 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9597 return klass->ext->field_def_values [field_index].data;
9601 * mono_field_get_data:
9602 * @field: the MonoClassField to act on
9604 * Returns: A pointer to the metadata constant value or to the field
9605 * data if it has an RVA flag.
9608 mono_field_get_data (MonoClassField *field)
9610 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9611 MonoTypeEnum def_type;
9613 return mono_class_get_field_default_value (field, &def_type);
9614 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9615 return mono_field_get_rva (field);
9622 * mono_property_get_name:
9623 * @prop: the MonoProperty to act on
9625 * Returns: The name of the property
9628 mono_property_get_name (MonoProperty *prop)
9634 * mono_property_get_set_method
9635 * @prop: the MonoProperty to act on.
9637 * Returns: The setter method of the property (A MonoMethod)
9640 mono_property_get_set_method (MonoProperty *prop)
9646 * mono_property_get_get_method
9647 * @prop: the MonoProperty to act on.
9649 * Returns: The setter method of the property (A MonoMethod)
9652 mono_property_get_get_method (MonoProperty *prop)
9658 * mono_property_get_parent:
9659 * @prop: the MonoProperty to act on.
9661 * Returns: The MonoClass where the property was defined.
9664 mono_property_get_parent (MonoProperty *prop)
9666 return prop->parent;
9670 * mono_property_get_flags:
9671 * @prop: the MonoProperty to act on.
9673 * The metadata flags for a property are encoded using the
9674 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9676 * Returns: The flags for the property.
9679 mono_property_get_flags (MonoProperty *prop)
9685 * mono_event_get_name:
9686 * @event: the MonoEvent to act on
9688 * Returns: The name of the event.
9691 mono_event_get_name (MonoEvent *event)
9697 * mono_event_get_add_method:
9698 * @event: The MonoEvent to act on.
9700 * Returns: The @add' method for the event (a MonoMethod).
9703 mono_event_get_add_method (MonoEvent *event)
9709 * mono_event_get_remove_method:
9710 * @event: The MonoEvent to act on.
9712 * Returns: The @remove method for the event (a MonoMethod).
9715 mono_event_get_remove_method (MonoEvent *event)
9717 return event->remove;
9721 * mono_event_get_raise_method:
9722 * @event: The MonoEvent to act on.
9724 * Returns: The @raise method for the event (a MonoMethod).
9727 mono_event_get_raise_method (MonoEvent *event)
9729 return event->raise;
9733 * mono_event_get_parent:
9734 * @event: the MonoEvent to act on.
9736 * Returns: The MonoClass where the event is defined.
9739 mono_event_get_parent (MonoEvent *event)
9741 return event->parent;
9745 * mono_event_get_flags
9746 * @event: the MonoEvent to act on.
9748 * The metadata flags for an event are encoded using the
9749 * EVENT_* constants. See the tabledefs.h file for details.
9751 * Returns: The flags for the event.
9754 mono_event_get_flags (MonoEvent *event)
9756 return event->attrs;
9760 * mono_class_get_method_from_name:
9761 * @klass: where to look for the method
9762 * @name: name of the method
9763 * @param_count: number of parameters. -1 for any number.
9765 * Obtains a MonoMethod with a given name and number of parameters.
9766 * It only works if there are no multiple signatures for any given method name.
9769 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9771 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9775 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9777 MonoMethod *res = NULL;
9780 /* Search directly in the metadata to avoid calling setup_methods () */
9781 for (i = 0; i < klass->method.count; ++i) {
9783 guint32 cols [MONO_METHOD_SIZE];
9785 MonoMethodSignature *sig;
9787 /* klass->method.first points into the methodptr table */
9788 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9790 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9791 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9793 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9796 if (param_count == -1) {
9800 sig = mono_method_signature_checked (method, &error);
9802 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9805 if (sig->param_count == param_count) {
9816 * mono_class_get_method_from_name_flags:
9817 * @klass: where to look for the method
9818 * @name_space: name of the method
9819 * @param_count: number of parameters. -1 for any number.
9820 * @flags: flags which must be set in the method
9822 * Obtains a MonoMethod with a given name and number of parameters.
9823 * It only works if there are no multiple signatures for any given method name.
9826 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9828 MonoMethod *res = NULL;
9831 mono_class_init (klass);
9833 if (klass->generic_class && !klass->methods) {
9834 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9837 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9838 if (!mono_error_ok (&error))
9839 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9844 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9845 mono_class_setup_methods (klass);
9847 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9848 See mono/tests/array_load_exception.il
9849 FIXME we should better report this error to the caller
9851 if (!klass->methods)
9853 for (i = 0; i < klass->method.count; ++i) {
9854 MonoMethod *method = klass->methods [i];
9856 if (method->name[0] == name [0] &&
9857 !strcmp (name, method->name) &&
9858 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9859 ((method->flags & flags) == flags)) {
9866 res = find_method_in_metadata (klass, name, param_count, flags);
9873 * mono_class_set_failure:
9874 * @klass: class in which the failure was detected
9875 * @ex_type: the kind of exception/error to be thrown (later)
9876 * @ex_data: exception data (specific to each type of exception/error)
9878 * Keep a detected failure informations in the class for later processing.
9879 * Note that only the first failure is kept.
9881 * LOCKING: Acquires the loader lock.
9884 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9886 if (mono_class_has_failure (klass))
9889 mono_loader_lock ();
9890 klass->exception_type = ex_type;
9892 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9893 mono_loader_unlock ();
9899 * mono_class_get_exception_data:
9901 * Return the exception_data property of KLASS.
9903 * LOCKING: Acquires the loader lock.
9906 mono_class_get_exception_data (MonoClass *klass)
9908 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9912 * mono_classes_init:
9914 * Initialize the resources used by this module.
9917 mono_classes_init (void)
9919 mono_os_mutex_init (&classes_mutex);
9921 mono_counters_register ("Inflated methods size",
9922 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9923 mono_counters_register ("Inflated classes",
9924 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9925 mono_counters_register ("Inflated classes size",
9926 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9927 mono_counters_register ("MonoClass size",
9928 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9929 mono_counters_register ("MonoClassExt size",
9930 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9934 * mono_classes_cleanup:
9936 * Free the resources used by this module.
9939 mono_classes_cleanup (void)
9941 if (global_interface_bitset)
9942 mono_bitset_free (global_interface_bitset);
9943 global_interface_bitset = NULL;
9944 mono_os_mutex_destroy (&classes_mutex);
9948 * mono_class_get_exception_for_failure:
9949 * @klass: class in which the failure was detected
9951 * Return a constructed MonoException than the caller can then throw
9952 * using mono_raise_exception - or NULL if no failure is present (or
9953 * doesn't result in an exception).
9956 mono_class_get_exception_for_failure (MonoClass *klass)
9958 gpointer exception_data = mono_class_get_exception_data (klass);
9960 switch (mono_class_get_failure(klass)) {
9961 case MONO_EXCEPTION_TYPE_LOAD: {
9964 char *str = mono_type_get_full_name (klass);
9965 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9966 name = mono_string_new (mono_domain_get (), str);
9968 ex = mono_get_exception_type_load (name, astr);
9972 case MONO_EXCEPTION_MISSING_METHOD: {
9973 char *class_name = (char *)exception_data;
9974 char *assembly_name = class_name + strlen (class_name) + 1;
9976 return mono_get_exception_missing_method (class_name, assembly_name);
9978 case MONO_EXCEPTION_MISSING_FIELD: {
9979 char *class_name = (char *)exception_data;
9980 char *member_name = class_name + strlen (class_name) + 1;
9982 return mono_get_exception_missing_field (class_name, member_name);
9984 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9985 char *msg_format = (char *)exception_data;
9986 char *assembly_name = msg_format + strlen (msg_format) + 1;
9987 char *msg = g_strdup_printf (msg_format, assembly_name);
9990 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9996 case MONO_EXCEPTION_BAD_IMAGE: {
9997 return mono_get_exception_bad_image_format ((const char *)exception_data);
9999 case MONO_EXCEPTION_INVALID_PROGRAM: {
10000 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10003 /* TODO - handle other class related failures */
10004 return mono_get_exception_execution_engine ("Unknown class failure");
10010 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10012 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10013 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10015 if (outer_klass == inner_klass)
10017 inner_klass = inner_klass->nested_in;
10018 } while (inner_klass);
10023 mono_class_get_generic_type_definition (MonoClass *klass)
10025 return klass->generic_class ? klass->generic_class->container_class : klass;
10029 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10031 * Generic instantiations are ignored for all super types of @klass.
10033 * Visibility checks ignoring generic instantiations.
10036 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10039 klass = mono_class_get_generic_type_definition (klass);
10040 parent = mono_class_get_generic_type_definition (parent);
10041 mono_class_setup_supertypes (klass);
10043 for (i = 0; i < klass->idepth; ++i) {
10044 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10050 * Subtype can only access parent members with family protection if the site object
10051 * is subclass of Subtype. For example:
10052 * class A { protected int x; }
10054 * void valid_access () {
10058 * void invalid_access () {
10065 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10067 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10070 if (context_klass == NULL)
10072 /*if access_klass is not member_klass context_klass must be type compat*/
10073 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10079 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10082 if (accessing == accessed)
10084 if (!accessed || !accessing)
10087 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10088 * anywhere so untrusted friends are not safe to access platform's code internals */
10089 if (mono_security_core_clr_enabled ()) {
10090 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10094 mono_assembly_load_friends (accessed);
10095 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10096 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10097 /* Be conservative with checks */
10098 if (!friend_->name)
10100 if (strcmp (accessing->aname.name, friend_->name))
10102 if (friend_->public_key_token [0]) {
10103 if (!accessing->aname.public_key_token [0])
10105 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10114 * If klass is a generic type or if it is derived from a generic type, return the
10115 * MonoClass of the generic definition
10116 * Returns NULL if not found
10119 get_generic_definition_class (MonoClass *klass)
10122 if (klass->generic_class && klass->generic_class->container_class)
10123 return klass->generic_class->container_class;
10124 klass = klass->parent;
10130 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10133 for (i = 0; i < ginst->type_argc; ++i) {
10134 MonoType *type = ginst->type_argv[i];
10135 switch (type->type) {
10136 case MONO_TYPE_SZARRAY:
10137 if (!can_access_type (access_klass, type->data.klass))
10140 case MONO_TYPE_ARRAY:
10141 if (!can_access_type (access_klass, type->data.array->eklass))
10144 case MONO_TYPE_PTR:
10145 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10148 case MONO_TYPE_CLASS:
10149 case MONO_TYPE_VALUETYPE:
10150 case MONO_TYPE_GENERICINST:
10151 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10161 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10165 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10168 if (access_klass->element_class && !access_klass->enumtype)
10169 access_klass = access_klass->element_class;
10171 if (member_klass->element_class && !member_klass->enumtype)
10172 member_klass = member_klass->element_class;
10174 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10176 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10179 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10182 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10185 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10188 /*Non nested type with nested visibility. We just fail it.*/
10189 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10192 switch (access_level) {
10193 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10194 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10196 case TYPE_ATTRIBUTE_PUBLIC:
10199 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10202 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10203 return is_nesting_type (member_klass, access_klass);
10205 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10206 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10208 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10209 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10211 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10212 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10213 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10215 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10216 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10217 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10222 /* FIXME: check visibility of type, too */
10224 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10226 MonoClass *member_generic_def;
10227 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10230 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10231 access_klass->generic_container) &&
10232 (member_generic_def = get_generic_definition_class (member_klass))) {
10233 MonoClass *access_container;
10235 if (access_klass->generic_container)
10236 access_container = access_klass;
10238 access_container = access_klass->generic_class->container_class;
10240 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10244 /* Partition I 8.5.3.2 */
10245 /* the access level values are the same for fields and methods */
10246 switch (access_level) {
10247 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10248 /* same compilation unit */
10249 return access_klass->image == member_klass->image;
10250 case FIELD_ATTRIBUTE_PRIVATE:
10251 return access_klass == member_klass;
10252 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10253 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10254 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10257 case FIELD_ATTRIBUTE_ASSEMBLY:
10258 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10259 case FIELD_ATTRIBUTE_FAMILY:
10260 if (is_valid_family_access (access_klass, member_klass, context_klass))
10263 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10264 if (is_valid_family_access (access_klass, member_klass, context_klass))
10266 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10267 case FIELD_ATTRIBUTE_PUBLIC:
10274 * mono_method_can_access_field:
10275 * @method: Method that will attempt to access the field
10276 * @field: the field to access
10278 * Used to determine if a method is allowed to access the specified field.
10280 * Returns: TRUE if the given @method is allowed to access the @field while following
10281 * the accessibility rules of the CLI.
10284 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10286 /* FIXME: check all overlapping fields */
10287 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10289 MonoClass *nested = method->klass->nested_in;
10291 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10294 nested = nested->nested_in;
10301 * mono_method_can_access_method:
10302 * @method: Method that will attempt to access the other method
10303 * @called: the method that we want to probe for accessibility.
10305 * Used to determine if the @method is allowed to access the specified @called method.
10307 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10308 * the accessibility rules of the CLI.
10311 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10313 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10315 MonoClass *nested = method->klass->nested_in;
10317 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10320 nested = nested->nested_in;
10325 * with generics calls to explicit interface implementations can be expressed
10326 * directly: the method is private, but we must allow it. This may be opening
10327 * a hole or the generics code should handle this differently.
10328 * Maybe just ensure the interface type is public.
10330 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10336 * mono_method_can_access_method_full:
10337 * @method: The caller method
10338 * @called: The called method
10339 * @context_klass: The static type on stack of the owner @called object used
10341 * This function must be used with instance calls, as they have more strict family accessibility.
10342 * It can be used with static methods, but context_klass should be NULL.
10344 * Returns: TRUE if caller have proper visibility and acessibility to @called
10347 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10349 MonoClass *access_class = method->klass;
10350 MonoClass *member_class = called->klass;
10351 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10353 MonoClass *nested = access_class->nested_in;
10355 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10358 nested = nested->nested_in;
10365 can = can_access_type (access_class, member_class);
10367 MonoClass *nested = access_class->nested_in;
10369 can = can_access_type (nested, member_class);
10372 nested = nested->nested_in;
10379 if (called->is_inflated) {
10380 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10381 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10390 * mono_method_can_access_field_full:
10391 * @method: The caller method
10392 * @field: The accessed field
10393 * @context_klass: The static type on stack of the owner @field object used
10395 * This function must be used with instance fields, as they have more strict family accessibility.
10396 * It can be used with static fields, but context_klass should be NULL.
10398 * Returns: TRUE if caller have proper visibility and acessibility to @field
10401 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10403 MonoClass *access_class = method->klass;
10404 MonoClass *member_class = field->parent;
10405 /* FIXME: check all overlapping fields */
10406 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10408 MonoClass *nested = access_class->nested_in;
10410 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10413 nested = nested->nested_in;
10420 can = can_access_type (access_class, member_class);
10422 MonoClass *nested = access_class->nested_in;
10424 can = can_access_type (nested, member_class);
10427 nested = nested->nested_in;
10437 * mono_class_can_access_class:
10438 * @source_class: The source class
10439 * @target_class: The accessed class
10441 * This function returns is @target_class is visible to @source_class
10443 * Returns: TRUE if source have proper visibility and acessibility to target
10446 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10448 return can_access_type (source_class, target_class);
10452 * mono_type_is_valid_enum_basetype:
10453 * @type: The MonoType to check
10455 * Returns: TRUE if the type can be used as the basetype of an enum
10457 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10458 switch (type->type) {
10461 case MONO_TYPE_BOOLEAN:
10464 case MONO_TYPE_CHAR:
10478 * mono_class_is_valid_enum:
10479 * @klass: An enum class to be validated
10481 * This method verify the required properties an enum should have.
10483 * Returns: TRUE if the informed enum class is valid
10485 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10486 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10487 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10489 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10490 MonoClassField * field;
10491 gpointer iter = NULL;
10492 gboolean found_base_field = FALSE;
10494 g_assert (klass->enumtype);
10495 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10496 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10500 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10503 while ((field = mono_class_get_fields (klass, &iter))) {
10504 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10505 if (found_base_field)
10507 found_base_field = TRUE;
10508 if (!mono_type_is_valid_enum_basetype (field->type))
10513 if (!found_base_field)
10516 if (klass->method.count > 0)
10523 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10525 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10529 * mono_class_setup_interface_id:
10531 * Initializes MonoClass::interface_id if required.
10533 * LOCKING: Acquires the loader lock.
10536 mono_class_setup_interface_id (MonoClass *klass)
10538 mono_loader_lock ();
10539 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10540 klass->interface_id = mono_get_unique_iid (klass);
10541 mono_loader_unlock ();
10545 * mono_class_alloc_ext:
10547 * Allocate klass->ext if not already done.
10550 mono_class_alloc_ext (MonoClass *klass)
10557 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10558 mono_image_lock (klass->image);
10559 mono_memory_barrier ();
10562 class_ext_size += sizeof (MonoClassExt);
10563 mono_image_unlock (klass->image);
10567 * mono_class_setup_interfaces:
10569 * Initialize klass->interfaces/interfaces_count.
10570 * LOCKING: Acquires the loader lock.
10571 * This function can fail the type.
10574 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10576 int i, interface_count;
10577 MonoClass **interfaces;
10579 mono_error_init (error);
10581 if (klass->interfaces_inited)
10584 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10585 MonoType *args [1];
10587 /* generic IList, ICollection, IEnumerable */
10588 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10589 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10591 args [0] = &klass->element_class->byval_arg;
10592 interfaces [0] = mono_class_bind_generic_parameters (
10593 mono_defaults.generic_ilist_class, 1, args, FALSE);
10594 if (interface_count > 1)
10595 interfaces [1] = mono_class_bind_generic_parameters (
10596 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10597 } else if (klass->generic_class) {
10598 MonoClass *gklass = klass->generic_class->container_class;
10600 mono_class_setup_interfaces (gklass, error);
10601 if (!mono_error_ok (error)) {
10602 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10606 interface_count = gklass->interface_count;
10607 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10608 for (i = 0; i < interface_count; i++) {
10609 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10610 if (!mono_error_ok (error)) {
10611 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10616 interface_count = 0;
10620 mono_image_lock (klass->image);
10622 if (!klass->interfaces_inited) {
10623 klass->interface_count = interface_count;
10624 klass->interfaces = interfaces;
10626 mono_memory_barrier ();
10628 klass->interfaces_inited = TRUE;
10631 mono_image_unlock (klass->image);
10635 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10637 MonoClass *klass = field->parent;
10638 MonoImage *image = klass->image;
10639 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10640 int field_idx = field - klass->fields;
10642 mono_error_init (error);
10645 MonoClassField *gfield = >d->fields [field_idx];
10646 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10647 if (!mono_error_ok (error)) {
10648 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10649 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10652 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10653 if (!mono_error_ok (error)) {
10654 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10655 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10659 guint32 cols [MONO_FIELD_SIZE];
10660 MonoGenericContainer *container = NULL;
10661 int idx = klass->field.first + field_idx;
10663 /*FIXME, in theory we do not lazy load SRE fields*/
10664 g_assert (!image_is_dynamic (image));
10666 if (klass->generic_container) {
10667 container = klass->generic_container;
10669 container = gtd->generic_container;
10670 g_assert (container);
10673 /* klass->field.first and idx points into the fieldptr table */
10674 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10676 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10677 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10678 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10682 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10684 mono_metadata_decode_value (sig, &sig);
10685 /* FIELD signature == 0x06 */
10686 g_assert (*sig == 0x06);
10688 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10689 if (!field->type) {
10690 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10691 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10697 mono_field_resolve_flags (MonoClassField *field)
10699 MonoClass *klass = field->parent;
10700 MonoImage *image = klass->image;
10701 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10702 int field_idx = field - klass->fields;
10706 MonoClassField *gfield = >d->fields [field_idx];
10707 return mono_field_get_flags (gfield);
10709 int idx = klass->field.first + field_idx;
10711 /*FIXME, in theory we do not lazy load SRE fields*/
10712 g_assert (!image_is_dynamic (image));
10714 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10719 * mono_class_setup_basic_field_info:
10720 * @class: The class to initialize
10722 * Initializes the klass->fields array of fields.
10723 * Aquires the loader lock.
10726 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10728 mono_loader_lock ();
10729 mono_class_setup_basic_field_info (klass);
10730 mono_loader_unlock ();
10734 * mono_class_get_fields_lazy:
10735 * @klass: the MonoClass to act on
10737 * This routine is an iterator routine for retrieving the fields in a class.
10738 * Only minimal information about fields are loaded. Accessors must be used
10739 * for all MonoClassField returned.
10741 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10742 * iterate over all of the elements. When no more values are
10743 * available, the return value is NULL.
10745 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10748 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10750 MonoClassField* field;
10754 mono_class_setup_basic_field_info_locking (klass);
10755 if (!klass->fields)
10757 /* start from the first */
10758 if (klass->field.count) {
10759 *iter = &klass->fields [0];
10760 return (MonoClassField *)*iter;
10766 field = (MonoClassField *)*iter;
10768 if (field < &klass->fields [klass->field.count]) {
10770 return (MonoClassField *)*iter;
10776 mono_class_full_name (MonoClass *klass)
10778 return mono_type_full_name (&klass->byval_arg);
10781 /* Declare all shared lazy type lookup functions */
10782 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)