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 (!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) {
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*/
8027 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8028 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8030 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8033 for (i = 0; i < klass->interface_count; i ++) {
8034 MonoClass *ic = klass->interfaces [i];
8039 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8044 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8047 if (klassc == mono_defaults.object_class)
8054 mono_type_is_generic_argument (MonoType *type)
8056 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8060 mono_class_has_variant_generic_params (MonoClass *klass)
8063 MonoGenericContainer *container;
8065 if (!klass->generic_class)
8068 container = klass->generic_class->container_class->generic_container;
8070 for (i = 0; i < container->type_argc; ++i)
8071 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8078 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8080 if (target == candidate)
8083 if (check_for_reference_conv &&
8084 mono_type_is_generic_argument (&target->byval_arg) &&
8085 mono_type_is_generic_argument (&candidate->byval_arg)) {
8086 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8087 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8089 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8092 if (!mono_class_is_assignable_from (target, candidate))
8098 * @container the generic container from the GTD
8099 * @klass: the class to be assigned to
8100 * @oklass: the source class
8102 * Both @klass and @oklass must be instances of the same generic interface.
8104 * Returns: TRUE if @klass can be assigned to a @klass variable
8107 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8110 MonoType **klass_argv, **oklass_argv;
8111 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8112 MonoGenericContainer *container = klass_gtd->generic_container;
8114 if (klass == oklass)
8117 /*Viable candidates are instances of the same generic interface*/
8118 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8121 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8122 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8124 for (j = 0; j < container->type_argc; ++j) {
8125 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8126 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8128 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8132 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8133 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8135 if (param1_class != param2_class) {
8136 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8137 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8139 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8140 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8150 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8152 MonoGenericParam *gparam, *ogparam;
8153 MonoGenericParamInfo *tinfo, *cinfo;
8154 MonoClass **candidate_class;
8155 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8158 if (target == candidate)
8160 if (target->byval_arg.type != candidate->byval_arg.type)
8163 gparam = target->byval_arg.data.generic_param;
8164 ogparam = candidate->byval_arg.data.generic_param;
8165 tinfo = mono_generic_param_info (gparam);
8166 cinfo = mono_generic_param_info (ogparam);
8168 class_constraint_satisfied = FALSE;
8169 valuetype_constraint_satisfied = FALSE;
8171 /*candidate must have a super set of target's special constraints*/
8172 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8173 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8175 if (cinfo->constraints) {
8176 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8177 MonoClass *cc = *candidate_class;
8179 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8180 class_constraint_satisfied = TRUE;
8181 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8182 valuetype_constraint_satisfied = TRUE;
8185 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8186 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8188 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8190 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8192 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8193 valuetype_constraint_satisfied)) {
8198 /*candidate type constraints must be a superset of target's*/
8199 if (tinfo->constraints) {
8200 MonoClass **target_class;
8201 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8202 MonoClass *tc = *target_class;
8205 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8206 * check it's constraints since it satisfy the constraint by itself.
8208 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8211 if (!cinfo->constraints)
8214 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8215 MonoClass *cc = *candidate_class;
8217 if (mono_class_is_assignable_from (tc, cc))
8221 * This happens when we have the following:
8223 * Bar<K> where K : IFace
8224 * Foo<T, U> where T : U where U : IFace
8226 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8229 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8230 if (mono_gparam_is_assignable_from (target, cc))
8234 if (!*candidate_class)
8239 /*candidate itself must have a constraint that satisfy target*/
8240 if (cinfo->constraints) {
8241 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8242 MonoClass *cc = *candidate_class;
8243 if (mono_class_is_assignable_from (target, cc))
8251 * mono_class_is_assignable_from:
8252 * @klass: the class to be assigned to
8253 * @oklass: the source class
8255 * Returns: TRUE if an instance of object oklass can be assigned to an
8256 * instance of object @klass
8259 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8262 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8264 mono_class_init (klass);
8266 if (!oklass->inited)
8267 mono_class_init (oklass);
8269 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8272 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8273 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8275 return mono_gparam_is_assignable_from (klass, oklass);
8278 if (MONO_CLASS_IS_INTERFACE (klass)) {
8279 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8280 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8281 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8285 for (i = 0; constraints [i]; ++i) {
8286 if (mono_class_is_assignable_from (klass, constraints [i]))
8294 /* interface_offsets might not be set for dynamic classes */
8295 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8297 * oklass might be a generic type parameter but they have
8298 * interface_offsets set.
8300 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8301 if (!is_ok (&error)) {
8302 mono_error_cleanup (&error);
8307 if (!oklass->interface_bitmap)
8308 /* Happens with generic instances of not-yet created dynamic types */
8310 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8313 if (mono_class_has_variant_generic_params (klass)) {
8315 mono_class_setup_interfaces (oklass, &error);
8316 if (!mono_error_ok (&error)) {
8317 mono_error_cleanup (&error);
8321 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8322 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8323 MonoClass *iface = oklass->interfaces_packed [i];
8325 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8330 } else if (klass->delegate) {
8331 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8333 }else if (klass->rank) {
8334 MonoClass *eclass, *eoclass;
8336 if (oklass->rank != klass->rank)
8339 /* vectors vs. one dimensional arrays */
8340 if (oklass->byval_arg.type != klass->byval_arg.type)
8343 eclass = klass->cast_class;
8344 eoclass = oklass->cast_class;
8347 * a is b does not imply a[] is b[] when a is a valuetype, and
8348 * b is a reference type.
8351 if (eoclass->valuetype) {
8352 if ((eclass == mono_defaults.enum_class) ||
8353 (eclass == mono_defaults.enum_class->parent) ||
8354 (eclass == mono_defaults.object_class))
8358 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8359 } else if (mono_class_is_nullable (klass)) {
8360 if (mono_class_is_nullable (oklass))
8361 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8363 return mono_class_is_assignable_from (klass->cast_class, oklass);
8364 } else if (klass == mono_defaults.object_class)
8367 return mono_class_has_parent (oklass, klass);
8370 /*Check if @oklass is variant compatible with @klass.*/
8372 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8375 MonoType **klass_argv, **oklass_argv;
8376 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8377 MonoGenericContainer *container = klass_gtd->generic_container;
8379 /*Viable candidates are instances of the same generic interface*/
8380 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8383 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8384 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8386 for (j = 0; j < container->type_argc; ++j) {
8387 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8388 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8390 if (param1_class->valuetype != param2_class->valuetype)
8394 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8395 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8397 if (param1_class != param2_class) {
8398 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8399 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8401 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8402 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8410 /*Check if @candidate implements the interface @target*/
8412 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8416 gboolean is_variant = mono_class_has_variant_generic_params (target);
8418 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8419 if (mono_class_is_variant_compatible_slow (target, candidate))
8424 if (candidate == target)
8427 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8428 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8429 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8431 if (tb && tb->interfaces) {
8432 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8433 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8434 MonoClass *iface_class;
8436 /* we can't realize the type here since it can do pretty much anything. */
8439 iface_class = mono_class_from_mono_type (iface->type);
8440 if (iface_class == target)
8442 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8444 if (mono_class_implement_interface_slow (target, iface_class))
8449 /*setup_interfaces don't mono_class_init anything*/
8450 /*FIXME this doesn't handle primitive type arrays.
8451 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8452 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8454 mono_class_setup_interfaces (candidate, &error);
8455 if (!mono_error_ok (&error)) {
8456 mono_error_cleanup (&error);
8460 for (i = 0; i < candidate->interface_count; ++i) {
8461 if (candidate->interfaces [i] == target)
8464 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8467 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8471 candidate = candidate->parent;
8472 } while (candidate);
8478 * Check if @oklass can be assigned to @klass.
8479 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8482 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8484 if (candidate == target)
8486 if (target == mono_defaults.object_class)
8489 if (mono_class_has_parent (candidate, target))
8492 /*If target is not an interface there is no need to check them.*/
8493 if (MONO_CLASS_IS_INTERFACE (target))
8494 return mono_class_implement_interface_slow (target, candidate);
8496 if (target->delegate && mono_class_has_variant_generic_params (target))
8497 return mono_class_is_variant_compatible (target, candidate, FALSE);
8500 MonoClass *eclass, *eoclass;
8502 if (target->rank != candidate->rank)
8505 /* vectors vs. one dimensional arrays */
8506 if (target->byval_arg.type != candidate->byval_arg.type)
8509 eclass = target->cast_class;
8510 eoclass = candidate->cast_class;
8513 * a is b does not imply a[] is b[] when a is a valuetype, and
8514 * b is a reference type.
8517 if (eoclass->valuetype) {
8518 if ((eclass == mono_defaults.enum_class) ||
8519 (eclass == mono_defaults.enum_class->parent) ||
8520 (eclass == mono_defaults.object_class))
8524 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8526 /*FIXME properly handle nullables */
8527 /*FIXME properly handle (M)VAR */
8532 * mono_class_get_cctor:
8533 * @klass: A MonoClass pointer
8535 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8538 mono_class_get_cctor (MonoClass *klass)
8540 MonoCachedClassInfo cached_info;
8542 if (image_is_dynamic (klass->image)) {
8544 * has_cctor is not set for these classes because mono_class_init () is
8547 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8550 if (!klass->has_cctor)
8553 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8555 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8556 if (!mono_error_ok (&error))
8557 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8561 if (klass->generic_class && !klass->methods)
8562 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8564 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8568 * mono_class_get_finalizer:
8569 * @klass: The MonoClass pointer
8571 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8574 mono_class_get_finalizer (MonoClass *klass)
8576 MonoCachedClassInfo cached_info;
8579 mono_class_init (klass);
8580 if (!mono_class_has_finalizer (klass))
8583 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8585 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8586 if (!mono_error_ok (&error))
8587 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8590 mono_class_setup_vtable (klass);
8591 return klass->vtable [finalize_slot];
8596 * mono_class_needs_cctor_run:
8597 * @klass: the MonoClass pointer
8598 * @caller: a MonoMethod describing the caller
8600 * Determines whenever the class has a static constructor and whenever it
8601 * needs to be called when executing CALLER.
8604 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8608 method = mono_class_get_cctor (klass);
8610 return (method == caller) ? FALSE : TRUE;
8616 * mono_class_array_element_size:
8619 * Returns: The number of bytes an element of type @klass
8620 * uses when stored into an array.
8623 mono_class_array_element_size (MonoClass *klass)
8625 MonoType *type = &klass->byval_arg;
8628 switch (type->type) {
8631 case MONO_TYPE_BOOLEAN:
8635 case MONO_TYPE_CHAR:
8644 case MONO_TYPE_CLASS:
8645 case MONO_TYPE_STRING:
8646 case MONO_TYPE_OBJECT:
8647 case MONO_TYPE_SZARRAY:
8648 case MONO_TYPE_ARRAY:
8649 return sizeof (gpointer);
8654 case MONO_TYPE_VALUETYPE:
8655 if (type->data.klass->enumtype) {
8656 type = mono_class_enum_basetype (type->data.klass);
8657 klass = klass->element_class;
8660 return mono_class_instance_size (klass) - sizeof (MonoObject);
8661 case MONO_TYPE_GENERICINST:
8662 type = &type->data.generic_class->container_class->byval_arg;
8665 case MONO_TYPE_MVAR: {
8668 return mono_type_size (type, &align);
8670 case MONO_TYPE_VOID:
8674 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8680 * mono_array_element_size:
8681 * @ac: pointer to a #MonoArrayClass
8683 * Returns: The size of single array element.
8686 mono_array_element_size (MonoClass *ac)
8688 g_assert (ac->rank);
8689 return ac->sizes.element_size;
8693 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8694 MonoGenericContext *context)
8697 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8698 g_assert (mono_error_ok (&error));
8703 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8704 MonoGenericContext *context, MonoError *error)
8706 mono_error_init (error);
8708 if (image_is_dynamic (image)) {
8709 MonoClass *tmp_handle_class;
8710 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8712 mono_error_assert_ok (error);
8713 g_assert (tmp_handle_class);
8715 *handle_class = tmp_handle_class;
8717 if (tmp_handle_class == mono_defaults.typehandle_class)
8718 return &((MonoClass*)obj)->byval_arg;
8723 switch (token & 0xff000000) {
8724 case MONO_TOKEN_TYPE_DEF:
8725 case MONO_TOKEN_TYPE_REF:
8726 case MONO_TOKEN_TYPE_SPEC: {
8729 *handle_class = mono_defaults.typehandle_class;
8730 type = mono_type_get_checked (image, token, context, error);
8734 mono_class_init (mono_class_from_mono_type (type));
8735 /* We return a MonoType* as handle */
8738 case MONO_TOKEN_FIELD_DEF: {
8740 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8742 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8746 *handle_class = mono_defaults.fieldhandle_class;
8747 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8751 mono_class_init (klass);
8752 return mono_class_get_field (klass, token);
8754 case MONO_TOKEN_METHOD_DEF:
8755 case MONO_TOKEN_METHOD_SPEC: {
8757 meth = mono_get_method_checked (image, token, NULL, context, error);
8759 *handle_class = mono_defaults.methodhandle_class;
8765 case MONO_TOKEN_MEMBER_REF: {
8766 guint32 cols [MONO_MEMBERREF_SIZE];
8768 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8769 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8770 mono_metadata_decode_blob_size (sig, &sig);
8771 if (*sig == 0x6) { /* it's a field */
8773 MonoClassField *field;
8774 field = mono_field_from_token_checked (image, token, &klass, context, error);
8776 *handle_class = mono_defaults.fieldhandle_class;
8780 meth = mono_get_method_checked (image, token, NULL, context, error);
8782 *handle_class = mono_defaults.methodhandle_class;
8787 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8793 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8795 MonoClass *handle_class;
8796 mono_error_init (error);
8797 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8801 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8803 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8806 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8809 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8811 get_cached_class_info = func;
8815 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8817 if (!get_cached_class_info)
8820 return get_cached_class_info (klass, res);
8824 mono_install_get_class_from_name (MonoGetClassFromName func)
8826 get_class_from_name = func;
8830 * mono_class_get_image:
8832 * Use this method to get the `MonoImage*` where this class came from.
8834 * Returns: The image where this class is defined.
8837 mono_class_get_image (MonoClass *klass)
8839 return klass->image;
8843 * mono_class_get_element_class:
8844 * @klass: the MonoClass to act on
8846 * Use this function to get the element class of an array.
8848 * Returns: The element class of an array.
8851 mono_class_get_element_class (MonoClass *klass)
8853 return klass->element_class;
8857 * mono_class_is_valuetype:
8858 * @klass: the MonoClass to act on
8860 * Use this method to determine if the provided `MonoClass*` represents a value type,
8861 * or a reference type.
8863 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8866 mono_class_is_valuetype (MonoClass *klass)
8868 return klass->valuetype;
8872 * mono_class_is_enum:
8873 * @klass: the MonoClass to act on
8875 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8877 * Returns: TRUE if the MonoClass represents an enumeration.
8880 mono_class_is_enum (MonoClass *klass)
8882 return klass->enumtype;
8886 * mono_class_enum_basetype:
8887 * @klass: the MonoClass to act on
8889 * Use this function to get the underlying type for an enumeration value.
8891 * Returns: The underlying type representation for an enumeration.
8894 mono_class_enum_basetype (MonoClass *klass)
8896 if (klass->element_class == klass)
8897 /* SRE or broken types */
8900 return &klass->element_class->byval_arg;
8904 * mono_class_get_parent
8905 * @klass: the MonoClass to act on
8907 * Returns: The parent class for this class.
8910 mono_class_get_parent (MonoClass *klass)
8912 return klass->parent;
8916 * mono_class_get_nesting_type:
8917 * @klass: the MonoClass to act on
8919 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8921 * If the return is NULL, this indicates that this class is not nested.
8923 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8926 mono_class_get_nesting_type (MonoClass *klass)
8928 return klass->nested_in;
8932 * mono_class_get_rank:
8933 * @klass: the MonoClass to act on
8935 * Returns: The rank for the array (the number of dimensions).
8938 mono_class_get_rank (MonoClass *klass)
8944 * mono_class_get_flags:
8945 * @klass: the MonoClass to act on
8947 * The type flags from the TypeDef table from the metadata.
8948 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8951 * Returns: The flags from the TypeDef table.
8954 mono_class_get_flags (MonoClass *klass)
8956 return klass->flags;
8960 * mono_class_get_name
8961 * @klass: the MonoClass to act on
8963 * Returns: The name of the class.
8966 mono_class_get_name (MonoClass *klass)
8972 * mono_class_get_namespace:
8973 * @klass: the MonoClass to act on
8975 * Returns: The namespace of the class.
8978 mono_class_get_namespace (MonoClass *klass)
8980 return klass->name_space;
8984 * mono_class_get_type:
8985 * @klass: the MonoClass to act on
8987 * This method returns the internal Type representation for the class.
8989 * Returns: The MonoType from the class.
8992 mono_class_get_type (MonoClass *klass)
8994 return &klass->byval_arg;
8998 * mono_class_get_type_token:
8999 * @klass: the MonoClass to act on
9001 * This method returns type token for the class.
9003 * Returns: The type token for the class.
9006 mono_class_get_type_token (MonoClass *klass)
9008 return klass->type_token;
9012 * mono_class_get_byref_type:
9013 * @klass: the MonoClass to act on
9018 mono_class_get_byref_type (MonoClass *klass)
9020 return &klass->this_arg;
9024 * mono_class_num_fields:
9025 * @klass: the MonoClass to act on
9027 * Returns: The number of static and instance fields in the class.
9030 mono_class_num_fields (MonoClass *klass)
9032 return klass->field.count;
9036 * mono_class_num_methods:
9037 * @klass: the MonoClass to act on
9039 * Returns: The number of methods in the class.
9042 mono_class_num_methods (MonoClass *klass)
9044 return klass->method.count;
9048 * mono_class_num_properties
9049 * @klass: the MonoClass to act on
9051 * Returns: The number of properties in the class.
9054 mono_class_num_properties (MonoClass *klass)
9056 mono_class_setup_properties (klass);
9058 return klass->ext->property.count;
9062 * mono_class_num_events:
9063 * @klass: the MonoClass to act on
9065 * Returns: The number of events in the class.
9068 mono_class_num_events (MonoClass *klass)
9070 mono_class_setup_events (klass);
9072 return klass->ext->event.count;
9076 * mono_class_get_fields:
9077 * @klass: the MonoClass to act on
9079 * This routine is an iterator routine for retrieving the fields in a class.
9081 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9082 * iterate over all of the elements. When no more values are
9083 * available, the return value is NULL.
9085 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9088 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9090 MonoClassField* field;
9094 mono_class_setup_fields_locking (klass);
9095 if (mono_class_has_failure (klass))
9097 /* start from the first */
9098 if (klass->field.count) {
9099 *iter = &klass->fields [0];
9100 return &klass->fields [0];
9106 field = (MonoClassField *)*iter;
9108 if (field < &klass->fields [klass->field.count]) {
9116 * mono_class_get_methods
9117 * @klass: the MonoClass to act on
9119 * This routine is an iterator routine for retrieving the fields in a class.
9121 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9122 * iterate over all of the elements. When no more values are
9123 * available, the return value is NULL.
9125 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9128 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9130 MonoMethod** method;
9134 mono_class_setup_methods (klass);
9137 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9138 * FIXME we should better report this error to the caller
9140 if (!klass->methods)
9142 /* start from the first */
9143 if (klass->method.count) {
9144 *iter = &klass->methods [0];
9145 return klass->methods [0];
9151 method = (MonoMethod **)*iter;
9153 if (method < &klass->methods [klass->method.count]) {
9161 * mono_class_get_virtual_methods:
9163 * Iterate over the virtual methods of KLASS.
9165 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9168 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9170 MonoMethod** method;
9173 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9175 mono_class_setup_methods (klass);
9177 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9178 * FIXME we should better report this error to the caller
9180 if (!klass->methods)
9182 /* start from the first */
9183 method = &klass->methods [0];
9185 method = (MonoMethod **)*iter;
9188 while (method < &klass->methods [klass->method.count]) {
9189 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9193 if (method < &klass->methods [klass->method.count]) {
9200 /* Search directly in metadata to avoid calling setup_methods () */
9201 MonoMethod *res = NULL;
9207 start_index = GPOINTER_TO_UINT (*iter);
9210 for (i = start_index; i < klass->method.count; ++i) {
9213 /* klass->method.first points into the methodptr table */
9214 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9216 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9220 if (i < klass->method.count) {
9222 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9223 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9225 /* Add 1 here so the if (*iter) check fails */
9226 *iter = GUINT_TO_POINTER (i + 1);
9235 * mono_class_get_properties:
9236 * @klass: the MonoClass to act on
9238 * This routine is an iterator routine for retrieving the properties in a class.
9240 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9241 * iterate over all of the elements. When no more values are
9242 * available, the return value is NULL.
9244 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9247 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9249 MonoProperty* property;
9253 mono_class_setup_properties (klass);
9254 /* start from the first */
9255 if (klass->ext->property.count) {
9256 *iter = &klass->ext->properties [0];
9257 return (MonoProperty *)*iter;
9263 property = (MonoProperty *)*iter;
9265 if (property < &klass->ext->properties [klass->ext->property.count]) {
9267 return (MonoProperty *)*iter;
9273 * mono_class_get_events:
9274 * @klass: the MonoClass to act on
9276 * This routine is an iterator routine for retrieving the properties in a class.
9278 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9279 * iterate over all of the elements. When no more values are
9280 * available, the return value is NULL.
9282 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9285 mono_class_get_events (MonoClass* klass, gpointer *iter)
9291 mono_class_setup_events (klass);
9292 /* start from the first */
9293 if (klass->ext->event.count) {
9294 *iter = &klass->ext->events [0];
9295 return (MonoEvent *)*iter;
9301 event = (MonoEvent *)*iter;
9303 if (event < &klass->ext->events [klass->ext->event.count]) {
9305 return (MonoEvent *)*iter;
9311 * mono_class_get_interfaces
9312 * @klass: the MonoClass to act on
9314 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9316 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9317 * iterate over all of the elements. When no more values are
9318 * available, the return value is NULL.
9320 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9323 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9331 mono_class_init (klass);
9332 if (!klass->interfaces_inited) {
9333 mono_class_setup_interfaces (klass, &error);
9334 if (!mono_error_ok (&error)) {
9335 mono_error_cleanup (&error);
9339 /* start from the first */
9340 if (klass->interface_count) {
9341 *iter = &klass->interfaces [0];
9342 return klass->interfaces [0];
9348 iface = (MonoClass **)*iter;
9350 if (iface < &klass->interfaces [klass->interface_count]) {
9358 setup_nested_types (MonoClass *klass)
9361 GList *classes, *nested_classes, *l;
9364 if (klass->nested_classes_inited)
9367 if (!klass->type_token)
9368 klass->nested_classes_inited = TRUE;
9370 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9374 guint32 cols [MONO_NESTED_CLASS_SIZE];
9375 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9376 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9377 if (!mono_error_ok (&error)) {
9378 /*FIXME don't swallow the error message*/
9379 mono_error_cleanup (&error);
9381 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9385 classes = g_list_prepend (classes, nclass);
9387 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9390 mono_class_alloc_ext (klass);
9392 nested_classes = NULL;
9393 for (l = classes; l; l = l->next)
9394 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9395 g_list_free (classes);
9397 mono_image_lock (klass->image);
9399 mono_memory_barrier ();
9400 if (!klass->nested_classes_inited) {
9401 klass->ext->nested_classes = nested_classes;
9402 mono_memory_barrier ();
9403 klass->nested_classes_inited = TRUE;
9406 mono_image_unlock (klass->image);
9410 * mono_class_get_nested_types
9411 * @klass: the MonoClass to act on
9413 * This routine is an iterator routine for retrieving the nested types of a class.
9414 * This works only if @klass is non-generic, or a generic type definition.
9416 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9417 * iterate over all of the elements. When no more values are
9418 * available, the return value is NULL.
9420 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9423 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9429 if (!klass->nested_classes_inited)
9430 setup_nested_types (klass);
9433 /* start from the first */
9434 if (klass->ext && klass->ext->nested_classes) {
9435 *iter = klass->ext->nested_classes;
9436 return (MonoClass *)klass->ext->nested_classes->data;
9438 /* no nested types */
9442 item = (GList *)*iter;
9446 return (MonoClass *)item->data;
9453 * mono_class_is_delegate
9454 * @klass: the MonoClass to act on
9456 * Returns: TRUE if the MonoClass represents a System.Delegate.
9459 mono_class_is_delegate (MonoClass *klass)
9461 return klass->delegate;
9465 * mono_class_implements_interface
9466 * @klass: The MonoClass to act on
9467 * @interface: The interface to check if @klass implements.
9469 * Returns: TRUE if @klass implements @interface.
9472 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9474 return mono_class_is_assignable_from (iface, klass);
9478 * mono_field_get_name:
9479 * @field: the MonoClassField to act on
9481 * Returns: The name of the field.
9484 mono_field_get_name (MonoClassField *field)
9490 * mono_field_get_type:
9491 * @field: the MonoClassField to act on
9493 * Returns: MonoType of the field.
9496 mono_field_get_type (MonoClassField *field)
9499 MonoType *type = mono_field_get_type_checked (field, &error);
9500 if (!mono_error_ok (&error)) {
9501 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9502 mono_error_cleanup (&error);
9509 * mono_field_get_type_checked:
9510 * @field: the MonoClassField to act on
9511 * @error: used to return any erro found while retrieving @field type
9513 * Returns: MonoType of the field.
9516 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9518 mono_error_init (error);
9520 mono_field_resolve_type (field, error);
9525 * mono_field_get_parent:
9526 * @field: the MonoClassField to act on
9528 * Returns: MonoClass where the field was defined.
9531 mono_field_get_parent (MonoClassField *field)
9533 return field->parent;
9537 * mono_field_get_flags;
9538 * @field: the MonoClassField to act on
9540 * The metadata flags for a field are encoded using the
9541 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9543 * Returns: The flags for the field.
9546 mono_field_get_flags (MonoClassField *field)
9549 return mono_field_resolve_flags (field);
9550 return field->type->attrs;
9554 * mono_field_get_offset:
9555 * @field: the MonoClassField to act on
9557 * Returns: The field offset.
9560 mono_field_get_offset (MonoClassField *field)
9562 return field->offset;
9566 mono_field_get_rva (MonoClassField *field)
9570 MonoClass *klass = field->parent;
9571 MonoFieldDefaultValue *field_def_values;
9573 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9575 if (!klass->ext || !klass->ext->field_def_values) {
9576 mono_class_alloc_ext (klass);
9578 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9580 mono_image_lock (klass->image);
9581 if (!klass->ext->field_def_values)
9582 klass->ext->field_def_values = field_def_values;
9583 mono_image_unlock (klass->image);
9586 field_index = mono_field_get_index (field);
9588 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9589 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9591 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9592 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9595 return klass->ext->field_def_values [field_index].data;
9599 * mono_field_get_data:
9600 * @field: the MonoClassField to act on
9602 * Returns: A pointer to the metadata constant value or to the field
9603 * data if it has an RVA flag.
9606 mono_field_get_data (MonoClassField *field)
9608 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9609 MonoTypeEnum def_type;
9611 return mono_class_get_field_default_value (field, &def_type);
9612 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9613 return mono_field_get_rva (field);
9620 * mono_property_get_name:
9621 * @prop: the MonoProperty to act on
9623 * Returns: The name of the property
9626 mono_property_get_name (MonoProperty *prop)
9632 * mono_property_get_set_method
9633 * @prop: the MonoProperty to act on.
9635 * Returns: The setter method of the property (A MonoMethod)
9638 mono_property_get_set_method (MonoProperty *prop)
9644 * mono_property_get_get_method
9645 * @prop: the MonoProperty to act on.
9647 * Returns: The setter method of the property (A MonoMethod)
9650 mono_property_get_get_method (MonoProperty *prop)
9656 * mono_property_get_parent:
9657 * @prop: the MonoProperty to act on.
9659 * Returns: The MonoClass where the property was defined.
9662 mono_property_get_parent (MonoProperty *prop)
9664 return prop->parent;
9668 * mono_property_get_flags:
9669 * @prop: the MonoProperty to act on.
9671 * The metadata flags for a property are encoded using the
9672 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9674 * Returns: The flags for the property.
9677 mono_property_get_flags (MonoProperty *prop)
9683 * mono_event_get_name:
9684 * @event: the MonoEvent to act on
9686 * Returns: The name of the event.
9689 mono_event_get_name (MonoEvent *event)
9695 * mono_event_get_add_method:
9696 * @event: The MonoEvent to act on.
9698 * Returns: The @add' method for the event (a MonoMethod).
9701 mono_event_get_add_method (MonoEvent *event)
9707 * mono_event_get_remove_method:
9708 * @event: The MonoEvent to act on.
9710 * Returns: The @remove method for the event (a MonoMethod).
9713 mono_event_get_remove_method (MonoEvent *event)
9715 return event->remove;
9719 * mono_event_get_raise_method:
9720 * @event: The MonoEvent to act on.
9722 * Returns: The @raise method for the event (a MonoMethod).
9725 mono_event_get_raise_method (MonoEvent *event)
9727 return event->raise;
9731 * mono_event_get_parent:
9732 * @event: the MonoEvent to act on.
9734 * Returns: The MonoClass where the event is defined.
9737 mono_event_get_parent (MonoEvent *event)
9739 return event->parent;
9743 * mono_event_get_flags
9744 * @event: the MonoEvent to act on.
9746 * The metadata flags for an event are encoded using the
9747 * EVENT_* constants. See the tabledefs.h file for details.
9749 * Returns: The flags for the event.
9752 mono_event_get_flags (MonoEvent *event)
9754 return event->attrs;
9758 * mono_class_get_method_from_name:
9759 * @klass: where to look for the method
9760 * @name: name of the method
9761 * @param_count: number of parameters. -1 for any number.
9763 * Obtains a MonoMethod with a given name and number of parameters.
9764 * It only works if there are no multiple signatures for any given method name.
9767 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9769 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9773 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9775 MonoMethod *res = NULL;
9778 /* Search directly in the metadata to avoid calling setup_methods () */
9779 for (i = 0; i < klass->method.count; ++i) {
9781 guint32 cols [MONO_METHOD_SIZE];
9783 MonoMethodSignature *sig;
9785 /* klass->method.first points into the methodptr table */
9786 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9788 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9789 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9791 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9794 if (param_count == -1) {
9798 sig = mono_method_signature_checked (method, &error);
9800 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9803 if (sig->param_count == param_count) {
9814 * mono_class_get_method_from_name_flags:
9815 * @klass: where to look for the method
9816 * @name_space: name of the method
9817 * @param_count: number of parameters. -1 for any number.
9818 * @flags: flags which must be set in the method
9820 * Obtains a MonoMethod with a given name and number of parameters.
9821 * It only works if there are no multiple signatures for any given method name.
9824 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9826 MonoMethod *res = NULL;
9829 mono_class_init (klass);
9831 if (klass->generic_class && !klass->methods) {
9832 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9835 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9836 if (!mono_error_ok (&error))
9837 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9842 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9843 mono_class_setup_methods (klass);
9845 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9846 See mono/tests/array_load_exception.il
9847 FIXME we should better report this error to the caller
9849 if (!klass->methods)
9851 for (i = 0; i < klass->method.count; ++i) {
9852 MonoMethod *method = klass->methods [i];
9854 if (method->name[0] == name [0] &&
9855 !strcmp (name, method->name) &&
9856 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9857 ((method->flags & flags) == flags)) {
9864 res = find_method_in_metadata (klass, name, param_count, flags);
9871 * mono_class_set_failure:
9872 * @klass: class in which the failure was detected
9873 * @ex_type: the kind of exception/error to be thrown (later)
9874 * @ex_data: exception data (specific to each type of exception/error)
9876 * Keep a detected failure informations in the class for later processing.
9877 * Note that only the first failure is kept.
9879 * LOCKING: Acquires the loader lock.
9882 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9884 if (mono_class_has_failure (klass))
9887 mono_loader_lock ();
9888 klass->exception_type = ex_type;
9890 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9891 mono_loader_unlock ();
9897 * mono_class_get_exception_data:
9899 * Return the exception_data property of KLASS.
9901 * LOCKING: Acquires the loader lock.
9904 mono_class_get_exception_data (MonoClass *klass)
9906 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9910 * mono_classes_init:
9912 * Initialize the resources used by this module.
9915 mono_classes_init (void)
9917 mono_os_mutex_init (&classes_mutex);
9919 mono_counters_register ("Inflated methods size",
9920 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9921 mono_counters_register ("Inflated classes",
9922 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9923 mono_counters_register ("Inflated classes size",
9924 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9925 mono_counters_register ("MonoClass size",
9926 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9927 mono_counters_register ("MonoClassExt size",
9928 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9932 * mono_classes_cleanup:
9934 * Free the resources used by this module.
9937 mono_classes_cleanup (void)
9939 if (global_interface_bitset)
9940 mono_bitset_free (global_interface_bitset);
9941 global_interface_bitset = NULL;
9942 mono_os_mutex_destroy (&classes_mutex);
9946 * mono_class_get_exception_for_failure:
9947 * @klass: class in which the failure was detected
9949 * Return a constructed MonoException than the caller can then throw
9950 * using mono_raise_exception - or NULL if no failure is present (or
9951 * doesn't result in an exception).
9954 mono_class_get_exception_for_failure (MonoClass *klass)
9956 gpointer exception_data = mono_class_get_exception_data (klass);
9958 switch (mono_class_get_failure(klass)) {
9959 case MONO_EXCEPTION_TYPE_LOAD: {
9962 char *str = mono_type_get_full_name (klass);
9963 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9964 name = mono_string_new (mono_domain_get (), str);
9966 ex = mono_get_exception_type_load (name, astr);
9970 case MONO_EXCEPTION_MISSING_METHOD: {
9971 char *class_name = (char *)exception_data;
9972 char *assembly_name = class_name + strlen (class_name) + 1;
9974 return mono_get_exception_missing_method (class_name, assembly_name);
9976 case MONO_EXCEPTION_MISSING_FIELD: {
9977 char *class_name = (char *)exception_data;
9978 char *member_name = class_name + strlen (class_name) + 1;
9980 return mono_get_exception_missing_field (class_name, member_name);
9982 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9983 char *msg_format = (char *)exception_data;
9984 char *assembly_name = msg_format + strlen (msg_format) + 1;
9985 char *msg = g_strdup_printf (msg_format, assembly_name);
9988 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9994 case MONO_EXCEPTION_BAD_IMAGE: {
9995 return mono_get_exception_bad_image_format ((const char *)exception_data);
9997 case MONO_EXCEPTION_INVALID_PROGRAM: {
9998 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10001 /* TODO - handle other class related failures */
10002 return mono_get_exception_execution_engine ("Unknown class failure");
10008 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10010 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10011 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10013 if (outer_klass == inner_klass)
10015 inner_klass = inner_klass->nested_in;
10016 } while (inner_klass);
10021 mono_class_get_generic_type_definition (MonoClass *klass)
10023 return klass->generic_class ? klass->generic_class->container_class : klass;
10027 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10029 * Generic instantiations are ignored for all super types of @klass.
10031 * Visibility checks ignoring generic instantiations.
10034 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10037 klass = mono_class_get_generic_type_definition (klass);
10038 parent = mono_class_get_generic_type_definition (parent);
10039 mono_class_setup_supertypes (klass);
10041 for (i = 0; i < klass->idepth; ++i) {
10042 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10048 * Subtype can only access parent members with family protection if the site object
10049 * is subclass of Subtype. For example:
10050 * class A { protected int x; }
10052 * void valid_access () {
10056 * void invalid_access () {
10063 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10065 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10068 if (context_klass == NULL)
10070 /*if access_klass is not member_klass context_klass must be type compat*/
10071 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10077 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10080 if (accessing == accessed)
10082 if (!accessed || !accessing)
10085 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10086 * anywhere so untrusted friends are not safe to access platform's code internals */
10087 if (mono_security_core_clr_enabled ()) {
10088 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10092 mono_assembly_load_friends (accessed);
10093 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10094 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10095 /* Be conservative with checks */
10096 if (!friend_->name)
10098 if (strcmp (accessing->aname.name, friend_->name))
10100 if (friend_->public_key_token [0]) {
10101 if (!accessing->aname.public_key_token [0])
10103 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10112 * If klass is a generic type or if it is derived from a generic type, return the
10113 * MonoClass of the generic definition
10114 * Returns NULL if not found
10117 get_generic_definition_class (MonoClass *klass)
10120 if (klass->generic_class && klass->generic_class->container_class)
10121 return klass->generic_class->container_class;
10122 klass = klass->parent;
10128 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10131 for (i = 0; i < ginst->type_argc; ++i) {
10132 MonoType *type = ginst->type_argv[i];
10133 switch (type->type) {
10134 case MONO_TYPE_SZARRAY:
10135 if (!can_access_type (access_klass, type->data.klass))
10138 case MONO_TYPE_ARRAY:
10139 if (!can_access_type (access_klass, type->data.array->eklass))
10142 case MONO_TYPE_PTR:
10143 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10146 case MONO_TYPE_CLASS:
10147 case MONO_TYPE_VALUETYPE:
10148 case MONO_TYPE_GENERICINST:
10149 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10159 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10163 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10166 if (access_klass->element_class && !access_klass->enumtype)
10167 access_klass = access_klass->element_class;
10169 if (member_klass->element_class && !member_klass->enumtype)
10170 member_klass = member_klass->element_class;
10172 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10174 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10177 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10180 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10183 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10186 /*Non nested type with nested visibility. We just fail it.*/
10187 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10190 switch (access_level) {
10191 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10192 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10194 case TYPE_ATTRIBUTE_PUBLIC:
10197 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10200 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10201 return is_nesting_type (member_klass, access_klass);
10203 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10204 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10206 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10207 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10209 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10210 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10211 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10213 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10214 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10215 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10220 /* FIXME: check visibility of type, too */
10222 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10224 MonoClass *member_generic_def;
10225 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10228 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10229 access_klass->generic_container) &&
10230 (member_generic_def = get_generic_definition_class (member_klass))) {
10231 MonoClass *access_container;
10233 if (access_klass->generic_container)
10234 access_container = access_klass;
10236 access_container = access_klass->generic_class->container_class;
10238 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10242 /* Partition I 8.5.3.2 */
10243 /* the access level values are the same for fields and methods */
10244 switch (access_level) {
10245 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10246 /* same compilation unit */
10247 return access_klass->image == member_klass->image;
10248 case FIELD_ATTRIBUTE_PRIVATE:
10249 return access_klass == member_klass;
10250 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10251 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10252 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10255 case FIELD_ATTRIBUTE_ASSEMBLY:
10256 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10257 case FIELD_ATTRIBUTE_FAMILY:
10258 if (is_valid_family_access (access_klass, member_klass, context_klass))
10261 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10262 if (is_valid_family_access (access_klass, member_klass, context_klass))
10264 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10265 case FIELD_ATTRIBUTE_PUBLIC:
10272 * mono_method_can_access_field:
10273 * @method: Method that will attempt to access the field
10274 * @field: the field to access
10276 * Used to determine if a method is allowed to access the specified field.
10278 * Returns: TRUE if the given @method is allowed to access the @field while following
10279 * the accessibility rules of the CLI.
10282 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10284 /* FIXME: check all overlapping fields */
10285 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10287 MonoClass *nested = method->klass->nested_in;
10289 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10292 nested = nested->nested_in;
10299 * mono_method_can_access_method:
10300 * @method: Method that will attempt to access the other method
10301 * @called: the method that we want to probe for accessibility.
10303 * Used to determine if the @method is allowed to access the specified @called method.
10305 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10306 * the accessibility rules of the CLI.
10309 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10311 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10313 MonoClass *nested = method->klass->nested_in;
10315 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10318 nested = nested->nested_in;
10323 * with generics calls to explicit interface implementations can be expressed
10324 * directly: the method is private, but we must allow it. This may be opening
10325 * a hole or the generics code should handle this differently.
10326 * Maybe just ensure the interface type is public.
10328 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10334 * mono_method_can_access_method_full:
10335 * @method: The caller method
10336 * @called: The called method
10337 * @context_klass: The static type on stack of the owner @called object used
10339 * This function must be used with instance calls, as they have more strict family accessibility.
10340 * It can be used with static methods, but context_klass should be NULL.
10342 * Returns: TRUE if caller have proper visibility and acessibility to @called
10345 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10347 MonoClass *access_class = method->klass;
10348 MonoClass *member_class = called->klass;
10349 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10351 MonoClass *nested = access_class->nested_in;
10353 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10356 nested = nested->nested_in;
10363 can = can_access_type (access_class, member_class);
10365 MonoClass *nested = access_class->nested_in;
10367 can = can_access_type (nested, member_class);
10370 nested = nested->nested_in;
10377 if (called->is_inflated) {
10378 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10379 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10388 * mono_method_can_access_field_full:
10389 * @method: The caller method
10390 * @field: The accessed field
10391 * @context_klass: The static type on stack of the owner @field object used
10393 * This function must be used with instance fields, as they have more strict family accessibility.
10394 * It can be used with static fields, but context_klass should be NULL.
10396 * Returns: TRUE if caller have proper visibility and acessibility to @field
10399 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10401 MonoClass *access_class = method->klass;
10402 MonoClass *member_class = field->parent;
10403 /* FIXME: check all overlapping fields */
10404 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10406 MonoClass *nested = access_class->nested_in;
10408 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10411 nested = nested->nested_in;
10418 can = can_access_type (access_class, member_class);
10420 MonoClass *nested = access_class->nested_in;
10422 can = can_access_type (nested, member_class);
10425 nested = nested->nested_in;
10435 * mono_class_can_access_class:
10436 * @source_class: The source class
10437 * @target_class: The accessed class
10439 * This function returns is @target_class is visible to @source_class
10441 * Returns: TRUE if source have proper visibility and acessibility to target
10444 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10446 return can_access_type (source_class, target_class);
10450 * mono_type_is_valid_enum_basetype:
10451 * @type: The MonoType to check
10453 * Returns: TRUE if the type can be used as the basetype of an enum
10455 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10456 switch (type->type) {
10459 case MONO_TYPE_BOOLEAN:
10462 case MONO_TYPE_CHAR:
10476 * mono_class_is_valid_enum:
10477 * @klass: An enum class to be validated
10479 * This method verify the required properties an enum should have.
10481 * Returns: TRUE if the informed enum class is valid
10483 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10484 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10485 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10487 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10488 MonoClassField * field;
10489 gpointer iter = NULL;
10490 gboolean found_base_field = FALSE;
10492 g_assert (klass->enumtype);
10493 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10494 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10498 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10501 while ((field = mono_class_get_fields (klass, &iter))) {
10502 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10503 if (found_base_field)
10505 found_base_field = TRUE;
10506 if (!mono_type_is_valid_enum_basetype (field->type))
10511 if (!found_base_field)
10514 if (klass->method.count > 0)
10521 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10523 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10527 * mono_class_setup_interface_id:
10529 * Initializes MonoClass::interface_id if required.
10531 * LOCKING: Acquires the loader lock.
10534 mono_class_setup_interface_id (MonoClass *klass)
10536 mono_loader_lock ();
10537 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10538 klass->interface_id = mono_get_unique_iid (klass);
10539 mono_loader_unlock ();
10543 * mono_class_alloc_ext:
10545 * Allocate klass->ext if not already done.
10548 mono_class_alloc_ext (MonoClass *klass)
10555 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10556 mono_image_lock (klass->image);
10557 mono_memory_barrier ();
10560 class_ext_size += sizeof (MonoClassExt);
10561 mono_image_unlock (klass->image);
10565 * mono_class_setup_interfaces:
10567 * Initialize klass->interfaces/interfaces_count.
10568 * LOCKING: Acquires the loader lock.
10569 * This function can fail the type.
10572 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10574 int i, interface_count;
10575 MonoClass **interfaces;
10577 mono_error_init (error);
10579 if (klass->interfaces_inited)
10582 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10583 MonoType *args [1];
10585 /* generic IList, ICollection, IEnumerable */
10586 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10587 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10589 args [0] = &klass->element_class->byval_arg;
10590 interfaces [0] = mono_class_bind_generic_parameters (
10591 mono_defaults.generic_ilist_class, 1, args, FALSE);
10592 if (interface_count > 1)
10593 interfaces [1] = mono_class_bind_generic_parameters (
10594 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10595 } else if (klass->generic_class) {
10596 MonoClass *gklass = klass->generic_class->container_class;
10598 mono_class_setup_interfaces (gklass, error);
10599 if (!mono_error_ok (error)) {
10600 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10604 interface_count = gklass->interface_count;
10605 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10606 for (i = 0; i < interface_count; i++) {
10607 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10608 if (!mono_error_ok (error)) {
10609 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10614 interface_count = 0;
10618 mono_image_lock (klass->image);
10620 if (!klass->interfaces_inited) {
10621 klass->interface_count = interface_count;
10622 klass->interfaces = interfaces;
10624 mono_memory_barrier ();
10626 klass->interfaces_inited = TRUE;
10629 mono_image_unlock (klass->image);
10633 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10635 MonoClass *klass = field->parent;
10636 MonoImage *image = klass->image;
10637 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10638 int field_idx = field - klass->fields;
10640 mono_error_init (error);
10643 MonoClassField *gfield = >d->fields [field_idx];
10644 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10645 if (!mono_error_ok (error)) {
10646 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10647 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10650 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10651 if (!mono_error_ok (error)) {
10652 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10653 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10657 guint32 cols [MONO_FIELD_SIZE];
10658 MonoGenericContainer *container = NULL;
10659 int idx = klass->field.first + field_idx;
10661 /*FIXME, in theory we do not lazy load SRE fields*/
10662 g_assert (!image_is_dynamic (image));
10664 if (klass->generic_container) {
10665 container = klass->generic_container;
10667 container = gtd->generic_container;
10668 g_assert (container);
10671 /* klass->field.first and idx points into the fieldptr table */
10672 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10674 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10675 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10676 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10680 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10682 mono_metadata_decode_value (sig, &sig);
10683 /* FIELD signature == 0x06 */
10684 g_assert (*sig == 0x06);
10686 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10687 if (!field->type) {
10688 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10689 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10695 mono_field_resolve_flags (MonoClassField *field)
10697 MonoClass *klass = field->parent;
10698 MonoImage *image = klass->image;
10699 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10700 int field_idx = field - klass->fields;
10704 MonoClassField *gfield = >d->fields [field_idx];
10705 return mono_field_get_flags (gfield);
10707 int idx = klass->field.first + field_idx;
10709 /*FIXME, in theory we do not lazy load SRE fields*/
10710 g_assert (!image_is_dynamic (image));
10712 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10717 * mono_class_setup_basic_field_info:
10718 * @class: The class to initialize
10720 * Initializes the klass->fields array of fields.
10721 * Aquires the loader lock.
10724 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10726 mono_loader_lock ();
10727 mono_class_setup_basic_field_info (klass);
10728 mono_loader_unlock ();
10732 * mono_class_get_fields_lazy:
10733 * @klass: the MonoClass to act on
10735 * This routine is an iterator routine for retrieving the fields in a class.
10736 * Only minimal information about fields are loaded. Accessors must be used
10737 * for all MonoClassField returned.
10739 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10740 * iterate over all of the elements. When no more values are
10741 * available, the return value is NULL.
10743 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10746 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10748 MonoClassField* field;
10752 mono_class_setup_basic_field_info_locking (klass);
10753 if (!klass->fields)
10755 /* start from the first */
10756 if (klass->field.count) {
10757 *iter = &klass->fields [0];
10758 return (MonoClassField *)*iter;
10764 field = (MonoClassField *)*iter;
10766 if (field < &klass->fields [klass->field.count]) {
10768 return (MonoClassField *)*iter;
10774 mono_class_full_name (MonoClass *klass)
10776 return mono_type_full_name (&klass->byval_arg);
10779 /* Declare all shared lazy type lookup functions */
10780 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)