2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
10 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
20 #include <mono/metadata/image.h>
21 #include <mono/metadata/image-internals.h>
22 #include <mono/metadata/assembly.h>
23 #include <mono/metadata/assembly-internals.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internals.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internals.h>
46 #include <mono/utils/mono-memory-model.h>
47 #include <mono/utils/atomic.h>
48 #include <mono/utils/bsearch.h>
49 #include <mono/utils/checked-build.h>
53 gboolean mono_print_vtable = FALSE;
54 gboolean mono_align_small_structs = FALSE;
57 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
58 guint32 classes_size, class_ext_size;
60 /* Low level lock which protects data structures in this module */
61 static mono_mutex_t classes_mutex;
63 /* Function supplied by the runtime to find classes by name using information from the AOT file */
64 static MonoGetClassFromName get_class_from_name = NULL;
66 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
67 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
68 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
69 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
70 static int generic_array_methods (MonoClass *klass);
71 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
73 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
74 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
75 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
76 static guint32 mono_field_resolve_flags (MonoClassField *field);
77 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
78 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
80 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
81 static gpointer mono_class_get_exception_data (const MonoClass *klass);
85 We use gclass recording to allow recursive system f types to be referenced by a parent.
87 Given the following type hierarchy:
89 class TextBox : TextBoxBase<TextBox> {}
90 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
91 class TextInput<T> : Input<T> where T: TextInput<T> {}
94 The runtime tries to load TextBoxBase<>.
95 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
96 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
97 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
99 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
100 at this point, iow, both are registered in the type map and both and a NULL parent. This means
101 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
103 To fix that what we do is to record all generic instantes created while resolving the parent of
104 any generic type definition and, after resolved, correct the parent field if needed.
107 static int record_gclass_instantiation;
108 static GSList *gclass_recorded_list;
109 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
111 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
112 static MonoNativeTlsKey setup_fields_tls_id;
114 static MonoNativeTlsKey init_pending_tls_id;
119 mono_locks_os_acquire (&classes_mutex, ClassesLock);
123 classes_unlock (void)
125 mono_locks_os_release (&classes_mutex, ClassesLock);
129 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
132 enable_gclass_recording (void)
134 ++record_gclass_instantiation;
138 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
141 disable_gclass_recording (gclass_record_func func, void *user_data)
143 GSList **head = &gclass_recorded_list;
145 g_assert (record_gclass_instantiation > 0);
146 --record_gclass_instantiation;
149 GSList *node = *head;
150 if (func ((MonoClass*)node->data, user_data)) {
152 g_slist_free_1 (node);
158 /* We automatically discard all recorded gclasses when disabled. */
159 if (!record_gclass_instantiation && gclass_recorded_list) {
160 g_slist_free (gclass_recorded_list);
161 gclass_recorded_list = NULL;
166 * mono_class_from_typeref:
167 * @image: a MonoImage
168 * @type_token: a TypeRef token
170 * Creates the MonoClass* structure representing the type defined by
171 * the typeref token valid inside @image.
172 * Returns: The MonoClass* representing the typeref token, NULL ifcould
176 mono_class_from_typeref (MonoImage *image, guint32 type_token)
179 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
180 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
185 * mono_class_from_typeref_checked:
186 * @image: a MonoImage
187 * @type_token: a TypeRef token
188 * @error: error return code, if any.
190 * Creates the MonoClass* structure representing the type defined by
191 * the typeref token valid inside @image.
193 * Returns: The MonoClass* representing the typeref token, NULL if it could
194 * not be loaded with the @error value filled with the information about the
198 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
200 guint32 cols [MONO_TYPEREF_SIZE];
201 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
203 const char *name, *nspace;
204 MonoClass *res = NULL;
207 mono_error_init (error);
209 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
212 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
214 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
215 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
217 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
218 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
219 case MONO_RESOLUTION_SCOPE_MODULE:
221 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
222 This is not the observed behavior of existing implementations.
223 The defacto behavior is that it's just a typedef in disguise.
225 /* a typedef in disguise */
226 res = mono_class_from_name_checked (image, nspace, name, error);
229 case MONO_RESOLUTION_SCOPE_MODULEREF:
230 module = mono_image_load_module_checked (image, idx, error);
232 res = mono_class_from_name_checked (module, nspace, name, error);
235 case MONO_RESOLUTION_SCOPE_TYPEREF: {
236 MonoClass *enclosing;
239 if (idx == mono_metadata_token_index (type_token)) {
240 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
244 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
245 return_val_if_nok (error, NULL);
247 if (enclosing->nested_classes_inited && enclosing->ext) {
248 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
249 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
250 res = (MonoClass *)tmp->data;
251 if (strcmp (res->name, name) == 0)
255 /* Don't call mono_class_init as we might've been called by it recursively */
256 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
258 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
259 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
260 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
262 if (strcmp (nname, name) == 0)
263 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
265 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
268 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
271 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
275 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
276 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
280 if (!image->references || !image->references [idx - 1])
281 mono_assembly_load_reference (image, idx - 1);
282 g_assert (image->references [idx - 1]);
284 /* If the assembly did not load, register this as a type load exception */
285 if (image->references [idx - 1] == REFERENCE_MISSING){
286 MonoAssemblyName aname;
289 mono_assembly_get_assemblyref (image, idx - 1, &aname);
290 human_name = mono_stringify_assembly_name (&aname);
291 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
295 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
298 /* Generic case, should be avoided for when a better error is possible. */
299 if (!res && mono_error_ok (error)) {
300 char *name = mono_class_name_from_token (image, type_token);
301 char *assembly = mono_assembly_name_from_token (image, type_token);
302 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
309 mono_image_memdup (MonoImage *image, void *data, guint size)
311 void *res = mono_image_alloc (image, size);
312 memcpy (res, data, size);
316 /* Copy everything mono_metadata_free_array free. */
318 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
321 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
323 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
325 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
327 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
329 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
331 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
336 /* Copy everything mono_metadata_free_method_signature free. */
338 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
342 sig = mono_metadata_signature_dup_full (image, sig);
344 sig->ret = mono_metadata_type_dup (image, sig->ret);
345 for (i = 0; i < sig->param_count; ++i)
346 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
352 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
354 MonoAssembly *ta = klass->image->assembly;
357 name = mono_stringify_assembly_name (&ta->aname);
358 g_string_append_printf (str, ", %s", name);
363 mono_type_name_check_byref (MonoType *type, GString *str)
366 g_string_append_c (str, '&');
370 * mono_identifier_escape_type_name_chars:
371 * @str: a destination string
372 * @identifier: an IDENTIFIER in internal form
376 * The displayed form of the identifier is appended to str.
378 * The displayed form of an identifier has the characters ,+&*[]\
379 * that have special meaning in type names escaped with a preceeding
380 * backslash (\) character.
383 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
389 // reserve space for common case: there will be no escaped characters.
390 g_string_set_size(str, n + strlen(identifier));
391 g_string_set_size(str, n);
393 for (const char* s = identifier; *s != 0 ; s++) {
402 g_string_append_c (str, '\\');
403 g_string_append_c (str, *s);
406 g_string_append_c (str, *s);
414 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
415 MonoTypeNameFormat format)
419 switch (type->type) {
420 case MONO_TYPE_ARRAY: {
421 int i, rank = type->data.array->rank;
422 MonoTypeNameFormat nested_format;
424 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
425 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
427 mono_type_get_name_recurse (
428 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
429 g_string_append_c (str, '[');
431 g_string_append_c (str, '*');
432 for (i = 1; i < rank; i++)
433 g_string_append_c (str, ',');
434 g_string_append_c (str, ']');
436 mono_type_name_check_byref (type, str);
438 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
439 _mono_type_get_assembly_name (type->data.array->eklass, str);
442 case MONO_TYPE_SZARRAY: {
443 MonoTypeNameFormat nested_format;
445 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
446 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
448 mono_type_get_name_recurse (
449 &type->data.klass->byval_arg, str, FALSE, nested_format);
450 g_string_append (str, "[]");
452 mono_type_name_check_byref (type, str);
454 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
455 _mono_type_get_assembly_name (type->data.klass, str);
458 case MONO_TYPE_PTR: {
459 MonoTypeNameFormat nested_format;
461 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
462 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
464 mono_type_get_name_recurse (
465 type->data.type, str, FALSE, nested_format);
466 g_string_append_c (str, '*');
468 mono_type_name_check_byref (type, str);
470 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
471 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
476 if (!mono_generic_param_info (type->data.generic_param))
477 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
479 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
481 mono_type_name_check_byref (type, str);
485 klass = mono_class_from_mono_type (type);
486 if (klass->nested_in) {
487 mono_type_get_name_recurse (
488 &klass->nested_in->byval_arg, str, TRUE, format);
489 if (format == MONO_TYPE_NAME_FORMAT_IL)
490 g_string_append_c (str, '.');
492 g_string_append_c (str, '+');
493 } else if (*klass->name_space) {
494 if (format == MONO_TYPE_NAME_FORMAT_IL)
495 g_string_append (str, klass->name_space);
497 mono_identifier_escape_type_name_chars (str, klass->name_space);
498 g_string_append_c (str, '.');
500 if (format == MONO_TYPE_NAME_FORMAT_IL) {
501 char *s = strchr (klass->name, '`');
502 int len = s ? s - klass->name : strlen (klass->name);
503 g_string_append_len (str, klass->name, len);
505 mono_identifier_escape_type_name_chars (str, klass->name);
509 if (klass->generic_class) {
510 MonoGenericClass *gclass = klass->generic_class;
511 MonoGenericInst *inst = gclass->context.class_inst;
512 MonoTypeNameFormat nested_format;
515 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
516 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
518 if (format == MONO_TYPE_NAME_FORMAT_IL)
519 g_string_append_c (str, '<');
521 g_string_append_c (str, '[');
522 for (i = 0; i < inst->type_argc; i++) {
523 MonoType *t = inst->type_argv [i];
526 g_string_append_c (str, ',');
527 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
528 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
529 g_string_append_c (str, '[');
530 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
531 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
532 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
533 g_string_append_c (str, ']');
535 if (format == MONO_TYPE_NAME_FORMAT_IL)
536 g_string_append_c (str, '>');
538 g_string_append_c (str, ']');
539 } else if (klass->generic_container &&
540 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
541 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
544 if (format == MONO_TYPE_NAME_FORMAT_IL)
545 g_string_append_c (str, '<');
547 g_string_append_c (str, '[');
548 for (i = 0; i < klass->generic_container->type_argc; i++) {
550 g_string_append_c (str, ',');
551 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
553 if (format == MONO_TYPE_NAME_FORMAT_IL)
554 g_string_append_c (str, '>');
556 g_string_append_c (str, ']');
559 mono_type_name_check_byref (type, str);
561 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
562 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
563 _mono_type_get_assembly_name (klass, str);
569 * mono_type_get_name_full:
571 * @format: the format for the return string.
574 * Returns: The string representation in a number of formats:
576 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
577 * returned in the formatrequired by System.Reflection, this is the
578 * inverse of mono_reflection_parse_type ().
580 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
581 * be used by the IL assembler.
583 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
585 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
588 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
592 result = g_string_new ("");
594 mono_type_get_name_recurse (type, result, FALSE, format);
596 return g_string_free (result, FALSE);
600 * mono_type_get_full_name:
603 * Returns: The string representation for type as required by System.Reflection.
604 * The inverse of mono_reflection_parse_type ().
607 mono_type_get_full_name (MonoClass *klass)
609 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
613 * mono_type_get_name:
616 * Returns: The string representation for type as it would be represented in IL code.
619 mono_type_get_name (MonoType *type)
621 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
625 * mono_type_get_underlying_type:
628 * Returns: The MonoType for the underlying integer type if @type
629 * is an enum and byref is false, otherwise the type itself.
632 mono_type_get_underlying_type (MonoType *type)
634 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
635 return mono_class_enum_basetype (type->data.klass);
636 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.generic_class->container_class);
642 * mono_class_is_open_constructed_type:
645 * Returns: TRUE if type represents a generics open constructed type.
646 * IOW, not all type parameters required for the instantiation have
647 * been provided or it's a generic type definition.
649 * An open constructed type means it's a non realizable type. Not to
650 * be mixed up with an abstract type - we can't cast or dispatch to
651 * an open type, for example.
654 mono_class_is_open_constructed_type (MonoType *t)
660 case MONO_TYPE_SZARRAY:
661 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
662 case MONO_TYPE_ARRAY:
663 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
665 return mono_class_is_open_constructed_type (t->data.type);
666 case MONO_TYPE_GENERICINST:
667 return t->data.generic_class->context.class_inst->is_open;
668 case MONO_TYPE_CLASS:
669 case MONO_TYPE_VALUETYPE:
670 return t->data.klass->generic_container != NULL;
677 This is a simple function to catch the most common bad instances of generic types.
678 Specially those that might lead to further failures in the runtime.
681 is_valid_generic_argument (MonoType *type)
683 switch (type->type) {
685 //case MONO_TYPE_TYPEDBYREF:
693 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
695 mono_error_init (error);
697 switch (type->type) {
698 case MONO_TYPE_MVAR: {
700 int num = mono_type_get_generic_param_num (type);
701 MonoGenericInst *inst = context->method_inst;
704 if (num >= inst->type_argc) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
707 num, info ? info->name : "", inst->type_argc);
711 if (!is_valid_generic_argument (inst->type_argv [num])) {
712 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
713 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
714 num, info ? info->name : "", inst->type_argv [num]->type);
718 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
719 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
720 * ->byref and ->attrs from @type are propagated to the returned type.
722 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
723 nt->byref = type->byref;
724 nt->attrs = type->attrs;
727 case MONO_TYPE_VAR: {
729 int num = mono_type_get_generic_param_num (type);
730 MonoGenericInst *inst = context->class_inst;
733 if (num >= inst->type_argc) {
734 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
736 num, info ? info->name : "", inst->type_argc);
739 if (!is_valid_generic_argument (inst->type_argv [num])) {
740 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
741 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
742 num, info ? info->name : "", inst->type_argv [num]->type);
745 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
746 nt->byref = type->byref;
747 nt->attrs = type->attrs;
750 case MONO_TYPE_SZARRAY: {
751 MonoClass *eclass = type->data.klass;
752 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
753 if (!inflated || !mono_error_ok (error))
755 nt = mono_metadata_type_dup (image, type);
756 nt->data.klass = mono_class_from_mono_type (inflated);
757 mono_metadata_free_type (inflated);
760 case MONO_TYPE_ARRAY: {
761 MonoClass *eclass = type->data.array->eklass;
762 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
763 if (!inflated || !mono_error_ok (error))
765 nt = mono_metadata_type_dup (image, type);
766 nt->data.array->eklass = mono_class_from_mono_type (inflated);
767 mono_metadata_free_type (inflated);
770 case MONO_TYPE_GENERICINST: {
771 MonoGenericClass *gclass = type->data.generic_class;
772 MonoGenericInst *inst;
774 if (!gclass->context.class_inst->is_open)
777 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
778 return_val_if_nok (error, NULL);
780 if (inst != gclass->context.class_inst)
781 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
783 if (gclass == type->data.generic_class)
786 nt = mono_metadata_type_dup (image, type);
787 nt->data.generic_class = gclass;
790 case MONO_TYPE_CLASS:
791 case MONO_TYPE_VALUETYPE: {
792 MonoClass *klass = type->data.klass;
793 MonoGenericContainer *container = klass->generic_container;
794 MonoGenericInst *inst;
795 MonoGenericClass *gclass = NULL;
801 /* We can't use context->class_inst directly, since it can have more elements */
802 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
803 return_val_if_nok (error, NULL);
805 if (inst == container->context.class_inst)
808 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
810 nt = mono_metadata_type_dup (image, type);
811 nt->type = MONO_TYPE_GENERICINST;
812 nt->data.generic_class = gclass;
822 mono_generic_class_get_context (MonoGenericClass *gclass)
824 return &gclass->context;
828 mono_class_get_context (MonoClass *klass)
830 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
834 * mono_class_get_generic_container:
836 * Return the generic container of KLASS which should be a generic type definition.
838 MonoGenericContainer*
839 mono_class_get_generic_container (MonoClass *klass)
841 g_assert (klass->is_generic);
843 return klass->generic_container;
847 * mono_class_get_generic_class:
849 * Return the MonoGenericClass of KLASS, which should be a generic instance.
852 mono_class_get_generic_class (MonoClass *klass)
854 g_assert (klass->is_inflated);
856 return klass->generic_class;
860 * mono_class_inflate_generic_type_with_mempool:
861 * @mempool: a mempool
863 * @context: a generics context
864 * @error: error context
866 * The same as mono_class_inflate_generic_type, but allocates the MonoType
867 * from mempool if it is non-NULL. If it is NULL, the MonoType is
868 * allocated on the heap and is owned by the caller.
869 * The returned type can potentially be the same as TYPE, so it should not be
870 * modified by the caller, and it should be freed using mono_metadata_free_type ().
873 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
875 MonoType *inflated = NULL;
876 mono_error_init (error);
879 inflated = inflate_generic_type (image, type, context, error);
880 return_val_if_nok (error, NULL);
883 MonoType *shared = mono_metadata_get_shared_type (type);
888 return mono_metadata_type_dup (image, type);
892 mono_stats.inflated_type_count++;
897 * mono_class_inflate_generic_type:
899 * @context: a generics context
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller. Returns NULL on error.
907 * @deprecated Please use mono_class_inflate_generic_type_checked instead
910 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
914 result = mono_class_inflate_generic_type_checked (type, context, &error);
915 mono_error_cleanup (&error);
920 * mono_class_inflate_generic_type:
922 * @context: a generics context
923 * @error: error context to use
925 * If @type is a generic type and @context is not NULL, instantiate it using the
926 * generics context @context.
928 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
929 * on the heap and is owned by the caller.
932 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
934 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
938 * mono_class_inflate_generic_type_no_copy:
940 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
944 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
946 MonoType *inflated = NULL;
948 mono_error_init (error);
950 inflated = inflate_generic_type (image, type, context, error);
951 return_val_if_nok (error, NULL);
957 mono_stats.inflated_type_count++;
962 * mono_class_inflate_generic_class:
964 * Inflate the class @gklass with @context. Set @error on failure.
967 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
972 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
973 return_val_if_nok (error, NULL);
975 res = mono_class_from_mono_type (inflated);
976 mono_metadata_free_type (inflated);
981 static MonoGenericContext
982 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
984 MonoGenericInst *class_inst = NULL;
985 MonoGenericInst *method_inst = NULL;
986 MonoGenericContext res = { NULL, NULL };
988 mono_error_init (error);
990 if (context->class_inst) {
991 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
992 if (!mono_error_ok (error))
996 if (context->method_inst) {
997 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
998 if (!mono_error_ok (error))
1002 res.class_inst = class_inst;
1003 res.method_inst = method_inst;
1009 * mono_class_inflate_generic_method:
1010 * @method: a generic method
1011 * @context: a generics context
1013 * Instantiate the generic method @method using the generics context @context.
1015 * Returns: The new instantiated method
1018 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1020 return mono_class_inflate_generic_method_full (method, NULL, context);
1024 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1026 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1030 * mono_class_inflate_generic_method_full:
1032 * Instantiate method @method with the generic context @context.
1033 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1034 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1037 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1040 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1041 if (!mono_error_ok (&error))
1042 /*FIXME do proper error handling - on this case, kill this function. */
1043 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1049 * mono_class_inflate_generic_method_full_checked:
1050 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1053 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1056 MonoMethodInflated *iresult, *cached;
1057 MonoMethodSignature *sig;
1058 MonoGenericContext tmp_context;
1060 mono_error_init (error);
1062 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1063 while (method->is_inflated) {
1064 MonoGenericContext *method_context = mono_method_get_context (method);
1065 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1067 tmp_context = inflate_generic_context (method_context, context, error);
1068 return_val_if_nok (error, NULL);
1070 context = &tmp_context;
1072 if (mono_metadata_generic_context_equal (method_context, context))
1075 method = imethod->declaring;
1079 * A method only needs to be inflated if the context has argument for which it is
1082 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1083 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1086 if (!((method->is_generic && context->method_inst) ||
1087 (method->klass->generic_container && context->class_inst)))
1090 iresult = g_new0 (MonoMethodInflated, 1);
1091 iresult->context = *context;
1092 iresult->declaring = method;
1094 if (!context->method_inst && method->is_generic)
1095 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1097 if (!context->class_inst) {
1098 g_assert (!iresult->declaring->klass->generic_class);
1099 if (iresult->declaring->klass->generic_container)
1100 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1101 else if (iresult->declaring->klass->generic_class)
1102 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1104 /* This can happen with some callers like mono_object_get_virtual_method () */
1105 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1106 iresult->context.class_inst = NULL;
1108 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1111 mono_image_set_lock (set);
1112 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1113 mono_image_set_unlock (set);
1117 return (MonoMethod*)cached;
1120 mono_stats.inflated_method_count++;
1122 inflated_methods_size += sizeof (MonoMethodInflated);
1124 sig = mono_method_signature (method);
1126 char *name = mono_type_get_full_name (method->klass);
1127 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1133 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1135 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1138 result = (MonoMethod *) iresult;
1139 result->is_inflated = TRUE;
1140 result->is_generic = FALSE;
1141 result->sre_method = FALSE;
1142 result->signature = NULL;
1144 if (method->wrapper_type) {
1145 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1146 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1147 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1149 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1150 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1153 if (iresult->context.method_inst) {
1154 /* Set the generic_container of the result to the generic_container of method */
1155 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1157 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1158 result->is_generic = 1;
1159 mono_method_set_generic_container (result, generic_container);
1163 if (!klass_hint || !klass_hint->generic_class ||
1164 klass_hint->generic_class->container_class != method->klass ||
1165 klass_hint->generic_class->context.class_inst != context->class_inst)
1168 if (method->klass->generic_container)
1169 result->klass = klass_hint;
1171 if (!result->klass) {
1172 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1173 if (!mono_error_ok (error))
1176 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1178 mono_metadata_free_type (inflated);
1182 * FIXME: This should hold, but it doesn't:
1184 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1185 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1186 * g_assert (result->is_generic);
1189 * Fixing this here causes other things to break, hence a very
1190 * ugly hack in mini-trampolines.c - see
1191 * is_generic_method_definition().
1195 mono_image_set_lock (set);
1196 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1198 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1199 iresult->owner = set;
1202 mono_image_set_unlock (set);
1204 return (MonoMethod*)cached;
1212 * mono_get_inflated_method:
1214 * Obsolete. We keep it around since it's mentioned in the public API.
1217 mono_get_inflated_method (MonoMethod *method)
1223 * mono_method_get_context_general:
1225 * @uninflated: handle uninflated methods?
1227 * Returns the generic context of a method or NULL if it doesn't have
1228 * one. For an inflated method that's the context stored in the
1229 * method. Otherwise it's in the method's generic container or in the
1230 * generic container of the method's class.
1233 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1235 if (method->is_inflated) {
1236 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1237 return &imethod->context;
1241 if (method->is_generic)
1242 return &(mono_method_get_generic_container (method)->context);
1243 if (method->klass->generic_container)
1244 return &method->klass->generic_container->context;
1249 * mono_method_get_context:
1252 * Returns the generic context for method if it's inflated, otherwise
1256 mono_method_get_context (MonoMethod *method)
1258 return mono_method_get_context_general (method, FALSE);
1262 * mono_method_get_generic_container:
1264 * Returns the generic container of METHOD, which should be a generic method definition.
1265 * Returns NULL if METHOD is not a generic method definition.
1266 * LOCKING: Acquires the loader lock.
1268 MonoGenericContainer*
1269 mono_method_get_generic_container (MonoMethod *method)
1271 MonoGenericContainer *container;
1273 if (!method->is_generic)
1276 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1277 g_assert (container);
1283 * mono_method_set_generic_container:
1285 * Sets the generic container of METHOD to CONTAINER.
1286 * LOCKING: Acquires the image lock.
1289 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1291 g_assert (method->is_generic);
1293 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1297 * mono_class_find_enum_basetype:
1298 * @class: The enum class
1300 * Determine the basetype of an enum by iterating through its fields. We do this
1301 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1304 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1306 MonoGenericContainer *container = NULL;
1307 MonoImage *m = klass->image;
1308 const int top = klass->field.count;
1311 g_assert (klass->enumtype);
1313 mono_error_init (error);
1315 if (klass->generic_container)
1316 container = klass->generic_container;
1317 else if (klass->generic_class) {
1318 MonoClass *gklass = klass->generic_class->container_class;
1320 container = gklass->generic_container;
1321 g_assert (container);
1325 * Fetch all the field information.
1327 for (i = 0; i < top; i++){
1329 guint32 cols [MONO_FIELD_SIZE];
1330 int idx = klass->field.first + i;
1333 /* klass->field.first and idx points into the fieldptr table */
1334 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1336 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1339 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1340 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1344 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1345 mono_metadata_decode_value (sig, &sig);
1346 /* FIELD signature == 0x06 */
1348 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1352 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1356 if (klass->generic_class) {
1357 //FIXME do we leak here?
1358 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1359 if (!mono_error_ok (error))
1361 ftype->attrs = cols [MONO_FIELD_FLAGS];
1366 mono_error_set_type_load_class (error, klass, "Could not find base type");
1373 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1376 mono_type_has_exceptions (MonoType *type)
1378 switch (type->type) {
1379 case MONO_TYPE_CLASS:
1380 case MONO_TYPE_VALUETYPE:
1381 case MONO_TYPE_SZARRAY:
1382 return mono_class_has_failure (type->data.klass);
1383 case MONO_TYPE_ARRAY:
1384 return mono_class_has_failure (type->data.array->eklass);
1385 case MONO_TYPE_GENERICINST:
1386 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1393 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1395 g_assert (mono_class_has_failure (klass));
1396 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1397 mono_error_set_from_boxed (oerror, box);
1404 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1408 mono_class_alloc (MonoClass *klass, int size)
1410 if (klass->generic_class)
1411 return mono_image_set_alloc (klass->generic_class->owner, size);
1413 return mono_image_alloc (klass->image, size);
1417 mono_class_alloc0 (MonoClass *klass, int size)
1421 res = mono_class_alloc (klass, size);
1422 memset (res, 0, size);
1426 #define mono_class_new0(klass,struct_type, n_structs) \
1427 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1430 * mono_class_setup_basic_field_info:
1431 * @class: The class to initialize
1433 * Initializes the following fields in MonoClass:
1434 * * klass->fields (only field->parent and field->name)
1435 * * klass->field.count
1436 * * klass->field.first
1437 * LOCKING: Acquires the loader lock
1440 mono_class_setup_basic_field_info (MonoClass *klass)
1442 MonoClassField *field;
1443 MonoClassField *fields;
1451 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1452 image = klass->image;
1454 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1456 * This happens when a generic instance of an unfinished generic typebuilder
1457 * is used as an element type for creating an array type. We can't initialize
1458 * the fields of this class using the fields of gklass, since gklass is not
1459 * finished yet, fields could be added to it later.
1465 mono_class_setup_basic_field_info (gtd);
1467 mono_loader_lock ();
1468 klass->field.first = gtd->field.first;
1469 klass->field.count = gtd->field.count;
1470 mono_loader_unlock ();
1473 top = klass->field.count;
1475 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1478 * Fetch all the field information.
1480 for (i = 0; i < top; i++){
1481 field = &fields [i];
1482 field->parent = klass;
1485 field->name = mono_field_get_name (>d->fields [i]);
1487 int idx = klass->field.first + i;
1488 /* klass->field.first and idx points into the fieldptr table */
1489 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1490 /* The name is needed for fieldrefs */
1491 field->name = mono_metadata_string_heap (image, name_idx);
1495 mono_memory_barrier ();
1497 mono_loader_lock ();
1499 klass->fields = fields;
1500 mono_loader_unlock ();
1504 * mono_class_set_failure_causedby_class:
1505 * @klass: the class that is failing
1506 * @caused_by: the class that caused the failure
1507 * @msg: Why @klass is failing.
1509 * If @caused_by has a failure, sets a TypeLoadException failure on
1510 * @klass with message "@msg, due to: {@caused_by message}".
1512 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1515 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1517 if (mono_class_has_failure (caused_by)) {
1518 MonoError cause_error;
1519 mono_error_init (&cause_error);
1520 mono_error_set_for_class_failure (&cause_error, caused_by);
1521 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1522 mono_error_cleanup (&cause_error);
1531 * mono_class_setup_fields:
1532 * @klass: The class to initialize
1534 * Initializes klass->fields, computes class layout and sizes.
1535 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1536 * Sets the following fields in @klass:
1537 * - all the fields initialized by mono_class_init_sizes ()
1538 * - element_class/cast_class (for enums)
1539 * - field->type/offset for all fields
1542 * LOCKING: Acquires the loader lock.
1545 mono_class_setup_fields (MonoClass *klass)
1548 MonoImage *m = klass->image;
1550 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1552 guint32 real_size = 0;
1553 guint32 packing_size = 0;
1555 gboolean explicit_size;
1556 MonoClassField *field;
1559 if (klass->fields_inited)
1562 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1564 * This happens when a generic instance of an unfinished generic typebuilder
1565 * is used as an element type for creating an array type. We can't initialize
1566 * the fields of this class using the fields of gklass, since gklass is not
1567 * finished yet, fields could be added to it later.
1572 mono_class_setup_basic_field_info (klass);
1573 top = klass->field.count;
1575 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1577 mono_class_setup_fields (gtd);
1578 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1583 if (klass->parent) {
1584 /* For generic instances, klass->parent might not have been initialized */
1585 mono_class_init (klass->parent);
1586 mono_class_setup_fields (klass->parent);
1587 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1589 instance_size = klass->parent->instance_size;
1591 instance_size = sizeof (MonoObject);
1594 /* Get the real size */
1595 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1597 instance_size += real_size;
1600 * This function can recursively call itself.
1601 * Prevent infinite recursion by using a list in TLS.
1603 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1604 if (g_slist_find (init_list, klass))
1606 init_list = g_slist_prepend (init_list, klass);
1607 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1610 * Fetch all the field information.
1612 for (i = 0; i < top; i++) {
1613 int idx = klass->field.first + i;
1614 field = &klass->fields [i];
1617 mono_field_resolve_type (field, &error);
1618 if (!mono_error_ok (&error)) {
1619 /*mono_field_resolve_type already failed class*/
1620 mono_error_cleanup (&error);
1624 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1625 g_assert (field->type);
1628 if (mono_field_is_deleted (field))
1630 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1632 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1633 int offset = uoffset;
1635 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1636 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1639 if (offset < -1) { /*-1 is used to encode special static fields */
1640 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1643 if (klass->generic_container) {
1644 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1648 if (mono_type_has_exceptions (field->type)) {
1649 char *class_name = mono_type_get_full_name (klass);
1650 char *type_name = mono_type_full_name (field->type);
1652 mono_class_set_type_load_failure (klass, "");
1653 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1654 g_free (class_name);
1658 /* The def_value of fields is compute lazily during vtable creation */
1661 if (!mono_class_has_failure (klass))
1662 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1664 init_list = g_slist_remove (init_list, klass);
1665 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1669 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1672 klass->instance_size = cached_info->instance_size;
1673 klass->sizes.class_size = cached_info->class_size;
1674 klass->packing_size = cached_info->packing_size;
1675 klass->min_align = cached_info->min_align;
1676 klass->blittable = cached_info->blittable;
1677 klass->has_references = cached_info->has_references;
1678 klass->has_static_refs = cached_info->has_static_refs;
1679 klass->no_special_static_fields = cached_info->no_special_static_fields;
1682 if (!klass->size_inited)
1683 mono_class_setup_fields (klass);
1688 * mono_class_init_sizes:
1690 * Initializes the size related fields of @klass without loading all field data if possible.
1691 * Sets the following fields in @klass:
1693 * - sizes.class_size
1700 * Can fail the class.
1702 * LOCKING: Acquires the loader lock.
1705 mono_class_init_sizes (MonoClass *klass)
1707 MonoCachedClassInfo cached_info;
1708 gboolean has_cached_info;
1710 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1712 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1716 * mono_type_get_basic_type_from_generic:
1719 * Returns a closed type corresponding to the possibly open type
1723 mono_type_get_basic_type_from_generic (MonoType *type)
1725 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1726 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1727 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1728 return &mono_defaults.object_class->byval_arg;
1733 class_has_references (MonoClass *klass)
1735 mono_class_init_sizes (klass);
1738 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1739 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1742 return klass->has_references;
1746 type_has_references (MonoClass *klass, MonoType *ftype)
1748 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1750 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1751 MonoGenericParam *gparam = ftype->data.generic_param;
1753 if (gparam->gshared_constraint)
1754 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1760 * mono_class_layout_fields:
1762 * @base_instance_size: base instance size
1765 * This contains the common code for computing the layout of classes and sizes.
1766 * This should only be called from mono_class_setup_fields () and
1767 * typebuilder_setup_fields ().
1769 * LOCKING: Acquires the loader lock
1772 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1775 const int top = klass->field.count;
1776 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1777 guint32 pass, passes, real_size;
1778 gboolean gc_aware_layout = FALSE;
1779 gboolean has_static_fields = FALSE;
1780 gboolean has_references = FALSE;
1781 gboolean has_static_refs = FALSE;
1782 MonoClassField *field;
1784 int instance_size = base_instance_size;
1785 int class_size, min_align;
1789 * We want to avoid doing complicated work inside locks, so we compute all the required
1790 * information and write it to @klass inside a lock.
1792 if (klass->fields_inited)
1795 if ((packing_size & 0xffffff00) != 0) {
1796 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1800 if (klass->parent) {
1801 min_align = klass->parent->min_align;
1802 /* we use | since it may have been set already */
1803 has_references = klass->has_references | klass->parent->has_references;
1807 /* We can't really enable 16 bytes alignment until the GC supports it.
1808 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1809 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1810 Bug #506144 is an example of this issue.
1812 if (klass->simd_type)
1817 * When we do generic sharing we need to have layout
1818 * information for open generic classes (either with a generic
1819 * context containing type variables or with a generic
1820 * container), so we don't return in that case anymore.
1823 if (klass->enumtype) {
1824 for (i = 0; i < top; i++) {
1825 field = &klass->fields [i];
1826 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1827 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1832 if (!mono_class_enum_basetype (klass)) {
1833 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1839 * Enable GC aware auto layout: in this mode, reference
1840 * fields are grouped together inside objects, increasing collector
1842 * Requires that all classes whose layout is known to native code be annotated
1843 * with [StructLayout (LayoutKind.Sequential)]
1844 * Value types have gc_aware_layout disabled by default, as per
1845 * what the default is for other runtimes.
1847 /* corlib is missing [StructLayout] directives in many places */
1848 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1849 if (!klass->valuetype)
1850 gc_aware_layout = TRUE;
1853 /* Compute klass->blittable */
1856 blittable = klass->parent->blittable;
1857 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1859 for (i = 0; i < top; i++) {
1860 field = &klass->fields [i];
1862 if (mono_field_is_deleted (field))
1864 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1867 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1870 MonoClass *field_class = mono_class_from_mono_type (field->type);
1872 mono_class_setup_fields (field_class);
1873 if (mono_class_has_failure (field_class)) {
1874 MonoError field_error;
1875 mono_error_init (&field_error);
1876 mono_error_set_for_class_failure (&field_error, field_class);
1877 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1878 mono_error_cleanup (&field_error);
1882 if (!field_class || !field_class->blittable)
1886 if (klass->enumtype)
1887 blittable = klass->element_class->blittable;
1889 if (mono_class_has_failure (klass))
1891 if (klass == mono_defaults.string_class)
1894 /* Compute klass->has_references */
1896 * Process non-static fields first, since static fields might recursively
1897 * refer to the class itself.
1899 for (i = 0; i < top; i++) {
1902 field = &klass->fields [i];
1904 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1905 ftype = mono_type_get_underlying_type (field->type);
1906 ftype = mono_type_get_basic_type_from_generic (ftype);
1907 if (type_has_references (klass, ftype))
1908 has_references = TRUE;
1913 * Compute field layout and total size (not considering static fields)
1915 field_offsets = g_new0 (int, top);
1917 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1918 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1919 if (gc_aware_layout)
1924 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1927 if (klass->parent) {
1928 mono_class_setup_fields (klass->parent);
1929 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1931 real_size = klass->parent->instance_size;
1933 real_size = sizeof (MonoObject);
1936 for (pass = 0; pass < passes; ++pass) {
1937 for (i = 0; i < top; i++){
1942 field = &klass->fields [i];
1944 if (mono_field_is_deleted (field))
1946 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1949 ftype = mono_type_get_underlying_type (field->type);
1950 ftype = mono_type_get_basic_type_from_generic (ftype);
1951 if (gc_aware_layout) {
1952 if (type_has_references (klass, ftype)) {
1961 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1962 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1963 /* This field is a hack inserted by MCS to empty structures */
1967 size = mono_type_size (field->type, &align);
1969 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1970 align = packing_size ? MIN (packing_size, align): align;
1971 /* if the field has managed references, we need to force-align it
1974 if (type_has_references (klass, ftype))
1975 align = MAX (align, sizeof (gpointer));
1977 min_align = MAX (align, min_align);
1978 field_offsets [i] = real_size;
1980 field_offsets [i] += align - 1;
1981 field_offsets [i] &= ~(align - 1);
1983 /*TypeBuilders produce all sort of weird things*/
1984 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1985 real_size = field_offsets [i] + size;
1988 instance_size = MAX (real_size, instance_size);
1990 if (instance_size & (min_align - 1)) {
1991 instance_size += min_align - 1;
1992 instance_size &= ~(min_align - 1);
1996 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2000 for (i = 0; i < top; i++) {
2005 field = &klass->fields [i];
2008 * There must be info about all the fields in a type if it
2009 * uses explicit layout.
2011 if (mono_field_is_deleted (field))
2013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2016 size = mono_type_size (field->type, &align);
2017 align = packing_size ? MIN (packing_size, align): align;
2018 min_align = MAX (align, min_align);
2021 /* Already set by typebuilder_setup_fields () */
2022 field_offsets [i] = field->offset + sizeof (MonoObject);
2024 int idx = klass->field.first + i;
2026 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2027 field_offsets [i] = offset + sizeof (MonoObject);
2029 ftype = mono_type_get_underlying_type (field->type);
2030 ftype = mono_type_get_basic_type_from_generic (ftype);
2031 if (type_has_references (klass, ftype)) {
2032 if (field_offsets [i] % sizeof (gpointer)) {
2033 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2040 real_size = MAX (real_size, size + field_offsets [i]);
2043 if (klass->has_references) {
2044 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2046 /* Check for overlapping reference and non-reference fields */
2047 for (i = 0; i < top; i++) {
2050 field = &klass->fields [i];
2052 if (mono_field_is_deleted (field))
2054 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2056 ftype = mono_type_get_underlying_type (field->type);
2057 if (MONO_TYPE_IS_REFERENCE (ftype))
2058 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2060 for (i = 0; i < top; i++) {
2061 field = &klass->fields [i];
2063 if (mono_field_is_deleted (field))
2065 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2068 // FIXME: Too much code does this
2070 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2071 mono_class_set_type_load_failure (klass, "Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field_offsets [i]);
2075 g_free (ref_bitmap);
2078 instance_size = MAX (real_size, instance_size);
2079 if (instance_size & (min_align - 1)) {
2080 instance_size += min_align - 1;
2081 instance_size &= ~(min_align - 1);
2087 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2089 * This leads to all kinds of problems with nested structs, so only
2090 * enable it when a MONO_DEBUG property is set.
2092 * For small structs, set min_align to at least the struct size to improve
2093 * performance, and since the JIT memset/memcpy code assumes this and generates
2094 * unaligned accesses otherwise. See #78990 for a testcase.
2096 if (mono_align_small_structs && top) {
2097 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2098 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2102 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2103 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2104 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2105 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2107 /* Publish the data */
2108 mono_loader_lock ();
2109 if (klass->instance_size && !klass->image->dynamic) {
2110 /* Might be already set using cached info */
2111 g_assert (klass->instance_size == instance_size);
2113 klass->instance_size = instance_size;
2115 klass->blittable = blittable;
2116 klass->has_references = has_references;
2117 klass->packing_size = packing_size;
2118 klass->min_align = min_align;
2119 for (i = 0; i < top; ++i) {
2120 field = &klass->fields [i];
2121 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2122 klass->fields [i].offset = field_offsets [i];
2125 mono_memory_barrier ();
2126 klass->size_inited = 1;
2127 mono_loader_unlock ();
2130 * Compute static field layout and size
2131 * Static fields can reference the class itself, so this has to be
2132 * done after instance_size etc. are initialized.
2135 for (i = 0; i < top; i++) {
2139 field = &klass->fields [i];
2141 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2143 if (mono_field_is_deleted (field))
2146 if (mono_type_has_exceptions (field->type)) {
2147 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2151 has_static_fields = TRUE;
2153 size = mono_type_size (field->type, &align);
2154 field_offsets [i] = class_size;
2155 /*align is always non-zero here*/
2156 field_offsets [i] += align - 1;
2157 field_offsets [i] &= ~(align - 1);
2158 class_size = field_offsets [i] + size;
2161 if (has_static_fields && class_size == 0)
2162 /* Simplify code which depends on class_size != 0 if the class has static fields */
2165 /* Compute klass->has_static_refs */
2166 has_static_refs = FALSE;
2167 for (i = 0; i < top; i++) {
2170 field = &klass->fields [i];
2172 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2173 ftype = mono_type_get_underlying_type (field->type);
2174 ftype = mono_type_get_basic_type_from_generic (ftype);
2175 if (type_has_references (klass, ftype))
2176 has_static_refs = TRUE;
2180 /*valuetypes can't be neither bigger than 1Mb or empty. */
2181 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2182 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2184 /* Publish the data */
2185 mono_loader_lock ();
2187 klass->sizes.class_size = class_size;
2188 klass->has_static_refs = has_static_refs;
2189 for (i = 0; i < top; ++i) {
2190 field = &klass->fields [i];
2192 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2193 field->offset = field_offsets [i];
2196 mono_memory_barrier ();
2197 klass->fields_inited = 1;
2198 mono_loader_unlock ();
2200 g_free (field_offsets);
2204 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2208 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2209 method->klass = klass;
2210 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2211 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2212 method->signature = sig;
2213 method->name = name;
2216 if (name [0] == '.') {
2217 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2219 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2225 * mono_class_setup_methods:
2228 * Initializes the 'methods' array in CLASS.
2229 * Calling this method should be avoided if possible since it allocates a lot
2230 * of long-living MonoMethod structures.
2231 * Methods belonging to an interface are assigned a sequential slot starting
2234 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2237 mono_class_setup_methods (MonoClass *klass)
2240 MonoMethod **methods;
2245 if (klass->generic_class) {
2247 MonoClass *gklass = klass->generic_class->container_class;
2249 mono_class_init (gklass);
2250 if (!mono_class_has_failure (gklass))
2251 mono_class_setup_methods (gklass);
2252 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2255 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2256 count = gklass->method.count;
2257 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2259 for (i = 0; i < count; i++) {
2260 methods [i] = mono_class_inflate_generic_method_full_checked (
2261 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2262 if (!mono_error_ok (&error)) {
2263 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2264 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2267 mono_error_cleanup (&error);
2271 } else if (klass->rank) {
2273 MonoMethod *amethod;
2274 MonoMethodSignature *sig;
2275 int count_generic = 0, first_generic = 0;
2277 gboolean jagged_ctor = FALSE;
2279 count = 3 + (klass->rank > 1? 2: 1);
2281 mono_class_setup_interfaces (klass, &error);
2282 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2284 if (klass->rank == 1 && klass->element_class->rank) {
2286 klass->method.count ++;
2289 if (klass->interface_count) {
2290 count_generic = generic_array_methods (klass);
2291 first_generic = count;
2292 count += klass->interface_count * count_generic;
2295 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2297 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2298 sig->ret = &mono_defaults.void_class->byval_arg;
2299 sig->pinvoke = TRUE;
2300 sig->hasthis = TRUE;
2301 for (i = 0; i < klass->rank; ++i)
2302 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2304 amethod = create_array_method (klass, ".ctor", sig);
2305 methods [method_num++] = amethod;
2306 if (klass->rank > 1) {
2307 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2308 sig->ret = &mono_defaults.void_class->byval_arg;
2309 sig->pinvoke = TRUE;
2310 sig->hasthis = TRUE;
2311 for (i = 0; i < klass->rank * 2; ++i)
2312 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2314 amethod = create_array_method (klass, ".ctor", sig);
2315 methods [method_num++] = amethod;
2319 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2320 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2321 sig->ret = &mono_defaults.void_class->byval_arg;
2322 sig->pinvoke = TRUE;
2323 sig->hasthis = TRUE;
2324 for (i = 0; i < klass->rank + 1; ++i)
2325 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2326 amethod = create_array_method (klass, ".ctor", sig);
2327 methods [method_num++] = amethod;
2330 /* element Get (idx11, [idx2, ...]) */
2331 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2332 sig->ret = &klass->element_class->byval_arg;
2333 sig->pinvoke = TRUE;
2334 sig->hasthis = TRUE;
2335 for (i = 0; i < klass->rank; ++i)
2336 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2337 amethod = create_array_method (klass, "Get", sig);
2338 methods [method_num++] = amethod;
2339 /* element& Address (idx11, [idx2, ...]) */
2340 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2341 sig->ret = &klass->element_class->this_arg;
2342 sig->pinvoke = TRUE;
2343 sig->hasthis = TRUE;
2344 for (i = 0; i < klass->rank; ++i)
2345 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2346 amethod = create_array_method (klass, "Address", sig);
2347 methods [method_num++] = amethod;
2348 /* void Set (idx11, [idx2, ...], element) */
2349 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2350 sig->ret = &mono_defaults.void_class->byval_arg;
2351 sig->pinvoke = TRUE;
2352 sig->hasthis = TRUE;
2353 for (i = 0; i < klass->rank; ++i)
2354 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2355 sig->params [i] = &klass->element_class->byval_arg;
2356 amethod = create_array_method (klass, "Set", sig);
2357 methods [method_num++] = amethod;
2359 for (i = 0; i < klass->interface_count; i++)
2360 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2364 count = klass->method.count;
2365 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2366 for (i = 0; i < count; ++i) {
2367 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2368 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2370 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2371 mono_error_cleanup (&error);
2376 if (MONO_CLASS_IS_INTERFACE (klass)) {
2378 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2379 for (i = 0; i < count; ++i) {
2380 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2381 methods [i]->slot = slot++;
2385 mono_image_lock (klass->image);
2387 if (!klass->methods) {
2388 klass->method.count = count;
2390 /* Needed because of the double-checking locking pattern */
2391 mono_memory_barrier ();
2393 klass->methods = methods;
2396 mono_image_unlock (klass->image);
2400 * mono_class_get_method_by_index:
2402 * Returns klass->methods [index], initializing klass->methods if neccesary.
2404 * LOCKING: Acquires the loader lock.
2407 mono_class_get_method_by_index (MonoClass *klass, int index)
2410 /* Avoid calling setup_methods () if possible */
2411 if (klass->generic_class && !klass->methods) {
2412 MonoClass *gklass = klass->generic_class->container_class;
2415 m = mono_class_inflate_generic_method_full_checked (
2416 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2417 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2419 * If setup_methods () is called later for this class, no duplicates are created,
2420 * since inflate_generic_method guarantees that only one instance of a method
2421 * is created for each context.
2424 mono_class_setup_methods (klass);
2425 g_assert (m == klass->methods [index]);
2429 mono_class_setup_methods (klass);
2430 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2432 g_assert (index >= 0 && index < klass->method.count);
2433 return klass->methods [index];
2438 * mono_class_get_inflated_method:
2440 * Given an inflated class CLASS and a method METHOD which should be a method of
2441 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2444 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2446 MonoClass *gklass = klass->generic_class->container_class;
2449 g_assert (method->klass == gklass);
2451 mono_class_setup_methods (gklass);
2452 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2454 for (i = 0; i < gklass->method.count; ++i) {
2455 if (gklass->methods [i] == method) {
2456 if (klass->methods) {
2457 return klass->methods [i];
2460 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2461 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2471 * mono_class_get_vtable_entry:
2473 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2474 * LOCKING: Acquires the loader lock.
2477 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2481 if (klass->rank == 1) {
2483 * szarrays do not overwrite any methods of Array, so we can avoid
2484 * initializing their vtables in some cases.
2486 mono_class_setup_vtable (klass->parent);
2487 if (offset < klass->parent->vtable_size)
2488 return klass->parent->vtable [offset];
2491 if (klass->generic_class) {
2493 MonoClass *gklass = klass->generic_class->container_class;
2494 mono_class_setup_vtable (gklass);
2495 m = gklass->vtable [offset];
2497 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2498 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2500 mono_class_setup_vtable (klass);
2501 if (mono_class_has_failure (klass))
2503 m = klass->vtable [offset];
2510 * mono_class_get_vtable_size:
2512 * Return the vtable size for KLASS.
2515 mono_class_get_vtable_size (MonoClass *klass)
2517 mono_class_setup_vtable (klass);
2519 return klass->vtable_size;
2523 * mono_class_setup_properties:
2525 * Initialize klass->ext.property and klass->ext.properties.
2527 * This method can fail the class.
2530 mono_class_setup_properties (MonoClass *klass)
2532 guint startm, endm, i, j;
2533 guint32 cols [MONO_PROPERTY_SIZE];
2534 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2535 MonoProperty *properties;
2539 if (klass->ext && klass->ext->properties)
2542 if (klass->generic_class) {
2543 MonoClass *gklass = klass->generic_class->container_class;
2545 mono_class_init (gklass);
2546 mono_class_setup_properties (gklass);
2547 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2550 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2552 for (i = 0; i < gklass->ext->property.count; i++) {
2554 MonoProperty *prop = &properties [i];
2556 *prop = gklass->ext->properties [i];
2559 prop->get = mono_class_inflate_generic_method_full_checked (
2560 prop->get, klass, mono_class_get_context (klass), &error);
2562 prop->set = mono_class_inflate_generic_method_full_checked (
2563 prop->set, klass, mono_class_get_context (klass), &error);
2565 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2566 prop->parent = klass;
2569 first = gklass->ext->property.first;
2570 count = gklass->ext->property.count;
2572 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2573 count = last - first;
2576 mono_class_setup_methods (klass);
2577 if (mono_class_has_failure (klass))
2581 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2582 for (i = first; i < last; ++i) {
2583 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2584 properties [i - first].parent = klass;
2585 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2586 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2588 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2589 for (j = startm; j < endm; ++j) {
2592 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2594 if (klass->image->uncompressed_metadata) {
2596 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2597 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2598 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2600 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2603 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2604 case METHOD_SEMANTIC_SETTER:
2605 properties [i - first].set = method;
2607 case METHOD_SEMANTIC_GETTER:
2608 properties [i - first].get = method;
2617 mono_class_alloc_ext (klass);
2619 mono_image_lock (klass->image);
2621 if (klass->ext->properties) {
2622 /* We leak 'properties' which was allocated from the image mempool */
2623 mono_image_unlock (klass->image);
2627 klass->ext->property.first = first;
2628 klass->ext->property.count = count;
2630 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2631 mono_memory_barrier ();
2633 /* Leave this assignment as the last op in the function */
2634 klass->ext->properties = properties;
2636 mono_image_unlock (klass->image);
2640 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2642 MonoMethod **om, **retval;
2645 for (om = methods, count = 0; *om; ++om, ++count)
2648 retval = g_new0 (MonoMethod*, count + 1);
2650 for (om = methods, count = 0; *om; ++om, ++count) {
2652 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2653 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2659 /*This method can fail the class.*/
2661 mono_class_setup_events (MonoClass *klass)
2664 guint startm, endm, i, j;
2665 guint32 cols [MONO_EVENT_SIZE];
2666 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2670 if (klass->ext && klass->ext->events)
2673 if (klass->generic_class) {
2674 MonoClass *gklass = klass->generic_class->container_class;
2675 MonoGenericContext *context = NULL;
2677 mono_class_setup_events (gklass);
2678 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2681 first = gklass->ext->event.first;
2682 count = gklass->ext->event.count;
2684 events = mono_class_new0 (klass, MonoEvent, count);
2687 context = mono_class_get_context (klass);
2689 for (i = 0; i < count; i++) {
2691 MonoEvent *event = &events [i];
2692 MonoEvent *gevent = &gklass->ext->events [i];
2694 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2696 event->parent = klass;
2697 event->name = gevent->name;
2698 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2699 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2700 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2701 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2702 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2703 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2705 #ifndef MONO_SMALL_CONFIG
2706 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2708 event->attrs = gevent->attrs;
2711 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2712 count = last - first;
2715 mono_class_setup_methods (klass);
2716 if (mono_class_has_failure (klass)) {
2721 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2722 for (i = first; i < last; ++i) {
2723 MonoEvent *event = &events [i - first];
2725 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2726 event->parent = klass;
2727 event->attrs = cols [MONO_EVENT_FLAGS];
2728 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2730 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2731 for (j = startm; j < endm; ++j) {
2734 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2736 if (klass->image->uncompressed_metadata) {
2738 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2739 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2740 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2742 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2745 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2746 case METHOD_SEMANTIC_ADD_ON:
2747 event->add = method;
2749 case METHOD_SEMANTIC_REMOVE_ON:
2750 event->remove = method;
2752 case METHOD_SEMANTIC_FIRE:
2753 event->raise = method;
2755 case METHOD_SEMANTIC_OTHER: {
2756 #ifndef MONO_SMALL_CONFIG
2759 if (event->other == NULL) {
2760 event->other = g_new0 (MonoMethod*, 2);
2762 while (event->other [n])
2764 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2766 event->other [n] = method;
2767 /* NULL terminated */
2768 event->other [n + 1] = NULL;
2779 mono_class_alloc_ext (klass);
2781 mono_image_lock (klass->image);
2783 if (klass->ext->events) {
2784 mono_image_unlock (klass->image);
2788 klass->ext->event.first = first;
2789 klass->ext->event.count = count;
2791 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2792 mono_memory_barrier ();
2794 /* Leave this assignment as the last op in the function */
2795 klass->ext->events = events;
2797 mono_image_unlock (klass->image);
2801 * Global pool of interface IDs, represented as a bitset.
2802 * LOCKING: Protected by the classes lock.
2804 static MonoBitSet *global_interface_bitset = NULL;
2807 * mono_unload_interface_ids:
2808 * @bitset: bit set of interface IDs
2810 * When an image is unloaded, the interface IDs associated with
2811 * the image are put back in the global pool of IDs so the numbers
2815 mono_unload_interface_ids (MonoBitSet *bitset)
2818 mono_bitset_sub (global_interface_bitset, bitset);
2823 mono_unload_interface_id (MonoClass *klass)
2825 if (global_interface_bitset && klass->interface_id) {
2827 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2833 * mono_get_unique_iid:
2836 * Assign a unique integer ID to the interface represented by @class.
2837 * The ID will positive and as small as possible.
2838 * LOCKING: Acquires the classes lock.
2839 * Returns: The new ID.
2842 mono_get_unique_iid (MonoClass *klass)
2846 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2850 if (!global_interface_bitset) {
2851 global_interface_bitset = mono_bitset_new (128, 0);
2854 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2856 int old_size = mono_bitset_size (global_interface_bitset);
2857 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2858 mono_bitset_free (global_interface_bitset);
2859 global_interface_bitset = new_set;
2862 mono_bitset_set (global_interface_bitset, iid);
2863 /* set the bit also in the per-image set */
2864 if (!klass->generic_class) {
2865 if (klass->image->interface_bitset) {
2866 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2867 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2868 mono_bitset_free (klass->image->interface_bitset);
2869 klass->image->interface_bitset = new_set;
2872 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2874 mono_bitset_set (klass->image->interface_bitset, iid);
2879 #ifndef MONO_SMALL_CONFIG
2880 if (mono_print_vtable) {
2882 char *type_name = mono_type_full_name (&klass->byval_arg);
2883 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2884 generic_id = klass->generic_class->context.class_inst->id;
2885 g_assert (generic_id != 0);
2889 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2894 g_assert (iid <= 65535);
2899 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2904 mono_class_setup_interfaces (klass, error);
2905 return_if_nok (error);
2907 for (i = 0; i < klass->interface_count; i++) {
2908 ic = klass->interfaces [i];
2911 *res = g_ptr_array_new ();
2912 g_ptr_array_add (*res, ic);
2913 mono_class_init (ic);
2914 if (mono_class_has_failure (ic)) {
2915 mono_error_set_type_load_class (error, ic, "Error Loading class");
2919 collect_implemented_interfaces_aux (ic, res, error);
2920 return_if_nok (error);
2925 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2927 GPtrArray *res = NULL;
2929 collect_implemented_interfaces_aux (klass, &res, error);
2930 if (!mono_error_ok (error)) {
2932 g_ptr_array_free (res, TRUE);
2939 compare_interface_ids (const void *p_key, const void *p_element) {
2940 const MonoClass *key = (const MonoClass *)p_key;
2941 const MonoClass *element = *(const MonoClass **)p_element;
2943 return (key->interface_id - element->interface_id);
2946 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2948 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2949 MonoClass **result = (MonoClass **)mono_binary_search (
2951 klass->interfaces_packed,
2952 klass->interface_offsets_count,
2953 sizeof (MonoClass *),
2954 compare_interface_ids);
2956 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2963 * mono_class_interface_offset_with_variance:
2965 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2966 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2968 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2970 * FIXME figure out MS disambiguation rules and fix this function.
2973 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2974 int i = mono_class_interface_offset (klass, itf);
2975 *non_exact_match = FALSE;
2979 if (!mono_class_has_variant_generic_params (itf))
2982 for (i = 0; i < klass->interface_offsets_count; i++) {
2983 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2984 *non_exact_match = TRUE;
2985 return klass->interface_offsets_packed [i];
2993 print_implemented_interfaces (MonoClass *klass) {
2996 GPtrArray *ifaces = NULL;
2998 int ancestor_level = 0;
3000 name = mono_type_get_full_name (klass);
3001 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3004 for (i = 0; i < klass->interface_offsets_count; i++)
3005 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3006 klass->interfaces_packed [i]->interface_id,
3007 klass->interface_offsets_packed [i],
3008 klass->interfaces_packed [i]->method.count,
3009 klass->interfaces_packed [i]->name_space,
3010 klass->interfaces_packed [i]->name );
3011 printf ("Interface flags: ");
3012 for (i = 0; i <= klass->max_interface_id; i++)
3013 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3014 printf ("(%d,T)", i);
3016 printf ("(%d,F)", i);
3018 printf ("Dump interface flags:");
3019 #ifdef COMPRESSED_INTERFACE_BITMAP
3021 const uint8_t* p = klass->interface_bitmap;
3022 i = klass->max_interface_id;
3024 printf (" %d x 00 %02X", p [0], p [1]);
3030 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3031 printf (" %02X", klass->interface_bitmap [i]);
3034 while (klass != NULL) {
3035 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3036 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3037 if (!mono_error_ok (&error)) {
3038 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3039 mono_error_cleanup (&error);
3040 } else if (ifaces) {
3041 for (i = 0; i < ifaces->len; i++) {
3042 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3043 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3044 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3046 mono_class_interface_offset (klass, ic),
3051 g_ptr_array_free (ifaces, TRUE);
3054 klass = klass->parent;
3059 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3062 args [0] = &arg0->byval_arg;
3064 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3068 array_class_get_if_rank (MonoClass *klass, guint rank)
3070 return rank ? mono_array_class_get (klass, rank) : klass;
3074 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3076 valuetype_types [0] = eclass;
3077 if (eclass == mono_defaults.int16_class)
3078 valuetype_types [1] = mono_defaults.uint16_class;
3079 else if (eclass == mono_defaults.uint16_class)
3080 valuetype_types [1] = mono_defaults.int16_class;
3081 else if (eclass == mono_defaults.int32_class)
3082 valuetype_types [1] = mono_defaults.uint32_class;
3083 else if (eclass == mono_defaults.uint32_class)
3084 valuetype_types [1] = mono_defaults.int32_class;
3085 else if (eclass == mono_defaults.int64_class)
3086 valuetype_types [1] = mono_defaults.uint64_class;
3087 else if (eclass == mono_defaults.uint64_class)
3088 valuetype_types [1] = mono_defaults.int64_class;
3089 else if (eclass == mono_defaults.byte_class)
3090 valuetype_types [1] = mono_defaults.sbyte_class;
3091 else if (eclass == mono_defaults.sbyte_class)
3092 valuetype_types [1] = mono_defaults.byte_class;
3093 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3094 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3097 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3098 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3099 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3100 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3101 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3103 /* this won't be needed once bug #325495 is completely fixed
3104 * though we'll need something similar to know which interfaces to allow
3105 * in arrays when they'll be lazyly created
3107 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3108 * MS returns diferrent types based on which instance is called. For example:
3109 * object obj = new byte[10][];
3110 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3111 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3114 * Fixing this should kill quite some code, save some bits and improve compatibility.
3117 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3119 MonoClass *eclass = klass->element_class;
3120 MonoClass* generic_icollection_class;
3121 MonoClass* generic_ienumerable_class;
3122 MonoClass* generic_ienumerator_class;
3123 MonoClass* generic_ireadonlylist_class;
3124 MonoClass* generic_ireadonlycollection_class;
3125 MonoClass *valuetype_types[2] = { NULL, NULL };
3126 MonoClass **interfaces = NULL;
3127 int i, nifaces, interface_count, real_count, original_rank;
3129 gboolean internal_enumerator;
3130 gboolean eclass_is_valuetype;
3132 if (!mono_defaults.generic_ilist_class) {
3136 internal_enumerator = FALSE;
3137 eclass_is_valuetype = FALSE;
3138 original_rank = eclass->rank;
3139 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3140 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3142 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3144 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3145 original_rank = eclass->rank;
3147 eclass = eclass->element_class;
3148 internal_enumerator = TRUE;
3149 *is_enumerator = TRUE;
3157 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3158 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3160 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3162 generic_icollection_class = mono_class_get_generic_icollection_class ();
3163 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3164 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3165 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3166 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3168 mono_class_init (eclass);
3171 * Arrays in 2.0 need to implement a number of generic interfaces
3172 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3173 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3174 * We collect the types needed to build the
3175 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3176 * the generic interfaces needed to implement.
3178 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3179 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3181 if (eclass->valuetype) {
3182 nifaces = generic_ireadonlylist_class ? 5 : 3;
3183 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3185 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3186 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3187 if (internal_enumerator) {
3189 if (valuetype_types [1])
3193 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3194 interfaces [0] = valuetype_types [0];
3195 if (valuetype_types [1])
3196 interfaces [nifaces] = valuetype_types [1];
3198 eclass_is_valuetype = TRUE;
3201 int idepth = eclass->idepth;
3202 if (!internal_enumerator)
3204 nifaces = generic_ireadonlylist_class ? 2 : 3;
3206 // FIXME: This doesn't seem to work/required for generic params
3207 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3208 mono_class_setup_interface_offsets (eclass);
3210 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3211 /* we add object for interfaces and the supertypes for the other
3212 * types. The last of the supertypes is the element class itself which we
3213 * already created the explicit interfaces for (so we include it for IEnumerator
3214 * and exclude it for arrays).
3216 if (MONO_CLASS_IS_INTERFACE (eclass))
3219 interface_count += idepth;
3220 if (eclass->rank && eclass->element_class->valuetype) {
3221 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3222 if (valuetype_types [1])
3225 /* IList, ICollection, IEnumerable, IReadOnlyList */
3226 interface_count *= nifaces;
3227 real_count = interface_count;
3228 if (internal_enumerator) {
3229 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3230 if (valuetype_types [1])
3233 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3234 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3235 interfaces [0] = mono_defaults.object_class;
3239 for (i = 0; i < idepth; i++) {
3240 mono_class_init (eclass->supertypes [i]);
3241 interfaces [j] = eclass->supertypes [i];
3245 if (all_interfaces) {
3246 for (i = 0; i < eclass->interface_offsets_count; i++) {
3247 interfaces [j] = eclass->interfaces_packed [i];
3251 for (i = 0; i < eclass->interface_count; i++) {
3252 interfaces [j] = eclass->interfaces [i];
3256 if (valuetype_types [1]) {
3257 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3262 /* instantiate the generic interfaces */
3263 for (i = 0; i < interface_count; i += nifaces) {
3264 MonoClass *iface = interfaces [i];
3266 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3267 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3269 if (eclass->valuetype) {
3270 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3271 if (generic_ireadonlylist_class) {
3272 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3273 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3276 if (!generic_ireadonlylist_class)
3277 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3280 if (internal_enumerator) {
3282 /* instantiate IEnumerator<iface> */
3283 for (i = 0; i < interface_count; i++) {
3284 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3286 j = interface_count;
3287 if (!eclass_is_valuetype) {
3288 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3289 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3292 for (i = 0; i < eclass->idepth; i++) {
3293 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3297 for (i = 0; i < eclass->interface_offsets_count; i++) {
3298 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3302 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3304 if (valuetype_types [1])
3305 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3309 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3310 for (i = 0; i < real_count; ++i) {
3311 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3312 g_print ("%s implements %s\n", type_name, name);
3323 find_array_interface (MonoClass *klass, const char *name)
3326 for (i = 0; i < klass->interface_count; ++i) {
3327 if (strcmp (klass->interfaces [i]->name, name) == 0)
3334 * Return the number of virtual methods.
3335 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3336 * Return -1 on failure.
3337 * FIXME It would be nice if this information could be cached somewhere.
3340 count_virtual_methods (MonoClass *klass)
3344 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3346 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3347 mono_class_setup_methods (klass);
3348 if (mono_class_has_failure (klass))
3351 for (i = 0; i < klass->method.count; ++i) {
3352 flags = klass->methods [i]->flags;
3353 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3357 for (i = 0; i < klass->method.count; ++i) {
3358 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3360 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3368 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3376 m = (l + num_ifaces) / 2;
3377 if (interfaces_full [m] == ic)
3379 if (l == num_ifaces)
3381 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3390 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3392 int i = find_interface (num_ifaces, interfaces_full, ic);
3394 return interface_offsets_full [i];
3399 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3401 int i = find_interface (num_ifaces, interfaces_full, ic);
3405 interface_offsets_full [i] = offset;
3408 for (i = 0; i < num_ifaces; ++i) {
3409 if (interfaces_full [i]) {
3411 if (interfaces_full [i]->interface_id < ic->interface_id)
3414 while (end < num_ifaces && interfaces_full [end]) end++;
3415 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3416 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3418 interfaces_full [i] = ic;
3419 interface_offsets_full [i] = offset;
3425 #ifdef COMPRESSED_INTERFACE_BITMAP
3428 * Compressed interface bitmap design.
3430 * Interface bitmaps take a large amount of memory, because their size is
3431 * linear with the maximum interface id assigned in the process (each interface
3432 * is assigned a unique id as it is loaded). The number of interface classes
3433 * is high because of the many implicit interfaces implemented by arrays (we'll
3434 * need to lazy-load them in the future).
3435 * Most classes implement a very small number of interfaces, so the bitmap is
3436 * sparse. This bitmap needs to be checked by interface casts, so access to the
3437 * needed bit must be fast and doable with few jit instructions.
3439 * The current compression format is as follows:
3440 * *) it is a sequence of one or more two-byte elements
3441 * *) the first byte in the element is the count of empty bitmap bytes
3442 * at the current bitmap position
3443 * *) the second byte in the element is an actual bitmap byte at the current
3446 * As an example, the following compressed bitmap bytes:
3447 * 0x07 0x01 0x00 0x7
3448 * correspond to the following bitmap:
3449 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3451 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3452 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3453 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3457 * mono_compress_bitmap:
3458 * @dest: destination buffer
3459 * @bitmap: bitmap buffer
3460 * @size: size of @bitmap in bytes
3462 * This is a mono internal function.
3463 * The @bitmap data is compressed into a format that is small but
3464 * still searchable in few instructions by the JIT and runtime.
3465 * The compressed data is stored in the buffer pointed to by the
3466 * @dest array. Passing a #NULL value for @dest allows to just compute
3467 * the size of the buffer.
3468 * This compression algorithm assumes the bits set in the bitmap are
3469 * few and far between, like in interface bitmaps.
3470 * Returns: The size of the compressed bitmap in bytes.
3473 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3477 const uint8_t *end = bitmap + size;
3478 while (bitmap < end) {
3479 if (*bitmap || numz == 255) {
3503 * mono_class_interface_match:
3504 * @bitmap: a compressed bitmap buffer
3505 * @id: the index to check in the bitmap
3507 * This is a mono internal function.
3508 * Checks if a bit is set in a compressed interface bitmap. @id must
3509 * be already checked for being smaller than the maximum id encoded in the
3512 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3516 mono_class_interface_match (const uint8_t *bitmap, int id)
3519 id -= bitmap [0] * 8;
3523 return bitmap [1] & (1 << id);
3532 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3533 * LOCKING: Acquires the loader lock.
3536 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3540 int i, j, max_iid, num_ifaces;
3541 MonoClass **interfaces_full = NULL;
3542 int *interface_offsets_full = NULL;
3544 GPtrArray **ifaces_array = NULL;
3545 int interface_offsets_count;
3546 MonoClass **array_interfaces = NULL;
3547 int num_array_interfaces;
3548 int is_enumerator = FALSE;
3550 mono_class_setup_supertypes (klass);
3552 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3553 * implicit interfaces have the property that they are assigned the same slot in the
3554 * vtables for compatible interfaces
3556 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3558 /* compute maximum number of slots and maximum interface id */
3560 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3561 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3562 for (j = 0; j < klass->idepth; j++) {
3563 k = klass->supertypes [j];
3564 num_ifaces += k->interface_count;
3565 for (i = 0; i < k->interface_count; i++) {
3566 ic = k->interfaces [i];
3568 mono_class_init (ic);
3570 if (max_iid < ic->interface_id)
3571 max_iid = ic->interface_id;
3573 ifaces = mono_class_get_implemented_interfaces (k, &error);
3574 if (!mono_error_ok (&error)) {
3575 char *name = mono_type_get_full_name (k);
3576 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3578 mono_error_cleanup (&error);
3583 num_ifaces += ifaces->len;
3584 for (i = 0; i < ifaces->len; ++i) {
3585 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3586 if (max_iid < ic->interface_id)
3587 max_iid = ic->interface_id;
3589 ifaces_array [j] = ifaces;
3593 for (i = 0; i < num_array_interfaces; ++i) {
3594 ic = array_interfaces [i];
3595 mono_class_init (ic);
3596 if (max_iid < ic->interface_id)
3597 max_iid = ic->interface_id;
3600 if (MONO_CLASS_IS_INTERFACE (klass)) {
3602 if (max_iid < klass->interface_id)
3603 max_iid = klass->interface_id;
3606 /* compute vtable offset for interfaces */
3607 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3608 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3610 for (i = 0; i < num_ifaces; i++)
3611 interface_offsets_full [i] = -1;
3613 /* skip the current class */
3614 for (j = 0; j < klass->idepth - 1; j++) {
3615 k = klass->supertypes [j];
3616 ifaces = ifaces_array [j];
3619 for (i = 0; i < ifaces->len; ++i) {
3621 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3623 /*Force the sharing of interface offsets between parent and subtypes.*/
3624 io = mono_class_interface_offset (k, ic);
3626 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3631 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3632 ifaces = ifaces_array [klass->idepth - 1];
3634 for (i = 0; i < ifaces->len; ++i) {
3636 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3637 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3639 count = count_virtual_methods (ic);
3641 char *name = mono_type_get_full_name (ic);
3642 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3651 if (MONO_CLASS_IS_INTERFACE (klass))
3652 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3654 if (num_array_interfaces) {
3655 if (is_enumerator) {
3656 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3657 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3658 g_assert (ienumerator_offset >= 0);
3659 for (i = 0; i < num_array_interfaces; ++i) {
3660 ic = array_interfaces [i];
3661 if (strcmp (ic->name, "IEnumerator`1") == 0)
3662 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3664 g_assert_not_reached ();
3665 /*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);*/
3668 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3669 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3670 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3671 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3672 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3673 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3674 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3675 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3676 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3677 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3678 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3679 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3680 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3681 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3682 for (i = 0; i < num_array_interfaces; ++i) {
3684 ic = array_interfaces [i];
3685 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3686 offset = ilist_offset;
3687 else if (strcmp (ic->name, "ICollection`1") == 0)
3688 offset = icollection_offset;
3689 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3690 offset = ienumerable_offset;
3691 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3692 offset = ireadonlylist_offset;
3693 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3694 offset = ireadonlycollection_offset;
3696 g_assert_not_reached ();
3697 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3698 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3703 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3704 if (interface_offsets_full [i] != -1)
3705 interface_offsets_count ++;
3708 /* Publish the data */
3709 mono_loader_lock ();
3711 klass->max_interface_id = max_iid;
3713 * We might get called multiple times:
3714 * - mono_class_init ()
3715 * - mono_class_setup_vtable ().
3716 * - mono_class_setup_interface_offsets ().
3717 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3718 * means we have to overwrite those when called from other places (#4440).
3720 if (klass->interfaces_packed) {
3722 g_assert (klass->interface_offsets_count == interface_offsets_count);
3726 klass->interface_offsets_count = interface_offsets_count;
3727 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3728 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3729 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3730 #ifdef COMPRESSED_INTERFACE_BITMAP
3731 bitmap = g_malloc0 (bsize);
3733 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3735 for (i = 0; i < interface_offsets_count; i++) {
3736 int id = interfaces_full [i]->interface_id;
3737 bitmap [id >> 3] |= (1 << (id & 7));
3738 klass->interfaces_packed [i] = interfaces_full [i];
3739 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3740 /*if (num_array_interfaces)
3741 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]);*/
3743 #ifdef COMPRESSED_INTERFACE_BITMAP
3744 i = mono_compress_bitmap (NULL, bitmap, bsize);
3745 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3746 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3749 klass->interface_bitmap = bitmap;
3752 mono_loader_unlock ();
3755 g_free (interfaces_full);
3756 g_free (interface_offsets_full);
3757 g_free (array_interfaces);
3758 for (i = 0; i < klass->idepth; i++) {
3759 ifaces = ifaces_array [i];
3761 g_ptr_array_free (ifaces, TRUE);
3763 g_free (ifaces_array);
3765 //printf ("JUST DONE: ");
3766 //print_implemented_interfaces (klass);
3772 * Setup interface offsets for interfaces.
3774 * - klass->max_interface_id
3775 * - klass->interface_offsets_count
3776 * - klass->interfaces_packed
3777 * - klass->interface_offsets_packed
3778 * - klass->interface_bitmap
3780 * This function can fail @class.
3783 mono_class_setup_interface_offsets (MonoClass *klass)
3785 setup_interface_offsets (klass, 0, FALSE);
3788 /*Checks if @klass has @parent as one of it's parents type gtd
3792 * Bar<T> : Foo<Bar<Bar<T>>>
3796 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3798 klass = mono_class_get_generic_type_definition (klass);
3799 parent = mono_class_get_generic_type_definition (parent);
3800 mono_class_setup_supertypes (klass);
3801 mono_class_setup_supertypes (parent);
3803 return klass->idepth >= parent->idepth &&
3804 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3808 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3810 MonoGenericInst *ginst;
3812 if (!klass->generic_class) {
3813 mono_class_setup_vtable_full (klass, in_setup);
3814 return !mono_class_has_failure (klass);
3817 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3818 if (mono_class_set_type_load_failure_causedby_class (klass, klass->generic_class->container_class, "Failed to load generic definition vtable"))
3821 ginst = klass->generic_class->context.class_inst;
3822 for (i = 0; i < ginst->type_argc; ++i) {
3824 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3826 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3827 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3828 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3830 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3831 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3839 * mono_class_setup_vtable:
3841 * Creates the generic vtable of CLASS.
3842 * Initializes the following fields in MonoClass:
3845 * Plus all the fields initialized by setup_interface_offsets ().
3846 * If there is an error during vtable construction, klass->has_failure
3847 * is set and details are stored in a MonoErrorBoxed.
3849 * LOCKING: Acquires the loader lock.
3852 mono_class_setup_vtable (MonoClass *klass)
3854 mono_class_setup_vtable_full (klass, NULL);
3858 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3861 MonoMethod **overrides;
3862 MonoGenericContext *context;
3870 if (MONO_CLASS_IS_INTERFACE (klass)) {
3871 /* This sets method->slot for all methods if this is an interface */
3872 mono_class_setup_methods (klass);
3876 if (mono_class_has_failure (klass))
3879 if (g_list_find (in_setup, klass))
3882 mono_loader_lock ();
3884 if (klass->vtable) {
3885 mono_loader_unlock ();
3889 mono_stats.generic_vtable_count ++;
3890 in_setup = g_list_prepend (in_setup, klass);
3892 if (klass->generic_class) {
3893 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3894 mono_loader_unlock ();
3895 g_list_remove (in_setup, klass);
3899 context = mono_class_get_context (klass);
3900 type_token = klass->generic_class->container_class->type_token;
3902 context = (MonoGenericContext *) klass->generic_container;
3903 type_token = klass->type_token;
3906 if (image_is_dynamic (klass->image)) {
3907 /* Generic instances can have zero method overrides without causing any harm.
3908 * This is true since we don't do layout all over again for them, we simply inflate
3909 * the layout of the parent.
3911 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3912 if (!is_ok (&error)) {
3913 mono_loader_unlock ();
3914 g_list_remove (in_setup, klass);
3915 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3916 mono_error_cleanup (&error);
3920 /* The following call fails if there are missing methods in the type */
3921 /* FIXME it's probably a good idea to avoid this for generic instances. */
3922 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3926 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3928 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3932 mono_loader_unlock ();
3933 g_list_remove (in_setup, klass);
3938 #define DEBUG_INTERFACE_VTABLE_CODE 0
3939 #define TRACE_INTERFACE_VTABLE_CODE 0
3940 #define VERIFY_INTERFACE_VTABLE_CODE 0
3941 #define VTABLE_SELECTOR (1)
3943 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3944 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3945 if (!(VTABLE_SELECTOR)) break; \
3949 #define DEBUG_INTERFACE_VTABLE(stmt)
3952 #if TRACE_INTERFACE_VTABLE_CODE
3953 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3954 if (!(VTABLE_SELECTOR)) break; \
3958 #define TRACE_INTERFACE_VTABLE(stmt)
3961 #if VERIFY_INTERFACE_VTABLE_CODE
3962 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3963 if (!(VTABLE_SELECTOR)) break; \
3967 #define VERIFY_INTERFACE_VTABLE(stmt)
3971 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3973 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3977 GString *res = g_string_new ("");
3979 g_string_append_c (res, '(');
3980 for (i = 0; i < sig->param_count; ++i) {
3982 g_string_append_c (res, ',');
3983 mono_type_get_desc (res, sig->params [i], include_namespace);
3985 g_string_append (res, ")=>");
3986 if (sig->ret != NULL) {
3987 mono_type_get_desc (res, sig->ret, include_namespace);
3989 g_string_append (res, "NULL");
3992 g_string_free (res, FALSE);
3996 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3997 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3998 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3999 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
4007 is_wcf_hack_disabled (void)
4009 static gboolean disabled;
4010 static gboolean inited = FALSE;
4012 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4019 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4021 MonoMethodSignature *cmsig, *imsig;
4022 if (strcmp (im->name, cm->name) == 0) {
4023 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4024 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4027 if (! slot_is_empty) {
4028 if (require_newslot) {
4029 if (! interface_is_explicitly_implemented_by_class) {
4030 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4033 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4034 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4038 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4041 cmsig = mono_method_signature (cm);
4042 imsig = mono_method_signature (im);
4043 if (!cmsig || !imsig) {
4044 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4048 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4049 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4050 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4051 TRACE_INTERFACE_VTABLE (printf ("]"));
4054 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4055 if (mono_security_core_clr_enabled ())
4056 mono_security_core_clr_check_override (klass, cm, im);
4058 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4059 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4060 char *body_name = mono_method_full_name (cm, TRUE);
4061 char *decl_name = mono_method_full_name (im, TRUE);
4062 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4070 MonoClass *ic = im->klass;
4071 const char *ic_name_space = ic->name_space;
4072 const char *ic_name = ic->name;
4075 if (! require_newslot) {
4076 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4079 if (cm->klass->rank == 0) {
4080 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4083 cmsig = mono_method_signature (cm);
4084 imsig = mono_method_signature (im);
4085 if (!cmsig || !imsig) {
4086 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4090 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4091 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4092 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4093 TRACE_INTERFACE_VTABLE (printf ("]"));
4096 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4097 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4100 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4101 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4104 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))) {
4105 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4109 subname = strstr (cm->name, ic_name_space);
4110 if (subname != cm->name) {
4111 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4114 subname += strlen (ic_name_space);
4115 if (subname [0] != '.') {
4116 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4120 if (strstr (subname, ic_name) != subname) {
4121 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4124 subname += strlen (ic_name);
4125 if (subname [0] != '.') {
4126 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4130 if (strcmp (subname, im->name) != 0) {
4131 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4135 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4136 if (mono_security_core_clr_enabled ())
4137 mono_security_core_clr_check_override (klass, cm, im);
4139 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4140 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4141 char *body_name = mono_method_full_name (cm, TRUE);
4142 char *decl_name = mono_method_full_name (im, TRUE);
4143 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4153 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4155 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4156 MonoMethod *method = key;
4157 MonoMethod *override = value;
4158 MonoClass *method_class = mono_method_get_class (method);
4159 MonoClass *override_class = mono_method_get_class (override);
4161 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4162 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4163 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4166 print_overrides (GHashTable *override_map, const char *message) {
4168 printf ("Override map \"%s\" START:\n", message);
4169 g_hash_table_foreach (override_map, foreach_override, NULL);
4170 printf ("Override map \"%s\" END.\n", message);
4172 printf ("Override map \"%s\" EMPTY.\n", message);
4176 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4177 char *full_name = mono_type_full_name (&klass->byval_arg);
4181 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4183 if (print_interfaces) {
4184 print_implemented_interfaces (klass);
4185 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4188 if (klass->parent) {
4189 parent_size = klass->parent->vtable_size;
4193 for (i = 0; i < size; ++i) {
4194 MonoMethod *cm = vtable [i];
4195 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4196 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4198 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4206 #if VERIFY_INTERFACE_VTABLE_CODE
4208 mono_method_try_get_vtable_index (MonoMethod *method)
4210 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4211 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4212 if (imethod->declaring->is_generic)
4213 return imethod->declaring->slot;
4215 return method->slot;
4219 mono_class_verify_vtable (MonoClass *klass)
4222 char *full_name = mono_type_full_name (&klass->byval_arg);
4224 printf ("*** Verifying VTable of class '%s' \n", full_name);
4228 if (!klass->methods)
4231 for (i = 0; i < klass->method.count; ++i) {
4232 MonoMethod *cm = klass->methods [i];
4235 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4239 full_name = mono_method_full_name (cm, TRUE);
4241 slot = mono_method_try_get_vtable_index (cm);
4243 if (slot >= klass->vtable_size) {
4244 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4248 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4249 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4250 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4251 g_free (other_name);
4254 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4261 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4263 char *method_signature;
4266 for (index = 0; index < onum; ++index) {
4267 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4268 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4270 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4271 type_name = mono_type_full_name (&klass->byval_arg);
4272 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4273 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4274 g_free (method_signature);
4276 mono_class_setup_methods (klass);
4277 if (mono_class_has_failure (klass)) {
4278 char *name = mono_type_get_full_name (klass);
4279 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4283 for (index = 0; index < klass->method.count; ++index) {
4284 MonoMethod *cm = klass->methods [index];
4285 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4287 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4288 g_free (method_signature);
4293 mono_method_get_method_definition (MonoMethod *method)
4295 while (method->is_inflated)
4296 method = ((MonoMethodInflated*)method)->declaring;
4301 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4305 for (i = 0; i < onum; ++i) {
4306 MonoMethod *decl = overrides [i * 2];
4307 MonoMethod *body = overrides [i * 2 + 1];
4309 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4310 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4314 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4315 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4316 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4318 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4322 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4323 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4324 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4326 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4330 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4331 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4335 body = mono_method_get_method_definition (body);
4336 decl = mono_method_get_method_definition (decl);
4338 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4339 char *body_name = mono_method_full_name (body, TRUE);
4340 char *decl_name = mono_method_full_name (decl, TRUE);
4341 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4351 mono_class_need_stelemref_method (MonoClass *klass)
4353 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4357 * LOCKING: this is supposed to be called with the loader lock held.
4360 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4364 MonoMethod **vtable;
4365 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4366 GPtrArray *ifaces = NULL;
4367 GHashTable *override_map = NULL;
4369 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4370 int first_non_interface_slot;
4372 GSList *virt_methods = NULL, *l;
4373 int stelemref_slot = 0;
4378 if (overrides && !verify_class_overrides (klass, overrides, onum))
4381 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4382 if (!mono_error_ok (&error)) {
4383 char *name = mono_type_get_full_name (klass);
4384 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4386 mono_error_cleanup (&error);
4388 } else if (ifaces) {
4389 for (i = 0; i < ifaces->len; i++) {
4390 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4391 max_vtsize += ic->method.count;
4393 g_ptr_array_free (ifaces, TRUE);
4397 if (klass->parent) {
4398 mono_class_init (klass->parent);
4399 mono_class_setup_vtable_full (klass->parent, in_setup);
4401 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4404 max_vtsize += klass->parent->vtable_size;
4405 cur_slot = klass->parent->vtable_size;
4408 max_vtsize += klass->method.count;
4410 /*Array have a slot for stelemref*/
4411 if (mono_class_need_stelemref_method (klass)) {
4412 stelemref_slot = cur_slot;
4417 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4418 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4420 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4422 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4423 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4426 max_iid = klass->max_interface_id;
4427 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4429 /* Optimized version for generic instances */
4430 if (klass->generic_class) {
4432 MonoClass *gklass = klass->generic_class->container_class;
4435 mono_class_setup_vtable_full (gklass, in_setup);
4436 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4439 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4440 klass->vtable_size = gklass->vtable_size;
4441 for (i = 0; i < gklass->vtable_size; ++i)
4442 if (gklass->vtable [i]) {
4443 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4444 if (!mono_error_ok (&error)) {
4445 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4446 mono_error_cleanup (&error);
4450 tmp [i]->slot = gklass->vtable [i]->slot;
4452 mono_memory_barrier ();
4453 klass->vtable = tmp;
4455 /* Have to set method->slot for abstract virtual methods */
4456 if (klass->methods && gklass->methods) {
4457 for (i = 0; i < klass->method.count; ++i)
4458 if (klass->methods [i]->slot == -1)
4459 klass->methods [i]->slot = gklass->methods [i]->slot;
4465 if (klass->parent && klass->parent->vtable_size) {
4466 MonoClass *parent = klass->parent;
4469 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4471 // Also inherit parent interface vtables, just as a starting point.
4472 // This is needed otherwise bug-77127.exe fails when the property methods
4473 // have different names in the iterface and the class, because for child
4474 // classes the ".override" information is not used anymore.
4475 for (i = 0; i < parent->interface_offsets_count; i++) {
4476 MonoClass *parent_interface = parent->interfaces_packed [i];
4477 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4478 /*FIXME this is now dead code as this condition will never hold true.
4479 Since interface offsets are inherited then the offset of an interface implemented
4480 by a parent will never be the out of it's vtable boundary.
4482 if (interface_offset >= parent->vtable_size) {
4483 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4486 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4487 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4488 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4489 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4490 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4491 parent_interface_offset + j, parent_interface_offset, j,
4492 interface_offset + j, interface_offset, j));
4499 /*Array have a slot for stelemref*/
4500 if (mono_class_need_stelemref_method (klass)) {
4501 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4503 method->slot = stelemref_slot;
4505 g_assert (method->slot == stelemref_slot);
4507 vtable [stelemref_slot] = method;
4510 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4511 /* override interface methods */
4512 for (i = 0; i < onum; i++) {
4513 MonoMethod *decl = overrides [i*2];
4514 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4516 dslot = mono_method_get_vtable_slot (decl);
4518 mono_class_set_type_load_failure (klass, "");
4522 dslot += mono_class_interface_offset (klass, decl->klass);
4523 vtable [dslot] = overrides [i*2 + 1];
4524 vtable [dslot]->slot = dslot;
4526 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4528 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4530 if (mono_security_core_clr_enabled ())
4531 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4534 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4535 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4538 * Create a list of virtual methods to avoid calling
4539 * mono_class_get_virtual_methods () which is slow because of the metadata
4543 gpointer iter = NULL;
4546 virt_methods = NULL;
4547 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4548 virt_methods = g_slist_prepend (virt_methods, cm);
4550 if (mono_class_has_failure (klass))
4554 // Loop on all implemented interfaces...
4555 for (i = 0; i < klass->interface_offsets_count; i++) {
4556 MonoClass *parent = klass->parent;
4558 gboolean interface_is_explicitly_implemented_by_class;
4561 ic = klass->interfaces_packed [i];
4562 ic_offset = mono_class_interface_offset (klass, ic);
4564 mono_class_setup_methods (ic);
4565 if (mono_class_has_failure (ic))
4568 // Check if this interface is explicitly implemented (instead of just inherited)
4569 if (parent != NULL) {
4570 int implemented_interfaces_index;
4571 interface_is_explicitly_implemented_by_class = FALSE;
4572 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4573 if (ic == klass->interfaces [implemented_interfaces_index]) {
4574 interface_is_explicitly_implemented_by_class = TRUE;
4579 interface_is_explicitly_implemented_by_class = TRUE;
4582 // Loop on all interface methods...
4583 for (im_index = 0; im_index < ic->method.count; im_index++) {
4584 MonoMethod *im = ic->methods [im_index];
4585 int im_slot = ic_offset + im->slot;
4586 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4588 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4591 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4593 // If there is an explicit implementation, just use it right away,
4594 // otherwise look for a matching method
4595 if (override_im == NULL) {
4599 // First look for a suitable method among the class methods
4600 for (l = virt_methods; l; l = l->next) {
4601 cm = (MonoMethod *)l->data;
4602 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)));
4603 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4604 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4605 vtable [im_slot] = cm;
4606 /* Why do we need this? */
4611 TRACE_INTERFACE_VTABLE (printf ("\n"));
4612 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4616 // If the slot is still empty, look in all the inherited virtual methods...
4617 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4618 MonoClass *parent = klass->parent;
4619 // Reverse order, so that last added methods are preferred
4620 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4621 MonoMethod *cm = parent->vtable [cm_index];
4623 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));
4624 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4625 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4626 vtable [im_slot] = cm;
4627 /* Why do we need this? */
4633 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4635 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4639 g_assert (vtable [im_slot] == override_im);
4644 // If the class is not abstract, check that all its interface slots are full.
4645 // The check is done here and not directly at the end of the loop above because
4646 // it can happen (for injected generic array interfaces) that the same slot is
4647 // processed multiple times (those interfaces have overlapping slots), and it
4648 // will not always be the first pass the one that fills the slot.
4649 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4650 for (i = 0; i < klass->interface_offsets_count; i++) {
4654 ic = klass->interfaces_packed [i];
4655 ic_offset = mono_class_interface_offset (klass, ic);
4657 for (im_index = 0; im_index < ic->method.count; im_index++) {
4658 MonoMethod *im = ic->methods [im_index];
4659 int im_slot = ic_offset + im->slot;
4661 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4664 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4665 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4666 if (vtable [im_slot] == NULL) {
4667 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4674 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4675 for (l = virt_methods; l; l = l->next) {
4676 cm = (MonoMethod *)l->data;
4678 * If the method is REUSE_SLOT, we must check in the
4679 * base class for a method to override.
4681 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4683 for (k = klass->parent; k ; k = k->parent) {
4688 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4689 MonoMethodSignature *cmsig, *m1sig;
4691 cmsig = mono_method_signature (cm);
4692 m1sig = mono_method_signature (m1);
4694 if (!cmsig || !m1sig) {
4695 /* FIXME proper error message */
4696 mono_class_set_type_load_failure (klass, "");
4700 if (!strcmp(cm->name, m1->name) &&
4701 mono_metadata_signature_equal (cmsig, m1sig)) {
4703 if (mono_security_core_clr_enabled ())
4704 mono_security_core_clr_check_override (klass, cm, m1);
4706 slot = mono_method_get_vtable_slot (m1);
4710 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4711 char *body_name = mono_method_full_name (cm, TRUE);
4712 char *decl_name = mono_method_full_name (m1, TRUE);
4713 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4719 g_assert (cm->slot < max_vtsize);
4721 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4722 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4723 mono_method_full_name (m1, 1), m1,
4724 mono_method_full_name (cm, 1), cm));
4725 g_hash_table_insert (override_map, m1, cm);
4729 if (mono_class_has_failure (k))
4739 /*Non final newslot methods must be given a non-interface vtable slot*/
4740 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4744 cm->slot = cur_slot++;
4746 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4747 vtable [cm->slot] = cm;
4750 /* override non interface methods */
4751 for (i = 0; i < onum; i++) {
4752 MonoMethod *decl = overrides [i*2];
4753 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4754 g_assert (decl->slot != -1);
4755 vtable [decl->slot] = overrides [i*2 + 1];
4756 overrides [i * 2 + 1]->slot = decl->slot;
4758 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4759 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4760 mono_method_full_name (decl, 1), decl,
4761 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4762 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4764 if (mono_security_core_clr_enabled ())
4765 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4770 * If a method occupies more than one place in the vtable, and it is
4771 * overriden, then change the other occurances too.
4776 for (i = 0; i < max_vtsize; ++i)
4778 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4780 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4785 g_hash_table_destroy (override_map);
4786 override_map = NULL;
4789 g_slist_free (virt_methods);
4790 virt_methods = NULL;
4792 /* Ensure that all vtable slots are filled with concrete instance methods */
4793 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4794 for (i = 0; i < cur_slot; ++i) {
4795 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4796 char *type_name = mono_type_get_full_name (klass);
4797 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4798 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4800 g_free (method_name);
4806 if (klass->generic_class) {
4807 MonoClass *gklass = klass->generic_class->container_class;
4809 mono_class_init (gklass);
4811 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4813 /* Check that the vtable_size value computed in mono_class_init () is correct */
4814 if (klass->vtable_size)
4815 g_assert (cur_slot == klass->vtable_size);
4816 klass->vtable_size = cur_slot;
4819 /* Try to share the vtable with our parent. */
4820 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4821 mono_memory_barrier ();
4822 klass->vtable = klass->parent->vtable;
4824 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4825 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4826 mono_memory_barrier ();
4827 klass->vtable = tmp;
4830 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4831 if (mono_print_vtable) {
4834 print_implemented_interfaces (klass);
4836 for (i = 0; i <= max_iid; i++)
4837 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4840 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4841 klass->vtable_size, icount);
4843 for (i = 0; i < cur_slot; ++i) {
4848 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4849 mono_method_full_name (cm, TRUE));
4855 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4856 klass->name, max_iid);
4858 for (i = 0; i < klass->interface_count; i++) {
4859 ic = klass->interfaces [i];
4860 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4861 mono_class_interface_offset (klass, ic),
4862 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4865 for (k = klass->parent; k ; k = k->parent) {
4866 for (i = 0; i < k->interface_count; i++) {
4867 ic = k->interfaces [i];
4868 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4869 mono_class_interface_offset (klass, ic),
4870 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4876 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4881 char *name = mono_type_get_full_name (klass);
4882 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4885 g_hash_table_destroy (override_map);
4887 g_slist_free (virt_methods);
4892 * mono_method_get_vtable_slot:
4894 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4895 * LOCKING: Acquires the loader lock.
4897 * FIXME Use proper MonoError machinery here.
4900 mono_method_get_vtable_slot (MonoMethod *method)
4902 if (method->slot == -1) {
4903 mono_class_setup_vtable (method->klass);
4904 if (mono_class_has_failure (method->klass))
4906 if (method->slot == -1) {
4910 if (!method->klass->generic_class) {
4911 g_assert (method->is_inflated);
4912 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4915 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4916 g_assert (method->klass->generic_class);
4917 gklass = method->klass->generic_class->container_class;
4918 mono_class_setup_methods (method->klass);
4919 g_assert (method->klass->methods);
4920 for (i = 0; i < method->klass->method.count; ++i) {
4921 if (method->klass->methods [i] == method)
4924 g_assert (i < method->klass->method.count);
4925 g_assert (gklass->methods);
4926 method->slot = gklass->methods [i]->slot;
4928 g_assert (method->slot != -1);
4930 return method->slot;
4934 * mono_method_get_vtable_index:
4937 * Returns the index into the runtime vtable to access the method or,
4938 * in the case of a virtual generic method, the virtual generic method
4939 * thunk. Returns -1 on failure.
4941 * FIXME Use proper MonoError machinery here.
4944 mono_method_get_vtable_index (MonoMethod *method)
4946 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4947 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4948 if (imethod->declaring->is_generic)
4949 return mono_method_get_vtable_slot (imethod->declaring);
4951 return mono_method_get_vtable_slot (method);
4954 static MonoMethod *default_ghc = NULL;
4955 static MonoMethod *default_finalize = NULL;
4956 static int finalize_slot = -1;
4957 static int ghc_slot = -1;
4960 initialize_object_slots (MonoClass *klass)
4965 if (klass == mono_defaults.object_class) {
4966 mono_class_setup_vtable (klass);
4967 for (i = 0; i < klass->vtable_size; ++i) {
4968 MonoMethod *cm = klass->vtable [i];
4970 if (!strcmp (cm->name, "GetHashCode"))
4972 else if (!strcmp (cm->name, "Finalize"))
4976 g_assert (ghc_slot > 0);
4977 default_ghc = klass->vtable [ghc_slot];
4979 g_assert (finalize_slot > 0);
4980 default_finalize = klass->vtable [finalize_slot];
4985 MonoMethod *array_method;
4987 } GenericArrayMethodInfo;
4989 static int generic_array_method_num = 0;
4990 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4993 generic_array_methods (MonoClass *klass)
4995 int i, count_generic = 0;
4996 GList *list = NULL, *tmp;
4997 if (generic_array_method_num)
4998 return generic_array_method_num;
4999 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
5000 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
5001 for (i = 0; i < klass->parent->method.count; i++) {
5002 MonoMethod *m = klass->parent->methods [i];
5003 if (!strncmp (m->name, "InternalArray__", 15)) {
5005 list = g_list_prepend (list, m);
5008 list = g_list_reverse (list);
5009 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
5011 for (tmp = list; tmp; tmp = tmp->next) {
5012 const char *mname, *iname;
5014 MonoMethod *m = (MonoMethod *)tmp->data;
5015 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
5016 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5018 generic_array_method_info [i].array_method = m;
5019 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5020 iname = "System.Collections.Generic.ICollection`1.";
5021 mname = m->name + 27;
5022 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5023 iname = "System.Collections.Generic.IEnumerable`1.";
5024 mname = m->name + 27;
5025 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5026 iname = "System.Collections.Generic.IReadOnlyList`1.";
5027 mname = m->name + strlen (ireadonlylist_prefix);
5028 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5029 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5030 mname = m->name + strlen (ireadonlycollection_prefix);
5031 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5032 iname = "System.Collections.Generic.IList`1.";
5033 mname = m->name + 15;
5035 g_assert_not_reached ();
5038 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5039 strcpy (name, iname);
5040 strcpy (name + strlen (iname), mname);
5041 generic_array_method_info [i].name = name;
5044 /*g_print ("array generic methods: %d\n", count_generic);*/
5046 generic_array_method_num = count_generic;
5048 return generic_array_method_num;
5052 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5054 MonoGenericContext tmp_context;
5057 tmp_context.class_inst = NULL;
5058 tmp_context.method_inst = iface->generic_class->context.class_inst;
5059 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5061 for (i = 0; i < generic_array_method_num; i++) {
5063 MonoMethod *m = generic_array_method_info [i].array_method;
5064 MonoMethod *inflated;
5066 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5067 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5068 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5073 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5075 int null_length = strlen ("(null)");
5076 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5077 char *s = (char *)mono_image_alloc (image, len);
5080 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5081 g_assert (result == len - 1);
5088 * @klass: the class to initialize
5090 * Compute the instance_size, class_size and other infos that cannot be
5091 * computed at mono_class_get() time. Also compute vtable_size if possible.
5092 * Returns TRUE on success or FALSE if there was a problem in loading
5093 * the type (incorrect assemblies, missing assemblies, methods, etc).
5094 * Initializes the following fields in @klass:
5095 * - all the fields initialized by mono_class_init_sizes ()
5100 * LOCKING: Acquires the loader lock.
5103 mono_class_init (MonoClass *klass)
5105 int i, vtable_size = 0, array_method_count = 0;
5106 MonoCachedClassInfo cached_info;
5107 gboolean has_cached_info;
5108 gboolean locked = FALSE;
5109 gboolean ghcimpl = FALSE;
5110 gboolean has_cctor = FALSE;
5111 int first_iface_slot = 0;
5115 /* Double-checking locking pattern */
5116 if (klass->inited || mono_class_has_failure (klass))
5117 return !mono_class_has_failure (klass);
5119 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5122 * This function can recursively call itself.
5124 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5125 if (g_slist_find (init_list, klass)) {
5126 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5129 init_list = g_slist_prepend (init_list, klass);
5130 mono_native_tls_set_value (init_pending_tls_id, init_list);
5133 * We want to avoid doing complicated work inside locks, so we compute all the required
5134 * information and write it to @klass inside a lock.
5137 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5138 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5142 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5143 MonoClass *element_class = klass->element_class;
5144 if (!element_class->inited)
5145 mono_class_init (element_class);
5146 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5150 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5151 MonoClass *gklass = klass->generic_class->container_class;
5153 mono_class_init (gklass);
5154 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5157 mono_class_setup_interface_id (klass);
5160 if (klass->parent && !klass->parent->inited)
5161 mono_class_init (klass->parent);
5163 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5165 /* Compute instance size etc. */
5166 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5167 if (mono_class_has_failure (klass))
5170 mono_class_setup_supertypes (klass);
5173 initialize_object_slots (klass);
5176 * Initialize the rest of the data without creating a generic vtable if possible.
5177 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5178 * also avoid computing a generic vtable.
5180 if (has_cached_info) {
5182 vtable_size = cached_info.vtable_size;
5183 ghcimpl = cached_info.ghcimpl;
5184 has_cctor = cached_info.has_cctor;
5185 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5186 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5187 * The first slot if for array with.
5189 static int szarray_vtable_size[2] = { 0 };
5191 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5194 if (!szarray_vtable_size [slot]) {
5195 mono_class_setup_vtable (klass);
5196 szarray_vtable_size [slot] = klass->vtable_size;
5197 vtable_size = klass->vtable_size;
5199 vtable_size = szarray_vtable_size[slot];
5201 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5202 MonoClass *gklass = klass->generic_class->container_class;
5204 /* Generic instance case */
5205 ghcimpl = gklass->ghcimpl;
5206 has_cctor = gklass->has_cctor;
5208 mono_class_setup_vtable (gklass);
5209 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5212 vtable_size = gklass->vtable_size;
5216 /* ghcimpl is not currently used
5218 if (klass->parent) {
5219 MonoMethod *cmethod = klass->vtable [ghc_slot];
5220 if (cmethod->is_inflated)
5221 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5222 if (cmethod == default_ghc) {
5228 /* C# doesn't allow interfaces to have cctors */
5229 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5230 MonoMethod *cmethod = NULL;
5232 if (klass->type_token && !image_is_dynamic(klass->image)) {
5233 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5234 /* The find_method function ignores the 'flags' argument */
5235 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5238 mono_class_setup_methods (klass);
5239 if (mono_class_has_failure (klass))
5242 for (i = 0; i < klass->method.count; ++i) {
5243 MonoMethod *method = klass->methods [i];
5244 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5245 (strcmp (".cctor", method->name) == 0)) {
5255 array_method_count = 3 + (klass->rank > 1? 2: 1);
5257 if (klass->interface_count) {
5258 int count_generic = generic_array_methods (klass);
5259 array_method_count += klass->interface_count * count_generic;
5263 if (klass->parent) {
5264 if (!klass->parent->vtable_size)
5265 mono_class_setup_vtable (klass->parent);
5266 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5268 g_assert (klass->parent->vtable_size);
5269 first_iface_slot = klass->parent->vtable_size;
5270 if (mono_class_need_stelemref_method (klass))
5275 * Do the actual changes to @klass inside the loader lock
5277 mono_loader_lock ();
5280 if (klass->inited || mono_class_has_failure (klass)) {
5281 mono_loader_unlock ();
5282 /* Somebody might have gotten in before us */
5283 return !mono_class_has_failure (klass);
5286 mono_stats.initialized_class_count++;
5288 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5289 MonoClass *gklass = klass->generic_class->container_class;
5291 mono_stats.generic_class_count++;
5293 klass->method = gklass->method;
5294 klass->field = gklass->field;
5297 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5298 klass->nested_classes_inited = TRUE;
5299 klass->ghcimpl = ghcimpl;
5300 klass->has_cctor = has_cctor;
5302 klass->vtable_size = vtable_size;
5303 if (has_cached_info) {
5304 klass->has_finalize = cached_info.has_finalize;
5305 klass->has_finalize_inited = TRUE;
5308 klass->method.count = array_method_count;
5310 mono_loader_unlock ();
5313 setup_interface_offsets (klass, first_iface_slot, TRUE);
5315 if (mono_security_core_clr_enabled ())
5316 mono_security_core_clr_check_inheritance (klass);
5318 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5319 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5324 init_list = g_slist_remove (init_list, klass);
5325 mono_native_tls_set_value (init_pending_tls_id, init_list);
5327 /* Because of the double-checking locking pattern */
5328 mono_memory_barrier ();
5332 mono_loader_unlock ();
5334 return !mono_class_has_failure (klass);
5338 * mono_class_has_finalizer:
5340 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5344 mono_class_has_finalizer (MonoClass *klass)
5346 gboolean has_finalize = FALSE;
5348 if (klass->has_finalize_inited)
5349 return klass->has_finalize;
5351 /* Interfaces and valuetypes are not supposed to have finalizers */
5352 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5353 MonoMethod *cmethod = NULL;
5355 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5356 } else if (klass->generic_class) {
5357 MonoClass *gklass = klass->generic_class->container_class;
5359 has_finalize = mono_class_has_finalizer (gklass);
5360 } else if (klass->parent && klass->parent->has_finalize) {
5361 has_finalize = TRUE;
5363 if (klass->parent) {
5365 * Can't search in metadata for a method named Finalize, because that
5366 * ignores overrides.
5368 mono_class_setup_vtable (klass);
5369 if (mono_class_has_failure (klass))
5372 cmethod = klass->vtable [finalize_slot];
5376 g_assert (klass->vtable_size > finalize_slot);
5378 if (klass->parent) {
5379 if (cmethod->is_inflated)
5380 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5381 if (cmethod != default_finalize)
5382 has_finalize = TRUE;
5388 mono_image_lock (klass->image);
5390 if (!klass->has_finalize_inited) {
5391 klass->has_finalize = has_finalize ? 1 : 0;
5393 mono_memory_barrier ();
5394 klass->has_finalize_inited = TRUE;
5397 mono_image_unlock (klass->image);
5399 return klass->has_finalize;
5403 mono_is_corlib_image (MonoImage *image)
5405 return image == mono_defaults.corlib;
5409 * LOCKING: this assumes the loader lock is held
5412 mono_class_setup_mono_type (MonoClass *klass)
5414 const char *name = klass->name;
5415 const char *nspace = klass->name_space;
5416 gboolean is_corlib = mono_is_corlib_image (klass->image);
5418 klass->this_arg.byref = 1;
5419 klass->this_arg.data.klass = klass;
5420 klass->this_arg.type = MONO_TYPE_CLASS;
5421 klass->byval_arg.data.klass = klass;
5422 klass->byval_arg.type = MONO_TYPE_CLASS;
5424 if (is_corlib && !strcmp (nspace, "System")) {
5425 if (!strcmp (name, "ValueType")) {
5427 * do not set the valuetype bit for System.ValueType.
5428 * klass->valuetype = 1;
5430 klass->blittable = TRUE;
5431 } else if (!strcmp (name, "Enum")) {
5433 * do not set the valuetype bit for System.Enum.
5434 * klass->valuetype = 1;
5436 klass->valuetype = 0;
5437 klass->enumtype = 0;
5438 } else if (!strcmp (name, "Object")) {
5439 klass->byval_arg.type = MONO_TYPE_OBJECT;
5440 klass->this_arg.type = MONO_TYPE_OBJECT;
5441 } else if (!strcmp (name, "String")) {
5442 klass->byval_arg.type = MONO_TYPE_STRING;
5443 klass->this_arg.type = MONO_TYPE_STRING;
5444 } else if (!strcmp (name, "TypedReference")) {
5445 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5446 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5450 if (klass->valuetype) {
5451 int t = MONO_TYPE_VALUETYPE;
5453 if (is_corlib && !strcmp (nspace, "System")) {
5456 if (!strcmp (name, "Boolean")) {
5457 t = MONO_TYPE_BOOLEAN;
5458 } else if (!strcmp(name, "Byte")) {
5460 klass->blittable = TRUE;
5464 if (!strcmp (name, "Char")) {
5469 if (!strcmp (name, "Double")) {
5471 klass->blittable = TRUE;
5475 if (!strcmp (name, "Int32")) {
5477 klass->blittable = TRUE;
5478 } else if (!strcmp(name, "Int16")) {
5480 klass->blittable = TRUE;
5481 } else if (!strcmp(name, "Int64")) {
5483 klass->blittable = TRUE;
5484 } else if (!strcmp(name, "IntPtr")) {
5486 klass->blittable = TRUE;
5490 if (!strcmp (name, "Single")) {
5492 klass->blittable = TRUE;
5493 } else if (!strcmp(name, "SByte")) {
5495 klass->blittable = TRUE;
5499 if (!strcmp (name, "UInt32")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "UInt16")) {
5504 klass->blittable = TRUE;
5505 } else if (!strcmp(name, "UInt64")) {
5507 klass->blittable = TRUE;
5508 } else if (!strcmp(name, "UIntPtr")) {
5510 klass->blittable = TRUE;
5514 if (!strcmp (name, "TypedReference")) {
5515 t = MONO_TYPE_TYPEDBYREF;
5516 klass->blittable = TRUE;
5520 if (!strcmp (name, "Void")) {
5528 klass->byval_arg.type = (MonoTypeEnum)t;
5529 klass->this_arg.type = (MonoTypeEnum)t;
5532 if (MONO_CLASS_IS_INTERFACE (klass))
5533 klass->interface_id = mono_get_unique_iid (klass);
5538 * COM initialization is delayed until needed.
5539 * However when a [ComImport] attribute is present on a type it will trigger
5540 * the initialization. This is not a problem unless the BCL being executed
5541 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5544 init_com_from_comimport (MonoClass *klass)
5546 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5547 if (mono_security_core_clr_enabled ()) {
5548 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5549 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5550 /* but it can not be made available for application (i.e. user code) since all COM calls
5551 * are considered native calls. In this case we fail with a TypeLoadException (just like
5552 * Silverlight 2 does */
5553 mono_class_set_type_load_failure (klass, "");
5558 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5560 #endif /*DISABLE_COM*/
5563 * LOCKING: this assumes the loader lock is held
5566 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5568 gboolean system_namespace;
5569 gboolean is_corlib = mono_is_corlib_image (klass->image);
5571 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5573 /* if root of the hierarchy */
5574 if (system_namespace && !strcmp (klass->name, "Object")) {
5575 klass->parent = NULL;
5576 klass->instance_size = sizeof (MonoObject);
5579 if (!strcmp (klass->name, "<Module>")) {
5580 klass->parent = NULL;
5581 klass->instance_size = 0;
5585 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5586 /* Imported COM Objects always derive from __ComObject. */
5588 if (MONO_CLASS_IS_IMPORT (klass)) {
5589 init_com_from_comimport (klass);
5590 if (parent == mono_defaults.object_class)
5591 parent = mono_class_get_com_object_class ();
5595 /* set the parent to something useful and safe, but mark the type as broken */
5596 parent = mono_defaults.object_class;
5597 mono_class_set_type_load_failure (klass, "");
5601 klass->parent = parent;
5603 if (parent->generic_class && !parent->name) {
5605 * If the parent is a generic instance, we may get
5606 * called before it is fully initialized, especially
5607 * before it has its name.
5612 #ifndef DISABLE_REMOTING
5613 klass->marshalbyref = parent->marshalbyref;
5614 klass->contextbound = parent->contextbound;
5617 klass->delegate = parent->delegate;
5619 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5620 mono_class_set_is_com_object (klass);
5622 if (system_namespace) {
5623 #ifndef DISABLE_REMOTING
5624 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5625 klass->marshalbyref = 1;
5627 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5628 klass->contextbound = 1;
5630 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5631 klass->delegate = 1;
5634 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5635 (strcmp (klass->parent->name_space, "System") == 0)))
5636 klass->valuetype = 1;
5637 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5638 klass->valuetype = klass->enumtype = 1;
5640 /*klass->enumtype = klass->parent->enumtype; */
5642 /* initialize com types if COM interfaces are present */
5644 if (MONO_CLASS_IS_IMPORT (klass))
5645 init_com_from_comimport (klass);
5647 klass->parent = NULL;
5653 * mono_class_setup_supertypes:
5656 * Build the data structure needed to make fast type checks work.
5657 * This currently sets two fields in @class:
5658 * - idepth: distance between @class and System.Object in the type
5660 * - supertypes: array of classes: each element has a class in the hierarchy
5661 * starting from @class up to System.Object
5663 * LOCKING: This function is atomic, in case of contention we waste memory.
5666 mono_class_setup_supertypes (MonoClass *klass)
5669 MonoClass **supertypes;
5671 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5675 if (klass->parent && !klass->parent->supertypes)
5676 mono_class_setup_supertypes (klass->parent);
5678 klass->idepth = klass->parent->idepth + 1;
5682 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5683 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5685 if (klass->parent) {
5686 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5689 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5690 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5692 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5695 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5699 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5701 MonoClass *gtd = (MonoClass*)user_data;
5702 /* Only try to fix generic instances of @gtd */
5703 if (gclass->generic_class->container_class != gtd)
5706 /* Check if the generic instance has no parent. */
5707 if (gtd->parent && !gclass->parent)
5708 mono_generic_class_setup_parent (gclass, gtd);
5714 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5716 mono_class_set_type_load_failure (klass, "%s", msg);
5717 mono_error_set_type_load_class (error, klass, "%s", msg);
5721 * mono_class_create_from_typedef:
5722 * @image: image where the token is valid
5723 * @type_token: typedef token
5724 * @error: used to return any error found while creating the type
5726 * Create the MonoClass* representing the specified type token.
5727 * @type_token must be a TypeDef token.
5729 * FIXME: don't return NULL on failure, just the the caller figure it out.
5732 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5734 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5735 MonoClass *klass, *parent = NULL;
5736 guint32 cols [MONO_TYPEDEF_SIZE];
5737 guint32 cols_next [MONO_TYPEDEF_SIZE];
5738 guint tidx = mono_metadata_token_index (type_token);
5739 MonoGenericContext *context = NULL;
5740 const char *name, *nspace;
5742 MonoClass **interfaces;
5743 guint32 field_last, method_last;
5744 guint32 nesting_tokeen;
5746 mono_error_init (error);
5748 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5749 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5753 mono_loader_lock ();
5755 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5756 mono_loader_unlock ();
5760 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5762 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5763 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5765 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5768 klass->name_space = nspace;
5770 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5772 klass->image = image;
5773 klass->type_token = type_token;
5774 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5776 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5778 classes_size += sizeof (MonoClass);
5781 * Check whether we're a generic type definition.
5783 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5784 if (klass->generic_container) {
5785 klass->is_generic = 1;
5786 klass->generic_container->owner.klass = klass;
5787 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5788 context = &klass->generic_container->context;
5791 if (klass->generic_container)
5792 enable_gclass_recording ();
5794 if (cols [MONO_TYPEDEF_EXTENDS]) {
5796 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5798 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5799 /*WARNING: this must satisfy mono_metadata_type_hash*/
5800 klass->this_arg.byref = 1;
5801 klass->this_arg.data.klass = klass;
5802 klass->this_arg.type = MONO_TYPE_CLASS;
5803 klass->byval_arg.data.klass = klass;
5804 klass->byval_arg.type = MONO_TYPE_CLASS;
5806 parent = mono_class_get_checked (image, parent_token, error);
5807 if (parent && context) /* Always inflate */
5808 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5810 if (parent == NULL) {
5811 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5812 goto parent_failure;
5815 for (tmp = parent; tmp; tmp = tmp->parent) {
5817 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5818 goto parent_failure;
5820 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5821 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5822 goto parent_failure;
5827 mono_class_setup_parent (klass, parent);
5829 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5830 mono_class_setup_mono_type (klass);
5832 if (klass->generic_container)
5833 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5836 * This might access klass->byval_arg for recursion generated by generic constraints,
5837 * so it has to come after setup_mono_type ().
5839 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5840 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5841 if (!mono_error_ok (error)) {
5842 /*FIXME implement a mono_class_set_failure_from_mono_error */
5843 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5844 mono_loader_unlock ();
5845 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5850 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5854 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5858 klass->cast_class = klass->element_class = klass;
5860 if (!klass->enumtype) {
5861 if (!mono_metadata_interfaces_from_typedef_full (
5862 image, type_token, &interfaces, &icount, FALSE, context, error)){
5864 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5865 mono_loader_unlock ();
5866 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5870 klass->interfaces = interfaces;
5871 klass->interface_count = icount;
5872 klass->interfaces_inited = 1;
5875 /*g_print ("Load class %s\n", name);*/
5878 * Compute the field and method lists
5880 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5881 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5883 if (tt->rows > tidx){
5884 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5885 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5886 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5888 field_last = image->tables [MONO_TABLE_FIELD].rows;
5889 method_last = image->tables [MONO_TABLE_METHOD].rows;
5892 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5893 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5894 klass->field.count = field_last - klass->field.first;
5896 klass->field.count = 0;
5898 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5899 klass->method.count = method_last - klass->method.first;
5901 klass->method.count = 0;
5903 /* reserve space to store vector pointer in arrays */
5904 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5905 klass->instance_size += 2 * sizeof (gpointer);
5906 g_assert (klass->field.count == 0);
5909 if (klass->enumtype) {
5910 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5911 if (!enum_basetype) {
5912 /*set it to a default value as the whole runtime can't handle this to be null*/
5913 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5914 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5915 mono_loader_unlock ();
5916 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5919 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5923 * If we're a generic type definition, load the constraints.
5924 * We must do this after the class has been constructed to make certain recursive scenarios
5927 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5928 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5929 mono_loader_unlock ();
5930 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5934 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5935 if (!strncmp (name, "Vector", 6))
5936 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");
5939 mono_loader_unlock ();
5941 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5946 mono_class_setup_mono_type (klass);
5947 mono_loader_unlock ();
5948 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5952 /** Is klass a Nullable<T> ginst? */
5954 mono_class_is_nullable (MonoClass *klass)
5956 return klass->generic_class != NULL &&
5957 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5961 /** if klass is T? return T */
5963 mono_class_get_nullable_param (MonoClass *klass)
5965 g_assert (mono_class_is_nullable (klass));
5966 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5970 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5974 MonoGenericClass *gclass = klass->generic_class;
5976 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5977 if (!mono_error_ok (&error)) {
5978 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5979 klass->parent = mono_defaults.object_class;
5980 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5981 mono_error_cleanup (&error);
5985 mono_class_setup_parent (klass, klass->parent);
5987 if (klass->enumtype) {
5988 klass->cast_class = gtd->cast_class;
5989 klass->element_class = gtd->element_class;
5995 * Create the `MonoClass' for an instantiation of a generic type.
5996 * We only do this if we actually need it.
5999 mono_generic_class_get_class (MonoGenericClass *gclass)
6001 MonoClass *klass, *gklass;
6003 if (gclass->cached_class)
6004 return gclass->cached_class;
6006 mono_loader_lock ();
6007 if (gclass->cached_class) {
6008 mono_loader_unlock ();
6009 return gclass->cached_class;
6012 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6014 gklass = gclass->container_class;
6016 if (record_gclass_instantiation > 0)
6017 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6019 if (gklass->nested_in) {
6020 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6021 klass->nested_in = gklass->nested_in;
6024 klass->name = gklass->name;
6025 klass->name_space = gklass->name_space;
6027 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6029 klass->image = gklass->image;
6030 klass->flags = gklass->flags;
6031 klass->type_token = gklass->type_token;
6032 klass->field.count = gklass->field.count;
6034 klass->is_inflated = 1;
6035 klass->generic_class = gclass;
6037 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6038 klass->this_arg.type = klass->byval_arg.type;
6039 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6040 klass->this_arg.byref = TRUE;
6041 klass->enumtype = gklass->enumtype;
6042 klass->valuetype = gklass->valuetype;
6044 klass->cast_class = klass->element_class = klass;
6046 if (mono_class_is_nullable (klass))
6047 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6050 * We're not interested in the nested classes of a generic instance.
6051 * We use the generic type definition to look for nested classes.
6054 mono_generic_class_setup_parent (klass, gklass);
6056 if (gclass->is_dynamic) {
6058 * 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.
6059 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6060 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6062 if (!gklass->wastypebuilder)
6065 mono_class_setup_supertypes (klass);
6067 if (klass->enumtype) {
6069 * For enums, gklass->fields might not been set, but instance_size etc. is
6070 * already set in mono_reflection_create_internal_class (). For non-enums,
6071 * these will be computed normally in mono_class_layout_fields ().
6073 klass->instance_size = gklass->instance_size;
6074 klass->sizes.class_size = gklass->sizes.class_size;
6075 mono_memory_barrier ();
6076 klass->size_inited = 1;
6080 mono_memory_barrier ();
6081 gclass->cached_class = klass;
6083 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6085 inflated_classes ++;
6086 inflated_classes_size += sizeof (MonoClass);
6088 mono_loader_unlock ();
6094 get_image_for_container (MonoGenericContainer *container)
6097 if (container->is_anonymous) {
6098 result = container->owner.image;
6101 if (container->is_method) {
6102 MonoMethod *method = container->owner.method;
6103 g_assert_checked (method);
6104 klass = method->klass;
6106 klass = container->owner.klass;
6108 g_assert_checked (klass);
6109 result = klass->image;
6116 get_image_for_generic_param (MonoGenericParam *param)
6118 MonoGenericContainer *container = mono_generic_param_owner (param);
6119 g_assert_checked (container);
6120 return get_image_for_container (container);
6123 // Make a string in the designated image consisting of a single integer.
6124 #define INT_STRING_SIZE 16
6126 make_generic_name_string (MonoImage *image, int num)
6128 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6129 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6133 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6134 // pinfo is derived from param by the caller for us.
6136 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6138 MonoClass *klass, **ptr;
6140 MonoGenericContainer *container = mono_generic_param_owner (param);
6141 g_assert_checked (container);
6143 MonoImage *image = get_image_for_container (container);
6144 gboolean is_mvar = container->is_method;
6145 gboolean is_anonymous = container->is_anonymous;
6147 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6148 classes_size += sizeof (MonoClass);
6151 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6153 int n = mono_generic_param_num (param);
6154 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6158 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6159 } else if (is_mvar) {
6160 MonoMethod *omethod = container->owner.method;
6161 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6163 MonoClass *oklass = container->owner.klass;
6164 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6167 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6169 // Count non-NULL items in pinfo->constraints
6172 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6176 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6177 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6179 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6180 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6182 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6185 if (count - pos > 0) {
6186 klass->interface_count = count - pos;
6187 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6188 klass->interfaces_inited = TRUE;
6189 for (i = pos; i < count; i++)
6190 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6193 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6195 klass->inited = TRUE;
6196 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6197 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6198 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6200 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6201 klass->this_arg.type = klass->byval_arg.type;
6202 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6203 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6204 klass->this_arg.byref = TRUE;
6206 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6207 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6209 /*Init these fields to sane values*/
6210 klass->min_align = 1;
6212 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6213 * constrained to, the JIT depends on this.
6215 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6216 mono_memory_barrier ();
6217 klass->size_inited = 1;
6219 mono_class_setup_supertypes (klass);
6221 if (count - pos > 0) {
6222 mono_class_setup_vtable (klass->parent);
6223 if (mono_class_has_failure (klass->parent))
6224 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6226 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6232 #define FAST_CACHE_SIZE 16
6235 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6236 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6237 * we cache the MonoClasses.
6238 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6239 * LOCKING: Takes the image lock depending on @take_lock.
6242 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6244 int n = mono_generic_param_num (param);
6245 MonoImage *image = get_image_for_generic_param (param);
6246 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6247 MonoClass *klass = NULL;
6252 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6253 // For high numbers or constraints we have to use pointer hashes.
6254 if (param->gshared_constraint) {
6255 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6258 mono_image_lock (image);
6259 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6261 mono_image_unlock (image);
6266 if (n < FAST_CACHE_SIZE) {
6268 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6270 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6272 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6275 mono_image_lock (image);
6276 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6278 mono_image_unlock (image);
6285 * LOCKING: Image lock (param->image) must be held
6288 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6290 int n = mono_generic_param_num (param);
6291 MonoImage *image = get_image_for_generic_param (param);
6292 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6296 if (param->gshared_constraint) {
6297 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6299 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6300 mono_memory_barrier ();
6302 image->mvar_cache_constrained = ht;
6304 image->var_cache_constrained = ht;
6306 g_hash_table_insert (ht, param, klass);
6307 } else if (n < FAST_CACHE_SIZE) {
6309 /* Requires locking to avoid droping an already published class */
6310 if (!image->mvar_cache_fast)
6311 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6312 image->mvar_cache_fast [n] = klass;
6314 if (!image->var_cache_fast)
6315 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6316 image->var_cache_fast [n] = klass;
6319 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6321 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6323 ht = g_hash_table_new (NULL, NULL);
6324 mono_memory_barrier ();
6326 image->mvar_cache_slow = ht;
6328 image->var_cache_slow = ht;
6331 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6336 * LOCKING: Acquires the image lock (@image).
6339 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6341 MonoImage *image = get_image_for_generic_param (param);
6342 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6343 MonoClass *klass, *klass2;
6345 // If a klass already exists for this object and is cached, return it.
6346 if (pinfo) // Non-anonymous
6347 klass = pinfo->pklass;
6349 klass = get_anon_gparam_class (param, TRUE);
6354 // Create a new klass
6355 klass = make_generic_param_class (param, pinfo);
6357 // Now we need to cache the klass we created.
6358 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6359 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6360 // and allow our newly-created klass object to just leak.
6361 mono_memory_barrier ();
6363 mono_image_lock (image);
6365 // Here "klass2" refers to the klass potentially created by the other thread.
6366 if (pinfo) // Repeat check from above
6367 klass2 = pinfo->pklass;
6369 klass2 = get_anon_gparam_class (param, FALSE);
6376 pinfo->pklass = klass;
6378 set_anon_gparam_class (param, klass);
6380 mono_image_unlock (image);
6382 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6384 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6386 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6392 * mono_class_from_generic_parameter:
6393 * @param: Parameter to find/construct a class for.
6394 * @arg2: Is ignored.
6395 * @arg3: Is ignored.
6398 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6400 return mono_class_from_generic_parameter_internal (param);
6405 mono_ptr_class_get (MonoType *type)
6408 MonoClass *el_class;
6412 el_class = mono_class_from_mono_type (type);
6413 image = el_class->image;
6415 mono_image_lock (image);
6416 if (image->ptr_cache) {
6417 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6418 mono_image_unlock (image);
6422 mono_image_unlock (image);
6424 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6426 classes_size += sizeof (MonoClass);
6428 result->parent = NULL; /* no parent for PTR types */
6429 result->name_space = el_class->name_space;
6430 name = g_strdup_printf ("%s*", el_class->name);
6431 result->name = mono_image_strdup (image, name);
6434 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6436 result->image = el_class->image;
6437 result->inited = TRUE;
6438 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6439 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6440 result->cast_class = result->element_class = el_class;
6441 result->blittable = TRUE;
6443 result->byval_arg.type = MONO_TYPE_PTR;
6444 result->this_arg.type = result->byval_arg.type;
6445 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6446 result->this_arg.byref = TRUE;
6448 mono_class_setup_supertypes (result);
6450 mono_image_lock (image);
6451 if (image->ptr_cache) {
6453 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6454 mono_image_unlock (image);
6455 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6459 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6461 g_hash_table_insert (image->ptr_cache, el_class, result);
6462 mono_image_unlock (image);
6464 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6470 mono_fnptr_class_get (MonoMethodSignature *sig)
6473 static GHashTable *ptr_hash = NULL;
6475 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6477 mono_loader_lock ();
6480 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6482 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6483 mono_loader_unlock ();
6486 result = g_new0 (MonoClass, 1);
6488 result->parent = NULL; /* no parent for PTR types */
6489 result->name_space = "System";
6490 result->name = "MonoFNPtrFakeClass";
6492 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6494 result->image = mono_defaults.corlib; /* need to fix... */
6495 result->inited = TRUE;
6496 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6497 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6498 result->cast_class = result->element_class = result;
6499 result->blittable = TRUE;
6501 result->byval_arg.type = MONO_TYPE_FNPTR;
6502 result->this_arg.type = result->byval_arg.type;
6503 result->this_arg.data.method = result->byval_arg.data.method = sig;
6504 result->this_arg.byref = TRUE;
6505 result->blittable = TRUE;
6507 mono_class_setup_supertypes (result);
6509 g_hash_table_insert (ptr_hash, sig, result);
6511 mono_loader_unlock ();
6513 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6519 * mono_class_from_mono_type:
6520 * @type: describes the type to return
6522 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6525 mono_class_from_mono_type (MonoType *type)
6527 switch (type->type) {
6528 case MONO_TYPE_OBJECT:
6529 return type->data.klass? type->data.klass: mono_defaults.object_class;
6530 case MONO_TYPE_VOID:
6531 return type->data.klass? type->data.klass: mono_defaults.void_class;
6532 case MONO_TYPE_BOOLEAN:
6533 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6534 case MONO_TYPE_CHAR:
6535 return type->data.klass? type->data.klass: mono_defaults.char_class;
6537 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6539 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6541 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6543 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6545 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6547 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6549 return type->data.klass? type->data.klass: mono_defaults.int_class;
6551 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6553 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6555 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6557 return type->data.klass? type->data.klass: mono_defaults.single_class;
6559 return type->data.klass? type->data.klass: mono_defaults.double_class;
6560 case MONO_TYPE_STRING:
6561 return type->data.klass? type->data.klass: mono_defaults.string_class;
6562 case MONO_TYPE_TYPEDBYREF:
6563 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6564 case MONO_TYPE_ARRAY:
6565 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6567 return mono_ptr_class_get (type->data.type);
6568 case MONO_TYPE_FNPTR:
6569 return mono_fnptr_class_get (type->data.method);
6570 case MONO_TYPE_SZARRAY:
6571 return mono_array_class_get (type->data.klass, 1);
6572 case MONO_TYPE_CLASS:
6573 case MONO_TYPE_VALUETYPE:
6574 return type->data.klass;
6575 case MONO_TYPE_GENERICINST:
6576 return mono_generic_class_get_class (type->data.generic_class);
6577 case MONO_TYPE_MVAR:
6579 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6581 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6582 g_assert_not_reached ();
6585 // Yes, this returns NULL, even if it is documented as not doing so, but there
6586 // is no way for the code to make it this far, due to the assert above.
6591 * mono_type_retrieve_from_typespec
6592 * @image: context where the image is created
6593 * @type_spec: typespec token
6594 * @context: the generic context used to evaluate generic instantiations in
6597 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6599 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6601 *did_inflate = FALSE;
6606 if (context && (context->class_inst || context->method_inst)) {
6607 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6609 if (!mono_error_ok (error)) {
6615 *did_inflate = TRUE;
6622 * mono_class_create_from_typespec
6623 * @image: context where the image is created
6624 * @type_spec: typespec token
6625 * @context: the generic context used to evaluate generic instantiations in
6628 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6631 gboolean inflated = FALSE;
6632 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6633 return_val_if_nok (error, NULL);
6634 ret = mono_class_from_mono_type (t);
6636 mono_metadata_free_type (t);
6641 * mono_bounded_array_class_get:
6642 * @element_class: element class
6643 * @rank: the dimension of the array class
6644 * @bounded: whenever the array has non-zero bounds
6646 * Returns: A class object describing the array with element type @element_type and
6650 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6654 MonoClass *parent = NULL;
6655 GSList *list, *rootlist = NULL;
6659 g_assert (rank <= 255);
6662 /* bounded only matters for one-dimensional arrays */
6665 image = eclass->image;
6667 if (rank == 1 && !bounded) {
6669 * This case is very frequent not just during compilation because of calls
6670 * from mono_class_from_mono_type (), mono_array_new (),
6671 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6673 mono_os_mutex_lock (&image->szarray_cache_lock);
6674 if (!image->szarray_cache)
6675 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6676 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6677 mono_os_mutex_unlock (&image->szarray_cache_lock);
6681 mono_loader_lock ();
6683 mono_loader_lock ();
6685 if (!image->array_cache)
6686 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6688 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6689 for (; list; list = list->next) {
6690 klass = (MonoClass *)list->data;
6691 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6692 mono_loader_unlock ();
6699 parent = mono_defaults.array_class;
6700 if (!parent->inited)
6701 mono_class_init (parent);
6703 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6705 klass->image = image;
6706 klass->name_space = eclass->name_space;
6707 nsize = strlen (eclass->name);
6708 name = (char *)g_malloc (nsize + 2 + rank + 1);
6709 memcpy (name, eclass->name, nsize);
6712 memset (name + nsize + 1, ',', rank - 1);
6714 name [nsize + rank] = '*';
6715 name [nsize + rank + bounded] = ']';
6716 name [nsize + rank + bounded + 1] = 0;
6717 klass->name = mono_image_strdup (image, name);
6720 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6722 classes_size += sizeof (MonoClass);
6724 klass->type_token = 0;
6725 /* all arrays are marked serializable and sealed, bug #42779 */
6726 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6727 klass->parent = parent;
6728 klass->instance_size = mono_class_instance_size (klass->parent);
6730 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6731 /*Arrays of those two types are invalid.*/
6732 MonoError prepared_error;
6733 mono_error_init (&prepared_error);
6734 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6735 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6736 mono_error_cleanup (&prepared_error);
6737 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6738 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6739 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6740 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6742 /* element_size -1 is ok as this is not an instantitable type*/
6743 klass->sizes.element_size = -1;
6745 klass->sizes.element_size = mono_class_array_element_size (eclass);
6747 mono_class_setup_supertypes (klass);
6749 if (eclass->generic_class)
6750 mono_class_init (eclass);
6751 mono_class_init_sizes (eclass);
6752 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6753 /*FIXME we fail the array type, but we have to let other fields be set.*/
6755 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6759 if (eclass->enumtype)
6760 klass->cast_class = eclass->element_class;
6762 klass->cast_class = eclass;
6764 switch (klass->cast_class->byval_arg.type) {
6766 klass->cast_class = mono_defaults.byte_class;
6769 klass->cast_class = mono_defaults.int16_class;
6772 #if SIZEOF_VOID_P == 4
6776 klass->cast_class = mono_defaults.int32_class;
6779 #if SIZEOF_VOID_P == 8
6783 klass->cast_class = mono_defaults.int64_class;
6789 klass->element_class = eclass;
6791 if ((rank > 1) || bounded) {
6792 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6793 klass->byval_arg.type = MONO_TYPE_ARRAY;
6794 klass->byval_arg.data.array = at;
6795 at->eklass = eclass;
6797 /* FIXME: complete.... */
6799 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6800 klass->byval_arg.data.klass = eclass;
6802 klass->this_arg = klass->byval_arg;
6803 klass->this_arg.byref = 1;
6805 klass->generic_container = eclass->generic_container;
6807 if (rank == 1 && !bounded) {
6808 MonoClass *prev_class;
6810 mono_os_mutex_lock (&image->szarray_cache_lock);
6811 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6813 /* Someone got in before us */
6816 g_hash_table_insert (image->szarray_cache, eclass, klass);
6817 mono_os_mutex_unlock (&image->szarray_cache_lock);
6819 list = g_slist_append (rootlist, klass);
6820 g_hash_table_insert (image->array_cache, eclass, list);
6823 mono_loader_unlock ();
6825 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6831 * mono_array_class_get:
6832 * @element_class: element class
6833 * @rank: the dimension of the array class
6835 * Returns: A class object describing the array with element type @element_type and
6839 mono_array_class_get (MonoClass *eclass, guint32 rank)
6841 return mono_bounded_array_class_get (eclass, rank, FALSE);
6845 * mono_class_instance_size:
6848 * Use to get the size of a class in bytes.
6850 * Returns: The size of an object instance
6853 mono_class_instance_size (MonoClass *klass)
6855 if (!klass->size_inited)
6856 mono_class_init_sizes (klass);
6858 return klass->instance_size;
6862 * mono_class_min_align:
6865 * Use to get the computed minimum alignment requirements for the specified class.
6867 * Returns: minimum alignment requirements
6870 mono_class_min_align (MonoClass *klass)
6872 if (!klass->size_inited)
6873 mono_class_init_sizes (klass);
6875 return klass->min_align;
6879 * mono_class_value_size:
6882 * This function is used for value types, and return the
6883 * space and the alignment to store that kind of value object.
6885 * Returns: the size of a value of kind @klass
6888 mono_class_value_size (MonoClass *klass, guint32 *align)
6892 /* fixme: check disable, because we still have external revereces to
6893 * mscorlib and Dummy Objects
6895 /*g_assert (klass->valuetype);*/
6897 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6900 *align = klass->min_align;
6906 * mono_class_data_size:
6909 * Returns: The size of the static class data
6912 mono_class_data_size (MonoClass *klass)
6915 mono_class_init (klass);
6916 /* This can happen with dynamically created types */
6917 if (!klass->size_inited)
6918 mono_class_init_sizes (klass);
6920 /* in arrays, sizes.class_size is unioned with element_size
6921 * and arrays have no static fields
6925 return klass->sizes.class_size;
6929 * Auxiliary routine to mono_class_get_field
6931 * Takes a field index instead of a field token.
6933 static MonoClassField *
6934 mono_class_get_field_idx (MonoClass *klass, int idx)
6936 mono_class_setup_fields (klass);
6937 if (mono_class_has_failure (klass))
6941 if (klass->image->uncompressed_metadata) {
6943 * klass->field.first points to the FieldPtr table, while idx points into the
6944 * Field table, so we have to do a search.
6946 /*FIXME this is broken for types with multiple fields with the same name.*/
6947 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6950 for (i = 0; i < klass->field.count; ++i)
6951 if (mono_field_get_name (&klass->fields [i]) == name)
6952 return &klass->fields [i];
6953 g_assert_not_reached ();
6955 if (klass->field.count) {
6956 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6957 return &klass->fields [idx - klass->field.first];
6961 klass = klass->parent;
6967 * mono_class_get_field:
6968 * @class: the class to lookup the field.
6969 * @field_token: the field token
6971 * Returns: A MonoClassField representing the type and offset of
6972 * the field, or a NULL value if the field does not belong to this
6976 mono_class_get_field (MonoClass *klass, guint32 field_token)
6978 int idx = mono_metadata_token_index (field_token);
6980 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6982 return mono_class_get_field_idx (klass, idx - 1);
6986 * mono_class_get_field_from_name:
6987 * @klass: the class to lookup the field.
6988 * @name: the field name
6990 * Search the class @klass and it's parents for a field with the name @name.
6992 * Returns: The MonoClassField pointer of the named field or NULL
6995 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6997 return mono_class_get_field_from_name_full (klass, name, NULL);
7001 * mono_class_get_field_from_name_full:
7002 * @klass: the class to lookup the field.
7003 * @name: the field name
7004 * @type: the type of the fields. This optional.
7006 * Search the class @klass and it's parents for a field with the name @name and type @type.
7008 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7009 * of its generic type definition.
7011 * Returns: The MonoClassField pointer of the named field or NULL
7014 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7018 mono_class_setup_fields (klass);
7019 if (mono_class_has_failure (klass))
7023 for (i = 0; i < klass->field.count; ++i) {
7024 MonoClassField *field = &klass->fields [i];
7026 if (strcmp (name, mono_field_get_name (field)) != 0)
7030 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7031 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7036 klass = klass->parent;
7042 * mono_class_get_field_token:
7043 * @field: the field we need the token of
7045 * Get the token of a field. Note that the tokesn is only valid for the image
7046 * the field was loaded from. Don't use this function for fields in dynamic types.
7048 * Returns: The token representing the field in the image it was loaded from.
7051 mono_class_get_field_token (MonoClassField *field)
7053 MonoClass *klass = field->parent;
7056 mono_class_setup_fields (klass);
7061 for (i = 0; i < klass->field.count; ++i) {
7062 if (&klass->fields [i] == field) {
7063 int idx = klass->field.first + i + 1;
7065 if (klass->image->uncompressed_metadata)
7066 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7067 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7070 klass = klass->parent;
7073 g_assert_not_reached ();
7078 mono_field_get_index (MonoClassField *field)
7080 int index = field - field->parent->fields;
7082 g_assert (index >= 0 && index < field->parent->field.count);
7088 * mono_class_get_field_default_value:
7090 * Return the default value of the field as a pointer into the metadata blob.
7093 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7096 guint32 constant_cols [MONO_CONSTANT_SIZE];
7098 MonoClass *klass = field->parent;
7100 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7102 if (!klass->ext || !klass->ext->field_def_values) {
7103 MonoFieldDefaultValue *def_values;
7105 mono_class_alloc_ext (klass);
7107 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7109 mono_image_lock (klass->image);
7110 mono_memory_barrier ();
7111 if (!klass->ext->field_def_values)
7112 klass->ext->field_def_values = def_values;
7113 mono_image_unlock (klass->image);
7116 field_index = mono_field_get_index (field);
7118 if (!klass->ext->field_def_values [field_index].data) {
7119 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7123 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7125 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7126 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7127 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7130 *def_type = klass->ext->field_def_values [field_index].def_type;
7131 return klass->ext->field_def_values [field_index].data;
7135 mono_property_get_index (MonoProperty *prop)
7137 int index = prop - prop->parent->ext->properties;
7139 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7145 * mono_class_get_property_default_value:
7147 * Return the default value of the field as a pointer into the metadata blob.
7150 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7153 guint32 constant_cols [MONO_CONSTANT_SIZE];
7154 MonoClass *klass = property->parent;
7156 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7158 * We don't cache here because it is not used by C# so it's quite rare, but
7159 * we still do the lookup in klass->ext because that is where the data
7160 * is stored for dynamic assemblies.
7163 if (image_is_dynamic (klass->image)) {
7164 int prop_index = mono_property_get_index (property);
7165 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7166 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7167 return klass->ext->prop_def_values [prop_index].data;
7171 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7175 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7176 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7177 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7181 mono_class_get_event_token (MonoEvent *event)
7183 MonoClass *klass = event->parent;
7188 for (i = 0; i < klass->ext->event.count; ++i) {
7189 if (&klass->ext->events [i] == event)
7190 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7193 klass = klass->parent;
7196 g_assert_not_reached ();
7201 * mono_class_get_property_from_name:
7203 * @name: name of the property to lookup in the specified class
7205 * Use this method to lookup a property in a class
7206 * Returns: the MonoProperty with the given name, or NULL if the property
7207 * does not exist on the @klass.
7210 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7214 gpointer iter = NULL;
7215 while ((p = mono_class_get_properties (klass, &iter))) {
7216 if (! strcmp (name, p->name))
7219 klass = klass->parent;
7225 * mono_class_get_property_token:
7226 * @prop: MonoProperty to query
7228 * Returns: The ECMA token for the specified property.
7231 mono_class_get_property_token (MonoProperty *prop)
7233 MonoClass *klass = prop->parent;
7237 gpointer iter = NULL;
7238 while ((p = mono_class_get_properties (klass, &iter))) {
7239 if (&klass->ext->properties [i] == prop)
7240 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7244 klass = klass->parent;
7247 g_assert_not_reached ();
7252 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7254 const char *name, *nspace;
7255 if (image_is_dynamic (image))
7256 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7258 switch (type_token & 0xff000000){
7259 case MONO_TOKEN_TYPE_DEF: {
7260 guint32 cols [MONO_TYPEDEF_SIZE];
7261 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7262 guint tidx = mono_metadata_token_index (type_token);
7264 if (tidx > tt->rows)
7265 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7267 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7268 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7269 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7270 if (strlen (nspace) == 0)
7271 return g_strdup_printf ("%s", name);
7273 return g_strdup_printf ("%s.%s", nspace, name);
7276 case MONO_TOKEN_TYPE_REF: {
7278 guint32 cols [MONO_TYPEREF_SIZE];
7279 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7280 guint tidx = mono_metadata_token_index (type_token);
7283 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7285 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7286 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7287 mono_error_cleanup (&error);
7291 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7292 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7293 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7294 if (strlen (nspace) == 0)
7295 return g_strdup_printf ("%s", name);
7297 return g_strdup_printf ("%s.%s", nspace, name);
7300 case MONO_TOKEN_TYPE_SPEC:
7301 return g_strdup_printf ("Typespec 0x%08x", type_token);
7303 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7308 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7310 if (image_is_dynamic (image))
7311 return g_strdup_printf ("DynamicAssembly %s", image->name);
7313 switch (type_token & 0xff000000){
7314 case MONO_TOKEN_TYPE_DEF:
7315 if (image->assembly)
7316 return mono_stringify_assembly_name (&image->assembly->aname);
7317 else if (image->assembly_name)
7318 return g_strdup (image->assembly_name);
7319 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7320 case MONO_TOKEN_TYPE_REF: {
7322 MonoAssemblyName aname;
7323 guint32 cols [MONO_TYPEREF_SIZE];
7324 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7325 guint32 idx = mono_metadata_token_index (type_token);
7328 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7330 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7331 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7332 mono_error_cleanup (&error);
7335 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7337 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7338 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7339 case MONO_RESOLUTION_SCOPE_MODULE:
7341 return g_strdup ("");
7342 case MONO_RESOLUTION_SCOPE_MODULEREF:
7344 return g_strdup ("");
7345 case MONO_RESOLUTION_SCOPE_TYPEREF:
7347 return g_strdup ("");
7348 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7349 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7350 return mono_stringify_assembly_name (&aname);
7352 g_assert_not_reached ();
7356 case MONO_TOKEN_TYPE_SPEC:
7358 return g_strdup ("");
7360 g_assert_not_reached ();
7367 * mono_class_get_full:
7368 * @image: the image where the class resides
7369 * @type_token: the token for the class
7370 * @context: the generic context used to evaluate generic instantiations in
7371 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7373 * Returns: The MonoClass that represents @type_token in @image
7376 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7380 klass = mono_class_get_checked (image, type_token, &error);
7382 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7383 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7385 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7391 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7395 mono_error_init (error);
7396 klass = mono_class_get_checked (image, type_token, error);
7398 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7399 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7404 * mono_class_get_checked:
7405 * @image: the image where the class resides
7406 * @type_token: the token for the class
7407 * @error: error object to return any error
7409 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7412 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7414 MonoClass *klass = NULL;
7416 mono_error_init (error);
7418 if (image_is_dynamic (image)) {
7419 int table = mono_metadata_token_table (type_token);
7421 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7422 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7425 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7429 switch (type_token & 0xff000000){
7430 case MONO_TOKEN_TYPE_DEF:
7431 klass = mono_class_create_from_typedef (image, type_token, error);
7433 case MONO_TOKEN_TYPE_REF:
7434 klass = mono_class_from_typeref_checked (image, type_token, error);
7436 case MONO_TOKEN_TYPE_SPEC:
7437 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7440 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7444 /* Generic case, should be avoided for when a better error is possible. */
7445 if (!klass && mono_error_ok (error)) {
7446 char *name = mono_class_name_from_token (image, type_token);
7447 char *assembly = mono_assembly_name_from_token (image, type_token);
7448 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7456 * mono_type_get_checked:
7457 * @image: the image where the type resides
7458 * @type_token: the token for the type
7459 * @context: the generic context used to evaluate generic instantiations in
7460 * @error: Error handling context
7462 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7464 * Returns: The MonoType that represents @type_token in @image
7467 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7469 MonoType *type = NULL;
7470 gboolean inflated = FALSE;
7472 mono_error_init (error);
7474 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7475 if (image_is_dynamic (image)) {
7476 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7477 return_val_if_nok (error, NULL);
7478 return mono_class_get_type (klass);
7481 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7482 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7489 return mono_class_get_type (klass);
7492 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7499 MonoType *tmp = type;
7500 type = mono_class_get_type (mono_class_from_mono_type (type));
7501 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7502 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7503 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7505 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7507 if (type->type != tmp->type)
7510 mono_metadata_free_type (tmp);
7517 * @image: image where the class token will be looked up.
7518 * @type_token: a type token from the image
7520 * Returns the MonoClass with the given @type_token on the @image
7523 mono_class_get (MonoImage *image, guint32 type_token)
7525 return mono_class_get_full (image, type_token, NULL);
7529 * mono_image_init_name_cache:
7531 * Initializes the class name cache stored in image->name_cache.
7533 * LOCKING: Acquires the corresponding image lock.
7536 mono_image_init_name_cache (MonoImage *image)
7538 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7539 guint32 cols [MONO_TYPEDEF_SIZE];
7542 guint32 i, visib, nspace_index;
7543 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7545 if (image->name_cache)
7548 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7550 if (image_is_dynamic (image)) {
7551 mono_image_lock (image);
7552 if (image->name_cache) {
7553 /* Somebody initialized it before us */
7554 g_hash_table_destroy (the_name_cache);
7556 mono_atomic_store_release (&image->name_cache, the_name_cache);
7558 mono_image_unlock (image);
7562 /* Temporary hash table to avoid lookups in the nspace_table */
7563 name_cache2 = g_hash_table_new (NULL, NULL);
7565 for (i = 1; i <= t->rows; ++i) {
7566 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7567 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7569 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7570 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7572 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7574 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7575 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7577 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7578 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7579 if (!nspace_table) {
7580 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7581 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7582 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7585 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7588 /* Load type names from EXPORTEDTYPES table */
7590 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7591 guint32 cols [MONO_EXP_TYPE_SIZE];
7594 for (i = 0; i < t->rows; ++i) {
7595 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7597 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7598 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7602 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7603 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7605 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7606 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7607 if (!nspace_table) {
7608 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7609 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7610 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7613 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7617 g_hash_table_destroy (name_cache2);
7619 mono_image_lock (image);
7620 if (image->name_cache) {
7621 /* Somebody initialized it before us */
7622 g_hash_table_destroy (the_name_cache);
7624 mono_atomic_store_release (&image->name_cache, the_name_cache);
7626 mono_image_unlock (image);
7629 /*FIXME Only dynamic assemblies should allow this operation.*/
7631 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7632 const char *name, guint32 index)
7634 GHashTable *nspace_table;
7635 GHashTable *name_cache;
7638 mono_image_init_name_cache (image);
7639 mono_image_lock (image);
7641 name_cache = image->name_cache;
7642 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7643 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7644 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7647 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7648 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7650 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7652 mono_image_unlock (image);
7661 find_nocase (gpointer key, gpointer value, gpointer user_data)
7663 char *name = (char*)key;
7664 FindUserData *data = (FindUserData*)user_data;
7666 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7667 data->value = value;
7671 * mono_class_from_name_case:
7672 * @image: The MonoImage where the type is looked up in
7673 * @name_space: the type namespace
7674 * @name: the type short name.
7675 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7677 * Obtains a MonoClass with a given namespace and a given name which
7678 * is located in the given MonoImage. The namespace and name
7679 * lookups are case insensitive.
7682 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7685 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7686 mono_error_cleanup (&error);
7692 * mono_class_from_name_case:
7693 * @image: The MonoImage where the type is looked up in
7694 * @name_space: the type namespace
7695 * @name: the type short name.
7698 * Obtains a MonoClass with a given namespace and a given name which
7699 * is located in the given MonoImage. The namespace and name
7700 * lookups are case insensitive.
7702 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7703 * was not found. The @error object will contain information about the problem
7707 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7709 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7710 guint32 cols [MONO_TYPEDEF_SIZE];
7715 mono_error_init (error);
7717 if (image_is_dynamic (image)) {
7719 FindUserData user_data;
7721 mono_image_init_name_cache (image);
7722 mono_image_lock (image);
7724 user_data.key = name_space;
7725 user_data.value = NULL;
7726 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7728 if (user_data.value) {
7729 GHashTable *nspace_table = (GHashTable*)user_data.value;
7731 user_data.key = name;
7732 user_data.value = NULL;
7734 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7736 if (user_data.value)
7737 token = GPOINTER_TO_UINT (user_data.value);
7740 mono_image_unlock (image);
7743 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7749 /* add a cache if needed */
7750 for (i = 1; i <= t->rows; ++i) {
7751 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7752 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7754 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7755 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7757 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7759 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7760 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7761 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7762 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7768 return_nested_in (MonoClass *klass, char *nested)
7771 char *s = strchr (nested, '/');
7772 gpointer iter = NULL;
7779 while ((found = mono_class_get_nested_types (klass, &iter))) {
7780 if (strcmp (found->name, nested) == 0) {
7782 return return_nested_in (found, s);
7790 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7792 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7793 MonoImage *file_image;
7797 mono_error_init (error);
7800 * The EXPORTEDTYPES table only contains public types, so have to search the
7802 * Note: image->modules contains the contents of the MODULEREF table, while
7803 * the real module list is in the FILE table.
7805 for (i = 0; i < file_table->rows; i++) {
7806 guint32 cols [MONO_FILE_SIZE];
7807 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7808 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7811 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7813 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7814 if (klass || !is_ok (error))
7823 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7825 GHashTable *nspace_table;
7826 MonoImage *loaded_image;
7833 mono_error_init (error);
7835 // Checking visited images avoids stack overflows when cyclic references exist.
7836 if (g_hash_table_lookup (visited_images, image))
7839 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7841 if ((nested = strchr (name, '/'))) {
7842 int pos = nested - name;
7843 int len = strlen (name);
7846 memcpy (buf, name, len + 1);
7848 nested = buf + pos + 1;
7852 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7853 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7854 gboolean res = get_class_from_name (image, name_space, name, &klass);
7857 klass = search_modules (image, name_space, name, error);
7862 return klass ? return_nested_in (klass, nested) : NULL;
7868 mono_image_init_name_cache (image);
7869 mono_image_lock (image);
7871 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7874 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7876 mono_image_unlock (image);
7878 if (!token && image_is_dynamic (image) && image->modules) {
7879 /* Search modules as well */
7880 for (i = 0; i < image->module_count; ++i) {
7881 MonoImage *module = image->modules [i];
7883 klass = mono_class_from_name_checked (module, name_space, name, error);
7884 if (klass || !is_ok (error))
7890 klass = search_modules (image, name_space, name, error);
7891 if (klass || !is_ok (error))
7896 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7897 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7898 guint32 cols [MONO_EXP_TYPE_SIZE];
7901 idx = mono_metadata_token_index (token);
7903 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7905 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7906 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7907 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7910 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7912 return klass ? return_nested_in (klass, nested) : NULL;
7914 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7915 guint32 assembly_idx;
7917 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7919 mono_assembly_load_reference (image, assembly_idx - 1);
7920 g_assert (image->references [assembly_idx - 1]);
7921 if (image->references [assembly_idx - 1] == (gpointer)-1)
7923 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7925 return klass ? return_nested_in (klass, nested) : NULL;
7928 g_assert_not_reached ();
7932 token = MONO_TOKEN_TYPE_DEF | token;
7934 klass = mono_class_get_checked (image, token, error);
7936 return return_nested_in (klass, nested);
7941 * mono_class_from_name_checked:
7942 * @image: The MonoImage where the type is looked up in
7943 * @name_space: the type namespace
7944 * @name: the type short name.
7946 * Obtains a MonoClass with a given namespace and a given name which
7947 * is located in the given MonoImage.
7949 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7950 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7953 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7956 GHashTable *visited_images;
7958 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7960 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7962 g_hash_table_destroy (visited_images);
7968 * mono_class_from_name:
7969 * @image: The MonoImage where the type is looked up in
7970 * @name_space: the type namespace
7971 * @name: the type short name.
7973 * Obtains a MonoClass with a given namespace and a given name which
7974 * is located in the given MonoImage.
7976 * To reference nested classes, use the "/" character as a separator.
7977 * For example use "Foo/Bar" to reference the class Bar that is nested
7978 * inside Foo, like this: "class Foo { class Bar {} }".
7981 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7986 klass = mono_class_from_name_checked (image, name_space, name, &error);
7987 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7993 * mono_class_load_from_name:
7994 * @image: The MonoImage where the type is looked up in
7995 * @name_space: the type namespace
7996 * @name: the type short name.
7998 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7999 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8000 * If they are missing. Thing of System.Object or System.String.
8003 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8008 klass = mono_class_from_name_checked (image, name_space, name, &error);
8010 g_error ("Runtime critical type %s.%s not found", name_space, name);
8011 if (!mono_error_ok (&error))
8012 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8017 * mono_class_try_load_from_name:
8018 * @image: The MonoImage where the type is looked up in
8019 * @name_space: the type namespace
8020 * @name: the type short name.
8022 * This function tries to load a type, returning the class was found or NULL otherwise.
8023 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8025 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8026 * a type that we would otherwise assume to be available but was not due some error.
8030 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8035 klass = mono_class_from_name_checked (image, name_space, name, &error);
8036 if (!mono_error_ok (&error))
8037 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8043 * mono_class_is_subclass_of:
8044 * @klass: class to probe if it is a subclass of another one
8045 * @klassc: the class we suspect is the base class
8046 * @check_interfaces: whether we should perform interface checks
8048 * This method determines whether @klass is a subclass of @klassc.
8050 * If the @check_interfaces flag is set, then if @klassc is an interface
8051 * this method return TRUE if the @klass implements the interface or
8052 * if @klass is an interface, if one of its base classes is @klass.
8054 * If @check_interfaces is false then, then if @klass is not an interface
8055 * then it returns TRUE if the @klass is a subclass of @klassc.
8057 * if @klass is an interface and @klassc is System.Object, then this function
8062 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8063 gboolean check_interfaces)
8065 /* FIXME test for interfaces with variant generic arguments */
8066 mono_class_init (klass);
8067 mono_class_init (klassc);
8069 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8070 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8072 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8075 for (i = 0; i < klass->interface_count; i ++) {
8076 MonoClass *ic = klass->interfaces [i];
8081 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8086 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8089 if (klassc == mono_defaults.object_class)
8096 mono_type_is_generic_argument (MonoType *type)
8098 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8102 mono_class_has_variant_generic_params (MonoClass *klass)
8105 MonoGenericContainer *container;
8107 if (!klass->generic_class)
8110 container = klass->generic_class->container_class->generic_container;
8112 for (i = 0; i < container->type_argc; ++i)
8113 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8120 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8122 if (target == candidate)
8125 if (check_for_reference_conv &&
8126 mono_type_is_generic_argument (&target->byval_arg) &&
8127 mono_type_is_generic_argument (&candidate->byval_arg)) {
8128 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8129 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8131 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8134 if (!mono_class_is_assignable_from (target, candidate))
8140 * @container the generic container from the GTD
8141 * @klass: the class to be assigned to
8142 * @oklass: the source class
8144 * Both @klass and @oklass must be instances of the same generic interface.
8146 * Returns: TRUE if @klass can be assigned to a @klass variable
8149 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8152 MonoType **klass_argv, **oklass_argv;
8153 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8154 MonoGenericContainer *container = klass_gtd->generic_container;
8156 if (klass == oklass)
8159 /*Viable candidates are instances of the same generic interface*/
8160 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8163 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8164 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8166 for (j = 0; j < container->type_argc; ++j) {
8167 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8168 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8170 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8174 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8175 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8177 if (param1_class != param2_class) {
8178 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8179 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8181 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8182 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8192 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8194 MonoGenericParam *gparam, *ogparam;
8195 MonoGenericParamInfo *tinfo, *cinfo;
8196 MonoClass **candidate_class;
8197 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8200 if (target == candidate)
8202 if (target->byval_arg.type != candidate->byval_arg.type)
8205 gparam = target->byval_arg.data.generic_param;
8206 ogparam = candidate->byval_arg.data.generic_param;
8207 tinfo = mono_generic_param_info (gparam);
8208 cinfo = mono_generic_param_info (ogparam);
8210 class_constraint_satisfied = FALSE;
8211 valuetype_constraint_satisfied = FALSE;
8213 /*candidate must have a super set of target's special constraints*/
8214 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8215 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8217 if (cinfo->constraints) {
8218 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8219 MonoClass *cc = *candidate_class;
8221 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8222 class_constraint_satisfied = TRUE;
8223 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8224 valuetype_constraint_satisfied = TRUE;
8227 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8228 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8230 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8232 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8234 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8235 valuetype_constraint_satisfied)) {
8240 /*candidate type constraints must be a superset of target's*/
8241 if (tinfo->constraints) {
8242 MonoClass **target_class;
8243 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8244 MonoClass *tc = *target_class;
8247 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8248 * check it's constraints since it satisfy the constraint by itself.
8250 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8253 if (!cinfo->constraints)
8256 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8257 MonoClass *cc = *candidate_class;
8259 if (mono_class_is_assignable_from (tc, cc))
8263 * This happens when we have the following:
8265 * Bar<K> where K : IFace
8266 * Foo<T, U> where T : U where U : IFace
8268 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8271 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8272 if (mono_gparam_is_assignable_from (target, cc))
8276 if (!*candidate_class)
8281 /*candidate itself must have a constraint that satisfy target*/
8282 if (cinfo->constraints) {
8283 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8284 MonoClass *cc = *candidate_class;
8285 if (mono_class_is_assignable_from (target, cc))
8293 * mono_class_is_assignable_from:
8294 * @klass: the class to be assigned to
8295 * @oklass: the source class
8297 * Returns: TRUE if an instance of object oklass can be assigned to an
8298 * instance of object @klass
8301 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8304 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8306 mono_class_init (klass);
8308 if (!oklass->inited)
8309 mono_class_init (oklass);
8311 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8314 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8315 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8317 return mono_gparam_is_assignable_from (klass, oklass);
8320 if (MONO_CLASS_IS_INTERFACE (klass)) {
8321 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8322 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8323 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8327 for (i = 0; constraints [i]; ++i) {
8328 if (mono_class_is_assignable_from (klass, constraints [i]))
8336 /* interface_offsets might not be set for dynamic classes */
8337 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8339 * oklass might be a generic type parameter but they have
8340 * interface_offsets set.
8342 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8343 if (!is_ok (&error)) {
8344 mono_error_cleanup (&error);
8349 if (!oklass->interface_bitmap)
8350 /* Happens with generic instances of not-yet created dynamic types */
8352 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8355 if (mono_class_has_variant_generic_params (klass)) {
8357 mono_class_setup_interfaces (oklass, &error);
8358 if (!mono_error_ok (&error)) {
8359 mono_error_cleanup (&error);
8363 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8364 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8365 MonoClass *iface = oklass->interfaces_packed [i];
8367 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8372 } else if (klass->delegate) {
8373 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8375 }else if (klass->rank) {
8376 MonoClass *eclass, *eoclass;
8378 if (oklass->rank != klass->rank)
8381 /* vectors vs. one dimensional arrays */
8382 if (oklass->byval_arg.type != klass->byval_arg.type)
8385 eclass = klass->cast_class;
8386 eoclass = oklass->cast_class;
8389 * a is b does not imply a[] is b[] when a is a valuetype, and
8390 * b is a reference type.
8393 if (eoclass->valuetype) {
8394 if ((eclass == mono_defaults.enum_class) ||
8395 (eclass == mono_defaults.enum_class->parent) ||
8396 (eclass == mono_defaults.object_class))
8400 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8401 } else if (mono_class_is_nullable (klass)) {
8402 if (mono_class_is_nullable (oklass))
8403 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8405 return mono_class_is_assignable_from (klass->cast_class, oklass);
8406 } else if (klass == mono_defaults.object_class)
8409 return mono_class_has_parent (oklass, klass);
8412 /*Check if @oklass is variant compatible with @klass.*/
8414 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8417 MonoType **klass_argv, **oklass_argv;
8418 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8419 MonoGenericContainer *container = klass_gtd->generic_container;
8421 /*Viable candidates are instances of the same generic interface*/
8422 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8425 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8426 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8428 for (j = 0; j < container->type_argc; ++j) {
8429 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8430 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8432 if (param1_class->valuetype != param2_class->valuetype)
8436 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8437 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8439 if (param1_class != param2_class) {
8440 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8441 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8443 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8444 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8452 /*Check if @candidate implements the interface @target*/
8454 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8458 gboolean is_variant = mono_class_has_variant_generic_params (target);
8460 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8461 if (mono_class_is_variant_compatible_slow (target, candidate))
8466 if (candidate == target)
8469 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8470 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8471 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8473 if (tb && tb->interfaces) {
8474 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8475 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8476 MonoClass *iface_class;
8478 /* we can't realize the type here since it can do pretty much anything. */
8481 iface_class = mono_class_from_mono_type (iface->type);
8482 if (iface_class == target)
8484 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8486 if (mono_class_implement_interface_slow (target, iface_class))
8491 /*setup_interfaces don't mono_class_init anything*/
8492 /*FIXME this doesn't handle primitive type arrays.
8493 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8494 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8496 mono_class_setup_interfaces (candidate, &error);
8497 if (!mono_error_ok (&error)) {
8498 mono_error_cleanup (&error);
8502 for (i = 0; i < candidate->interface_count; ++i) {
8503 if (candidate->interfaces [i] == target)
8506 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8509 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8513 candidate = candidate->parent;
8514 } while (candidate);
8520 * Check if @oklass can be assigned to @klass.
8521 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8524 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8526 if (candidate == target)
8528 if (target == mono_defaults.object_class)
8531 if (mono_class_has_parent (candidate, target))
8534 /*If target is not an interface there is no need to check them.*/
8535 if (MONO_CLASS_IS_INTERFACE (target))
8536 return mono_class_implement_interface_slow (target, candidate);
8538 if (target->delegate && mono_class_has_variant_generic_params (target))
8539 return mono_class_is_variant_compatible (target, candidate, FALSE);
8542 MonoClass *eclass, *eoclass;
8544 if (target->rank != candidate->rank)
8547 /* vectors vs. one dimensional arrays */
8548 if (target->byval_arg.type != candidate->byval_arg.type)
8551 eclass = target->cast_class;
8552 eoclass = candidate->cast_class;
8555 * a is b does not imply a[] is b[] when a is a valuetype, and
8556 * b is a reference type.
8559 if (eoclass->valuetype) {
8560 if ((eclass == mono_defaults.enum_class) ||
8561 (eclass == mono_defaults.enum_class->parent) ||
8562 (eclass == mono_defaults.object_class))
8566 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8568 /*FIXME properly handle nullables */
8569 /*FIXME properly handle (M)VAR */
8574 * mono_class_get_cctor:
8575 * @klass: A MonoClass pointer
8577 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8580 mono_class_get_cctor (MonoClass *klass)
8582 MonoCachedClassInfo cached_info;
8584 if (image_is_dynamic (klass->image)) {
8586 * has_cctor is not set for these classes because mono_class_init () is
8589 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8592 if (!klass->has_cctor)
8595 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8597 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8598 if (!mono_error_ok (&error))
8599 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8603 if (klass->generic_class && !klass->methods)
8604 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8606 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8610 * mono_class_get_finalizer:
8611 * @klass: The MonoClass pointer
8613 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8616 mono_class_get_finalizer (MonoClass *klass)
8618 MonoCachedClassInfo cached_info;
8621 mono_class_init (klass);
8622 if (!mono_class_has_finalizer (klass))
8625 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8627 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8628 if (!mono_error_ok (&error))
8629 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8632 mono_class_setup_vtable (klass);
8633 return klass->vtable [finalize_slot];
8638 * mono_class_needs_cctor_run:
8639 * @klass: the MonoClass pointer
8640 * @caller: a MonoMethod describing the caller
8642 * Determines whenever the class has a static constructor and whenever it
8643 * needs to be called when executing CALLER.
8646 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8650 method = mono_class_get_cctor (klass);
8652 return (method == caller) ? FALSE : TRUE;
8658 * mono_class_array_element_size:
8661 * Returns: The number of bytes an element of type @klass
8662 * uses when stored into an array.
8665 mono_class_array_element_size (MonoClass *klass)
8667 MonoType *type = &klass->byval_arg;
8670 switch (type->type) {
8673 case MONO_TYPE_BOOLEAN:
8677 case MONO_TYPE_CHAR:
8686 case MONO_TYPE_CLASS:
8687 case MONO_TYPE_STRING:
8688 case MONO_TYPE_OBJECT:
8689 case MONO_TYPE_SZARRAY:
8690 case MONO_TYPE_ARRAY:
8691 return sizeof (gpointer);
8696 case MONO_TYPE_VALUETYPE:
8697 if (type->data.klass->enumtype) {
8698 type = mono_class_enum_basetype (type->data.klass);
8699 klass = klass->element_class;
8702 return mono_class_instance_size (klass) - sizeof (MonoObject);
8703 case MONO_TYPE_GENERICINST:
8704 type = &type->data.generic_class->container_class->byval_arg;
8707 case MONO_TYPE_MVAR: {
8710 return mono_type_size (type, &align);
8712 case MONO_TYPE_VOID:
8716 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8722 * mono_array_element_size:
8723 * @ac: pointer to a #MonoArrayClass
8725 * Returns: The size of single array element.
8728 mono_array_element_size (MonoClass *ac)
8730 g_assert (ac->rank);
8731 return ac->sizes.element_size;
8735 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8736 MonoGenericContext *context)
8739 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8740 g_assert (mono_error_ok (&error));
8745 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8746 MonoGenericContext *context, MonoError *error)
8748 mono_error_init (error);
8750 if (image_is_dynamic (image)) {
8751 MonoClass *tmp_handle_class;
8752 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8754 mono_error_assert_ok (error);
8755 g_assert (tmp_handle_class);
8757 *handle_class = tmp_handle_class;
8759 if (tmp_handle_class == mono_defaults.typehandle_class)
8760 return &((MonoClass*)obj)->byval_arg;
8765 switch (token & 0xff000000) {
8766 case MONO_TOKEN_TYPE_DEF:
8767 case MONO_TOKEN_TYPE_REF:
8768 case MONO_TOKEN_TYPE_SPEC: {
8771 *handle_class = mono_defaults.typehandle_class;
8772 type = mono_type_get_checked (image, token, context, error);
8776 mono_class_init (mono_class_from_mono_type (type));
8777 /* We return a MonoType* as handle */
8780 case MONO_TOKEN_FIELD_DEF: {
8782 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8784 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8788 *handle_class = mono_defaults.fieldhandle_class;
8789 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8793 mono_class_init (klass);
8794 return mono_class_get_field (klass, token);
8796 case MONO_TOKEN_METHOD_DEF:
8797 case MONO_TOKEN_METHOD_SPEC: {
8799 meth = mono_get_method_checked (image, token, NULL, context, error);
8801 *handle_class = mono_defaults.methodhandle_class;
8807 case MONO_TOKEN_MEMBER_REF: {
8808 guint32 cols [MONO_MEMBERREF_SIZE];
8810 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8811 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8812 mono_metadata_decode_blob_size (sig, &sig);
8813 if (*sig == 0x6) { /* it's a field */
8815 MonoClassField *field;
8816 field = mono_field_from_token_checked (image, token, &klass, context, error);
8818 *handle_class = mono_defaults.fieldhandle_class;
8822 meth = mono_get_method_checked (image, token, NULL, context, error);
8824 *handle_class = mono_defaults.methodhandle_class;
8829 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8835 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8837 MonoClass *handle_class;
8838 mono_error_init (error);
8839 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8843 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8845 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8848 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8851 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8853 get_cached_class_info = func;
8857 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8859 if (!get_cached_class_info)
8862 return get_cached_class_info (klass, res);
8866 mono_install_get_class_from_name (MonoGetClassFromName func)
8868 get_class_from_name = func;
8872 * mono_class_get_image:
8874 * Use this method to get the `MonoImage*` where this class came from.
8876 * Returns: The image where this class is defined.
8879 mono_class_get_image (MonoClass *klass)
8881 return klass->image;
8885 * mono_class_get_element_class:
8886 * @klass: the MonoClass to act on
8888 * Use this function to get the element class of an array.
8890 * Returns: The element class of an array.
8893 mono_class_get_element_class (MonoClass *klass)
8895 return klass->element_class;
8899 * mono_class_is_valuetype:
8900 * @klass: the MonoClass to act on
8902 * Use this method to determine if the provided `MonoClass*` represents a value type,
8903 * or a reference type.
8905 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8908 mono_class_is_valuetype (MonoClass *klass)
8910 return klass->valuetype;
8914 * mono_class_is_enum:
8915 * @klass: the MonoClass to act on
8917 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8919 * Returns: TRUE if the MonoClass represents an enumeration.
8922 mono_class_is_enum (MonoClass *klass)
8924 return klass->enumtype;
8928 * mono_class_enum_basetype:
8929 * @klass: the MonoClass to act on
8931 * Use this function to get the underlying type for an enumeration value.
8933 * Returns: The underlying type representation for an enumeration.
8936 mono_class_enum_basetype (MonoClass *klass)
8938 if (klass->element_class == klass)
8939 /* SRE or broken types */
8942 return &klass->element_class->byval_arg;
8946 * mono_class_get_parent
8947 * @klass: the MonoClass to act on
8949 * Returns: The parent class for this class.
8952 mono_class_get_parent (MonoClass *klass)
8954 return klass->parent;
8958 * mono_class_get_nesting_type:
8959 * @klass: the MonoClass to act on
8961 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8963 * If the return is NULL, this indicates that this class is not nested.
8965 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8968 mono_class_get_nesting_type (MonoClass *klass)
8970 return klass->nested_in;
8974 * mono_class_get_rank:
8975 * @klass: the MonoClass to act on
8977 * Returns: The rank for the array (the number of dimensions).
8980 mono_class_get_rank (MonoClass *klass)
8986 * mono_class_get_flags:
8987 * @klass: the MonoClass to act on
8989 * The type flags from the TypeDef table from the metadata.
8990 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8993 * Returns: The flags from the TypeDef table.
8996 mono_class_get_flags (MonoClass *klass)
8998 return klass->flags;
9002 * mono_class_get_name
9003 * @klass: the MonoClass to act on
9005 * Returns: The name of the class.
9008 mono_class_get_name (MonoClass *klass)
9014 * mono_class_get_namespace:
9015 * @klass: the MonoClass to act on
9017 * Returns: The namespace of the class.
9020 mono_class_get_namespace (MonoClass *klass)
9022 return klass->name_space;
9026 * mono_class_get_type:
9027 * @klass: the MonoClass to act on
9029 * This method returns the internal Type representation for the class.
9031 * Returns: The MonoType from the class.
9034 mono_class_get_type (MonoClass *klass)
9036 return &klass->byval_arg;
9040 * mono_class_get_type_token:
9041 * @klass: the MonoClass to act on
9043 * This method returns type token for the class.
9045 * Returns: The type token for the class.
9048 mono_class_get_type_token (MonoClass *klass)
9050 return klass->type_token;
9054 * mono_class_get_byref_type:
9055 * @klass: the MonoClass to act on
9060 mono_class_get_byref_type (MonoClass *klass)
9062 return &klass->this_arg;
9066 * mono_class_num_fields:
9067 * @klass: the MonoClass to act on
9069 * Returns: The number of static and instance fields in the class.
9072 mono_class_num_fields (MonoClass *klass)
9074 return klass->field.count;
9078 * mono_class_num_methods:
9079 * @klass: the MonoClass to act on
9081 * Returns: The number of methods in the class.
9084 mono_class_num_methods (MonoClass *klass)
9086 return klass->method.count;
9090 * mono_class_num_properties
9091 * @klass: the MonoClass to act on
9093 * Returns: The number of properties in the class.
9096 mono_class_num_properties (MonoClass *klass)
9098 mono_class_setup_properties (klass);
9100 return klass->ext->property.count;
9104 * mono_class_num_events:
9105 * @klass: the MonoClass to act on
9107 * Returns: The number of events in the class.
9110 mono_class_num_events (MonoClass *klass)
9112 mono_class_setup_events (klass);
9114 return klass->ext->event.count;
9118 * mono_class_get_fields:
9119 * @klass: the MonoClass to act on
9121 * This routine is an iterator routine for retrieving the fields in a class.
9123 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9124 * iterate over all of the elements. When no more values are
9125 * available, the return value is NULL.
9127 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9130 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9132 MonoClassField* field;
9136 mono_class_setup_fields (klass);
9137 if (mono_class_has_failure (klass))
9139 /* start from the first */
9140 if (klass->field.count) {
9141 *iter = &klass->fields [0];
9142 return &klass->fields [0];
9148 field = (MonoClassField *)*iter;
9150 if (field < &klass->fields [klass->field.count]) {
9158 * mono_class_get_methods
9159 * @klass: the MonoClass to act on
9161 * This routine is an iterator routine for retrieving the fields in a class.
9163 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9164 * iterate over all of the elements. When no more values are
9165 * available, the return value is NULL.
9167 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9170 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9172 MonoMethod** method;
9176 mono_class_setup_methods (klass);
9179 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9180 * FIXME we should better report this error to the caller
9182 if (!klass->methods)
9184 /* start from the first */
9185 if (klass->method.count) {
9186 *iter = &klass->methods [0];
9187 return klass->methods [0];
9193 method = (MonoMethod **)*iter;
9195 if (method < &klass->methods [klass->method.count]) {
9203 * mono_class_get_virtual_methods:
9205 * Iterate over the virtual methods of KLASS.
9207 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9210 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9212 MonoMethod** method;
9215 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9217 mono_class_setup_methods (klass);
9219 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9220 * FIXME we should better report this error to the caller
9222 if (!klass->methods)
9224 /* start from the first */
9225 method = &klass->methods [0];
9227 method = (MonoMethod **)*iter;
9230 while (method < &klass->methods [klass->method.count]) {
9231 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9235 if (method < &klass->methods [klass->method.count]) {
9242 /* Search directly in metadata to avoid calling setup_methods () */
9243 MonoMethod *res = NULL;
9249 start_index = GPOINTER_TO_UINT (*iter);
9252 for (i = start_index; i < klass->method.count; ++i) {
9255 /* klass->method.first points into the methodptr table */
9256 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9258 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9262 if (i < klass->method.count) {
9264 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9265 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9267 /* Add 1 here so the if (*iter) check fails */
9268 *iter = GUINT_TO_POINTER (i + 1);
9277 * mono_class_get_properties:
9278 * @klass: the MonoClass to act on
9280 * This routine is an iterator routine for retrieving the properties in a class.
9282 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9283 * iterate over all of the elements. When no more values are
9284 * available, the return value is NULL.
9286 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9289 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9291 MonoProperty* property;
9295 mono_class_setup_properties (klass);
9296 /* start from the first */
9297 if (klass->ext->property.count) {
9298 *iter = &klass->ext->properties [0];
9299 return (MonoProperty *)*iter;
9305 property = (MonoProperty *)*iter;
9307 if (property < &klass->ext->properties [klass->ext->property.count]) {
9309 return (MonoProperty *)*iter;
9315 * mono_class_get_events:
9316 * @klass: the MonoClass to act on
9318 * This routine is an iterator routine for retrieving the properties in a class.
9320 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9321 * iterate over all of the elements. When no more values are
9322 * available, the return value is NULL.
9324 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9327 mono_class_get_events (MonoClass* klass, gpointer *iter)
9333 mono_class_setup_events (klass);
9334 /* start from the first */
9335 if (klass->ext->event.count) {
9336 *iter = &klass->ext->events [0];
9337 return (MonoEvent *)*iter;
9343 event = (MonoEvent *)*iter;
9345 if (event < &klass->ext->events [klass->ext->event.count]) {
9347 return (MonoEvent *)*iter;
9353 * mono_class_get_interfaces
9354 * @klass: the MonoClass to act on
9356 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9358 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9359 * iterate over all of the elements. When no more values are
9360 * available, the return value is NULL.
9362 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9365 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9373 mono_class_init (klass);
9374 if (!klass->interfaces_inited) {
9375 mono_class_setup_interfaces (klass, &error);
9376 if (!mono_error_ok (&error)) {
9377 mono_error_cleanup (&error);
9381 /* start from the first */
9382 if (klass->interface_count) {
9383 *iter = &klass->interfaces [0];
9384 return klass->interfaces [0];
9390 iface = (MonoClass **)*iter;
9392 if (iface < &klass->interfaces [klass->interface_count]) {
9400 setup_nested_types (MonoClass *klass)
9403 GList *classes, *nested_classes, *l;
9406 if (klass->nested_classes_inited)
9409 if (!klass->type_token)
9410 klass->nested_classes_inited = TRUE;
9412 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9416 guint32 cols [MONO_NESTED_CLASS_SIZE];
9417 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9418 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9419 if (!mono_error_ok (&error)) {
9420 /*FIXME don't swallow the error message*/
9421 mono_error_cleanup (&error);
9423 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9427 classes = g_list_prepend (classes, nclass);
9429 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9432 mono_class_alloc_ext (klass);
9434 nested_classes = NULL;
9435 for (l = classes; l; l = l->next)
9436 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9437 g_list_free (classes);
9439 mono_image_lock (klass->image);
9441 mono_memory_barrier ();
9442 if (!klass->nested_classes_inited) {
9443 klass->ext->nested_classes = nested_classes;
9444 mono_memory_barrier ();
9445 klass->nested_classes_inited = TRUE;
9448 mono_image_unlock (klass->image);
9452 * mono_class_get_nested_types
9453 * @klass: the MonoClass to act on
9455 * This routine is an iterator routine for retrieving the nested types of a class.
9456 * This works only if @klass is non-generic, or a generic type definition.
9458 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9459 * iterate over all of the elements. When no more values are
9460 * available, the return value is NULL.
9462 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9465 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9471 if (!klass->nested_classes_inited)
9472 setup_nested_types (klass);
9475 /* start from the first */
9476 if (klass->ext && klass->ext->nested_classes) {
9477 *iter = klass->ext->nested_classes;
9478 return (MonoClass *)klass->ext->nested_classes->data;
9480 /* no nested types */
9484 item = (GList *)*iter;
9488 return (MonoClass *)item->data;
9495 * mono_class_is_delegate
9496 * @klass: the MonoClass to act on
9498 * Returns: TRUE if the MonoClass represents a System.Delegate.
9501 mono_class_is_delegate (MonoClass *klass)
9503 return klass->delegate;
9507 * mono_class_implements_interface
9508 * @klass: The MonoClass to act on
9509 * @interface: The interface to check if @klass implements.
9511 * Returns: TRUE if @klass implements @interface.
9514 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9516 return mono_class_is_assignable_from (iface, klass);
9520 * mono_field_get_name:
9521 * @field: the MonoClassField to act on
9523 * Returns: The name of the field.
9526 mono_field_get_name (MonoClassField *field)
9532 * mono_field_get_type:
9533 * @field: the MonoClassField to act on
9535 * Returns: MonoType of the field.
9538 mono_field_get_type (MonoClassField *field)
9541 MonoType *type = mono_field_get_type_checked (field, &error);
9542 if (!mono_error_ok (&error)) {
9543 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9544 mono_error_cleanup (&error);
9551 * mono_field_get_type_checked:
9552 * @field: the MonoClassField to act on
9553 * @error: used to return any erro found while retrieving @field type
9555 * Returns: MonoType of the field.
9558 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9560 mono_error_init (error);
9562 mono_field_resolve_type (field, error);
9567 * mono_field_get_parent:
9568 * @field: the MonoClassField to act on
9570 * Returns: MonoClass where the field was defined.
9573 mono_field_get_parent (MonoClassField *field)
9575 return field->parent;
9579 * mono_field_get_flags;
9580 * @field: the MonoClassField to act on
9582 * The metadata flags for a field are encoded using the
9583 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9585 * Returns: The flags for the field.
9588 mono_field_get_flags (MonoClassField *field)
9591 return mono_field_resolve_flags (field);
9592 return field->type->attrs;
9596 * mono_field_get_offset:
9597 * @field: the MonoClassField to act on
9599 * Returns: The field offset.
9602 mono_field_get_offset (MonoClassField *field)
9604 return field->offset;
9608 mono_field_get_rva (MonoClassField *field)
9612 MonoClass *klass = field->parent;
9613 MonoFieldDefaultValue *field_def_values;
9615 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9617 if (!klass->ext || !klass->ext->field_def_values) {
9618 mono_class_alloc_ext (klass);
9620 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9622 mono_image_lock (klass->image);
9623 if (!klass->ext->field_def_values)
9624 klass->ext->field_def_values = field_def_values;
9625 mono_image_unlock (klass->image);
9628 field_index = mono_field_get_index (field);
9630 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9631 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9633 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9634 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9637 return klass->ext->field_def_values [field_index].data;
9641 * mono_field_get_data:
9642 * @field: the MonoClassField to act on
9644 * Returns: A pointer to the metadata constant value or to the field
9645 * data if it has an RVA flag.
9648 mono_field_get_data (MonoClassField *field)
9650 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9651 MonoTypeEnum def_type;
9653 return mono_class_get_field_default_value (field, &def_type);
9654 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9655 return mono_field_get_rva (field);
9662 * mono_property_get_name:
9663 * @prop: the MonoProperty to act on
9665 * Returns: The name of the property
9668 mono_property_get_name (MonoProperty *prop)
9674 * mono_property_get_set_method
9675 * @prop: the MonoProperty to act on.
9677 * Returns: The setter method of the property (A MonoMethod)
9680 mono_property_get_set_method (MonoProperty *prop)
9686 * mono_property_get_get_method
9687 * @prop: the MonoProperty to act on.
9689 * Returns: The setter method of the property (A MonoMethod)
9692 mono_property_get_get_method (MonoProperty *prop)
9698 * mono_property_get_parent:
9699 * @prop: the MonoProperty to act on.
9701 * Returns: The MonoClass where the property was defined.
9704 mono_property_get_parent (MonoProperty *prop)
9706 return prop->parent;
9710 * mono_property_get_flags:
9711 * @prop: the MonoProperty to act on.
9713 * The metadata flags for a property are encoded using the
9714 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9716 * Returns: The flags for the property.
9719 mono_property_get_flags (MonoProperty *prop)
9725 * mono_event_get_name:
9726 * @event: the MonoEvent to act on
9728 * Returns: The name of the event.
9731 mono_event_get_name (MonoEvent *event)
9737 * mono_event_get_add_method:
9738 * @event: The MonoEvent to act on.
9740 * Returns: The @add' method for the event (a MonoMethod).
9743 mono_event_get_add_method (MonoEvent *event)
9749 * mono_event_get_remove_method:
9750 * @event: The MonoEvent to act on.
9752 * Returns: The @remove method for the event (a MonoMethod).
9755 mono_event_get_remove_method (MonoEvent *event)
9757 return event->remove;
9761 * mono_event_get_raise_method:
9762 * @event: The MonoEvent to act on.
9764 * Returns: The @raise method for the event (a MonoMethod).
9767 mono_event_get_raise_method (MonoEvent *event)
9769 return event->raise;
9773 * mono_event_get_parent:
9774 * @event: the MonoEvent to act on.
9776 * Returns: The MonoClass where the event is defined.
9779 mono_event_get_parent (MonoEvent *event)
9781 return event->parent;
9785 * mono_event_get_flags
9786 * @event: the MonoEvent to act on.
9788 * The metadata flags for an event are encoded using the
9789 * EVENT_* constants. See the tabledefs.h file for details.
9791 * Returns: The flags for the event.
9794 mono_event_get_flags (MonoEvent *event)
9796 return event->attrs;
9800 * mono_class_get_method_from_name:
9801 * @klass: where to look for the method
9802 * @name: name of the method
9803 * @param_count: number of parameters. -1 for any number.
9805 * Obtains a MonoMethod with a given name and number of parameters.
9806 * It only works if there are no multiple signatures for any given method name.
9809 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9811 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9815 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9817 MonoMethod *res = NULL;
9820 /* Search directly in the metadata to avoid calling setup_methods () */
9821 for (i = 0; i < klass->method.count; ++i) {
9823 guint32 cols [MONO_METHOD_SIZE];
9825 MonoMethodSignature *sig;
9827 /* klass->method.first points into the methodptr table */
9828 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9830 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9831 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9833 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9836 if (param_count == -1) {
9840 sig = mono_method_signature_checked (method, &error);
9842 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9845 if (sig->param_count == param_count) {
9856 * mono_class_get_method_from_name_flags:
9857 * @klass: where to look for the method
9858 * @name_space: name of the method
9859 * @param_count: number of parameters. -1 for any number.
9860 * @flags: flags which must be set in the method
9862 * Obtains a MonoMethod with a given name and number of parameters.
9863 * It only works if there are no multiple signatures for any given method name.
9866 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9868 MonoMethod *res = NULL;
9871 mono_class_init (klass);
9873 if (klass->generic_class && !klass->methods) {
9874 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9877 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9878 if (!mono_error_ok (&error))
9879 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9884 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9885 mono_class_setup_methods (klass);
9887 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9888 See mono/tests/array_load_exception.il
9889 FIXME we should better report this error to the caller
9891 if (!klass->methods)
9893 for (i = 0; i < klass->method.count; ++i) {
9894 MonoMethod *method = klass->methods [i];
9896 if (method->name[0] == name [0] &&
9897 !strcmp (name, method->name) &&
9898 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9899 ((method->flags & flags) == flags)) {
9906 res = find_method_in_metadata (klass, name, param_count, flags);
9913 * mono_class_set_failure:
9914 * @klass: class in which the failure was detected
9915 * @ex_type: the kind of exception/error to be thrown (later)
9916 * @ex_data: exception data (specific to each type of exception/error)
9918 * Keep a detected failure informations in the class for later processing.
9919 * Note that only the first failure is kept.
9921 * LOCKING: Acquires the loader lock.
9924 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9926 g_assert (boxed_error != NULL);
9928 if (mono_class_has_failure (klass))
9931 mono_loader_lock ();
9932 klass->has_failure = 1;
9933 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9934 mono_loader_unlock ();
9940 mono_class_has_failure (const MonoClass *klass)
9942 g_assert (klass != NULL);
9943 return klass->has_failure != 0;
9948 * mono_class_set_type_load_failure:
9949 * @klass: class in which the failure was detected
9950 * @fmt: Printf-style error message string.
9952 * Collect detected failure informaion in the class for later processing.
9953 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9954 * Note that only the first failure is kept.
9956 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9958 * LOCKING: Acquires the loader lock.
9961 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9963 MonoError prepare_error;
9966 if (mono_class_has_failure (klass))
9969 mono_error_init (&prepare_error);
9971 va_start (args, fmt);
9972 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9975 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9976 mono_error_cleanup (&prepare_error);
9977 return mono_class_set_failure (klass, box);
9981 * mono_class_get_exception_data:
9983 * Return the exception_data property of KLASS.
9985 * LOCKING: Acquires the loader lock.
9988 mono_class_get_exception_data (const MonoClass *klass)
9990 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9994 * mono_classes_init:
9996 * Initialize the resources used by this module.
9999 mono_classes_init (void)
10001 mono_os_mutex_init (&classes_mutex);
10003 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10004 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10006 mono_counters_register ("Inflated methods size",
10007 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10008 mono_counters_register ("Inflated classes",
10009 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10010 mono_counters_register ("Inflated classes size",
10011 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10012 mono_counters_register ("MonoClass size",
10013 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10014 mono_counters_register ("MonoClassExt size",
10015 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10019 * mono_classes_cleanup:
10021 * Free the resources used by this module.
10024 mono_classes_cleanup (void)
10026 mono_native_tls_free (setup_fields_tls_id);
10027 mono_native_tls_free (init_pending_tls_id);
10029 if (global_interface_bitset)
10030 mono_bitset_free (global_interface_bitset);
10031 global_interface_bitset = NULL;
10032 mono_os_mutex_destroy (&classes_mutex);
10036 * mono_class_get_exception_for_failure:
10037 * @klass: class in which the failure was detected
10039 * Return a constructed MonoException than the caller can then throw
10040 * using mono_raise_exception - or NULL if no failure is present (or
10041 * doesn't result in an exception).
10044 mono_class_get_exception_for_failure (MonoClass *klass)
10046 if (!mono_class_has_failure (klass))
10048 MonoError unboxed_error;
10049 mono_error_init (&unboxed_error);
10050 mono_error_set_for_class_failure (&unboxed_error, klass);
10051 return mono_error_convert_to_exception (&unboxed_error);
10055 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10057 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10058 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10060 if (outer_klass == inner_klass)
10062 inner_klass = inner_klass->nested_in;
10063 } while (inner_klass);
10068 mono_class_get_generic_type_definition (MonoClass *klass)
10070 return klass->generic_class ? klass->generic_class->container_class : klass;
10074 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10076 * Generic instantiations are ignored for all super types of @klass.
10078 * Visibility checks ignoring generic instantiations.
10081 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10084 klass = mono_class_get_generic_type_definition (klass);
10085 parent = mono_class_get_generic_type_definition (parent);
10086 mono_class_setup_supertypes (klass);
10088 for (i = 0; i < klass->idepth; ++i) {
10089 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10095 * Subtype can only access parent members with family protection if the site object
10096 * is subclass of Subtype. For example:
10097 * class A { protected int x; }
10099 * void valid_access () {
10103 * void invalid_access () {
10110 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10112 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10115 if (context_klass == NULL)
10117 /*if access_klass is not member_klass context_klass must be type compat*/
10118 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10124 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10127 if (accessing == accessed)
10129 if (!accessed || !accessing)
10132 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10133 * anywhere so untrusted friends are not safe to access platform's code internals */
10134 if (mono_security_core_clr_enabled ()) {
10135 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10139 mono_assembly_load_friends (accessed);
10140 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10141 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10142 /* Be conservative with checks */
10143 if (!friend_->name)
10145 if (strcmp (accessing->aname.name, friend_->name))
10147 if (friend_->public_key_token [0]) {
10148 if (!accessing->aname.public_key_token [0])
10150 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10159 * If klass is a generic type or if it is derived from a generic type, return the
10160 * MonoClass of the generic definition
10161 * Returns NULL if not found
10164 get_generic_definition_class (MonoClass *klass)
10167 if (klass->generic_class && klass->generic_class->container_class)
10168 return klass->generic_class->container_class;
10169 klass = klass->parent;
10175 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10178 for (i = 0; i < ginst->type_argc; ++i) {
10179 MonoType *type = ginst->type_argv[i];
10180 switch (type->type) {
10181 case MONO_TYPE_SZARRAY:
10182 if (!can_access_type (access_klass, type->data.klass))
10185 case MONO_TYPE_ARRAY:
10186 if (!can_access_type (access_klass, type->data.array->eklass))
10189 case MONO_TYPE_PTR:
10190 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10193 case MONO_TYPE_CLASS:
10194 case MONO_TYPE_VALUETYPE:
10195 case MONO_TYPE_GENERICINST:
10196 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10206 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10210 if (access_klass == member_klass)
10213 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10216 if (access_klass->element_class && !access_klass->enumtype)
10217 access_klass = access_klass->element_class;
10219 if (member_klass->element_class && !member_klass->enumtype)
10220 member_klass = member_klass->element_class;
10222 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10224 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10227 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10230 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10233 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10236 /*Non nested type with nested visibility. We just fail it.*/
10237 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10240 switch (access_level) {
10241 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10242 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10244 case TYPE_ATTRIBUTE_PUBLIC:
10247 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10250 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10251 return is_nesting_type (member_klass, access_klass);
10253 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10254 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10256 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10257 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10259 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10260 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10261 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10263 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10264 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10265 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10270 /* FIXME: check visibility of type, too */
10272 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10274 MonoClass *member_generic_def;
10275 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10278 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10279 access_klass->generic_container) &&
10280 (member_generic_def = get_generic_definition_class (member_klass))) {
10281 MonoClass *access_container;
10283 if (access_klass->generic_container)
10284 access_container = access_klass;
10286 access_container = access_klass->generic_class->container_class;
10288 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10292 /* Partition I 8.5.3.2 */
10293 /* the access level values are the same for fields and methods */
10294 switch (access_level) {
10295 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10296 /* same compilation unit */
10297 return access_klass->image == member_klass->image;
10298 case FIELD_ATTRIBUTE_PRIVATE:
10299 return access_klass == member_klass;
10300 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10301 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10302 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10305 case FIELD_ATTRIBUTE_ASSEMBLY:
10306 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10307 case FIELD_ATTRIBUTE_FAMILY:
10308 if (is_valid_family_access (access_klass, member_klass, context_klass))
10311 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10312 if (is_valid_family_access (access_klass, member_klass, context_klass))
10314 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10315 case FIELD_ATTRIBUTE_PUBLIC:
10322 * mono_method_can_access_field:
10323 * @method: Method that will attempt to access the field
10324 * @field: the field to access
10326 * Used to determine if a method is allowed to access the specified field.
10328 * Returns: TRUE if the given @method is allowed to access the @field while following
10329 * the accessibility rules of the CLI.
10332 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10334 /* FIXME: check all overlapping fields */
10335 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10337 MonoClass *nested = method->klass->nested_in;
10339 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10342 nested = nested->nested_in;
10349 * mono_method_can_access_method:
10350 * @method: Method that will attempt to access the other method
10351 * @called: the method that we want to probe for accessibility.
10353 * Used to determine if the @method is allowed to access the specified @called method.
10355 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10356 * the accessibility rules of the CLI.
10359 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10361 method = mono_method_get_method_definition (method);
10362 called = mono_method_get_method_definition (called);
10363 return mono_method_can_access_method_full (method, called, NULL);
10367 * mono_method_can_access_method_full:
10368 * @method: The caller method
10369 * @called: The called method
10370 * @context_klass: The static type on stack of the owner @called object used
10372 * This function must be used with instance calls, as they have more strict family accessibility.
10373 * It can be used with static methods, but context_klass should be NULL.
10375 * Returns: TRUE if caller have proper visibility and acessibility to @called
10378 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10380 /* Wrappers are except from access checks */
10381 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10384 MonoClass *access_class = method->klass;
10385 MonoClass *member_class = called->klass;
10386 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10388 MonoClass *nested = access_class->nested_in;
10390 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10393 nested = nested->nested_in;
10400 can = can_access_type (access_class, member_class);
10402 MonoClass *nested = access_class->nested_in;
10404 can = can_access_type (nested, member_class);
10407 nested = nested->nested_in;
10414 if (called->is_inflated) {
10415 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10416 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10425 * mono_method_can_access_field_full:
10426 * @method: The caller method
10427 * @field: The accessed field
10428 * @context_klass: The static type on stack of the owner @field object used
10430 * This function must be used with instance fields, as they have more strict family accessibility.
10431 * It can be used with static fields, but context_klass should be NULL.
10433 * Returns: TRUE if caller have proper visibility and acessibility to @field
10436 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10438 MonoClass *access_class = method->klass;
10439 MonoClass *member_class = field->parent;
10440 /* FIXME: check all overlapping fields */
10441 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10443 MonoClass *nested = access_class->nested_in;
10445 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10448 nested = nested->nested_in;
10455 can = can_access_type (access_class, member_class);
10457 MonoClass *nested = access_class->nested_in;
10459 can = can_access_type (nested, member_class);
10462 nested = nested->nested_in;
10472 * mono_class_can_access_class:
10473 * @source_class: The source class
10474 * @target_class: The accessed class
10476 * This function returns is @target_class is visible to @source_class
10478 * Returns: TRUE if source have proper visibility and acessibility to target
10481 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10483 return can_access_type (source_class, target_class);
10487 * mono_type_is_valid_enum_basetype:
10488 * @type: The MonoType to check
10490 * Returns: TRUE if the type can be used as the basetype of an enum
10492 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10493 switch (type->type) {
10496 case MONO_TYPE_BOOLEAN:
10499 case MONO_TYPE_CHAR:
10513 * mono_class_is_valid_enum:
10514 * @klass: An enum class to be validated
10516 * This method verify the required properties an enum should have.
10518 * Returns: TRUE if the informed enum class is valid
10520 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10521 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10522 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10524 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10525 MonoClassField * field;
10526 gpointer iter = NULL;
10527 gboolean found_base_field = FALSE;
10529 g_assert (klass->enumtype);
10530 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10531 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10535 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10538 while ((field = mono_class_get_fields (klass, &iter))) {
10539 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10540 if (found_base_field)
10542 found_base_field = TRUE;
10543 if (!mono_type_is_valid_enum_basetype (field->type))
10548 if (!found_base_field)
10551 if (klass->method.count > 0)
10558 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10560 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10564 * mono_class_setup_interface_id:
10566 * Initializes MonoClass::interface_id if required.
10568 * LOCKING: Acquires the loader lock.
10571 mono_class_setup_interface_id (MonoClass *klass)
10573 mono_loader_lock ();
10574 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10575 klass->interface_id = mono_get_unique_iid (klass);
10576 mono_loader_unlock ();
10580 * mono_class_alloc_ext:
10582 * Allocate klass->ext if not already done.
10585 mono_class_alloc_ext (MonoClass *klass)
10592 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10593 mono_image_lock (klass->image);
10594 mono_memory_barrier ();
10597 class_ext_size += sizeof (MonoClassExt);
10598 mono_image_unlock (klass->image);
10602 * mono_class_setup_interfaces:
10604 * Initialize klass->interfaces/interfaces_count.
10605 * LOCKING: Acquires the loader lock.
10606 * This function can fail the type.
10609 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10611 int i, interface_count;
10612 MonoClass **interfaces;
10614 mono_error_init (error);
10616 if (klass->interfaces_inited)
10619 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10620 MonoType *args [1];
10622 /* generic IList, ICollection, IEnumerable */
10623 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10624 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10626 args [0] = &klass->element_class->byval_arg;
10627 interfaces [0] = mono_class_bind_generic_parameters (
10628 mono_defaults.generic_ilist_class, 1, args, FALSE);
10629 if (interface_count > 1)
10630 interfaces [1] = mono_class_bind_generic_parameters (
10631 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10632 } else if (klass->generic_class) {
10633 MonoClass *gklass = klass->generic_class->container_class;
10635 mono_class_setup_interfaces (gklass, error);
10636 if (!mono_error_ok (error)) {
10637 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10641 interface_count = gklass->interface_count;
10642 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10643 for (i = 0; i < interface_count; i++) {
10644 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10645 if (!mono_error_ok (error)) {
10646 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10651 interface_count = 0;
10655 mono_image_lock (klass->image);
10657 if (!klass->interfaces_inited) {
10658 klass->interface_count = interface_count;
10659 klass->interfaces = interfaces;
10661 mono_memory_barrier ();
10663 klass->interfaces_inited = TRUE;
10666 mono_image_unlock (klass->image);
10670 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10672 MonoClass *klass = field->parent;
10673 MonoImage *image = klass->image;
10674 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10675 int field_idx = field - klass->fields;
10677 mono_error_init (error);
10680 MonoClassField *gfield = >d->fields [field_idx];
10681 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10682 if (!mono_error_ok (error)) {
10683 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10686 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10687 if (!mono_error_ok (error)) {
10688 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10692 guint32 cols [MONO_FIELD_SIZE];
10693 MonoGenericContainer *container = NULL;
10694 int idx = klass->field.first + field_idx;
10696 /*FIXME, in theory we do not lazy load SRE fields*/
10697 g_assert (!image_is_dynamic (image));
10699 if (klass->generic_container) {
10700 container = klass->generic_container;
10702 container = gtd->generic_container;
10703 g_assert (container);
10706 /* klass->field.first and idx points into the fieldptr table */
10707 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10709 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10710 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10711 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10715 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10717 mono_metadata_decode_value (sig, &sig);
10718 /* FIELD signature == 0x06 */
10719 g_assert (*sig == 0x06);
10721 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10722 if (!field->type) {
10723 mono_class_set_type_load_failure (klass, "Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10729 mono_field_resolve_flags (MonoClassField *field)
10731 MonoClass *klass = field->parent;
10732 MonoImage *image = klass->image;
10733 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10734 int field_idx = field - klass->fields;
10738 MonoClassField *gfield = >d->fields [field_idx];
10739 return mono_field_get_flags (gfield);
10741 int idx = klass->field.first + field_idx;
10743 /*FIXME, in theory we do not lazy load SRE fields*/
10744 g_assert (!image_is_dynamic (image));
10746 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10751 * mono_class_get_fields_lazy:
10752 * @klass: the MonoClass to act on
10754 * This routine is an iterator routine for retrieving the fields in a class.
10755 * Only minimal information about fields are loaded. Accessors must be used
10756 * for all MonoClassField returned.
10758 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10759 * iterate over all of the elements. When no more values are
10760 * available, the return value is NULL.
10762 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10765 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10767 MonoClassField* field;
10771 mono_class_setup_basic_field_info (klass);
10772 if (!klass->fields)
10774 /* start from the first */
10775 if (klass->field.count) {
10776 *iter = &klass->fields [0];
10777 return (MonoClassField *)*iter;
10783 field = (MonoClassField *)*iter;
10785 if (field < &klass->fields [klass->field.count]) {
10787 return (MonoClassField *)*iter;
10793 mono_class_full_name (MonoClass *klass)
10795 return mono_type_full_name (&klass->byval_arg);
10798 /* Declare all shared lazy type lookup functions */
10799 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)