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->class_kind == MONO_CLASS_GTD);
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->class_kind == MONO_CLASS_GINST);
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 klass->class_kind = MONO_CLASS_DEF;
5785 if (klass->generic_container) {
5786 klass->class_kind = MONO_CLASS_GTD;
5787 klass->generic_container->owner.klass = klass;
5788 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5789 context = &klass->generic_container->context;
5792 if (klass->generic_container)
5793 enable_gclass_recording ();
5795 if (cols [MONO_TYPEDEF_EXTENDS]) {
5797 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5799 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5800 /*WARNING: this must satisfy mono_metadata_type_hash*/
5801 klass->this_arg.byref = 1;
5802 klass->this_arg.data.klass = klass;
5803 klass->this_arg.type = MONO_TYPE_CLASS;
5804 klass->byval_arg.data.klass = klass;
5805 klass->byval_arg.type = MONO_TYPE_CLASS;
5807 parent = mono_class_get_checked (image, parent_token, error);
5808 if (parent && context) /* Always inflate */
5809 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5811 if (parent == NULL) {
5812 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5813 goto parent_failure;
5816 for (tmp = parent; tmp; tmp = tmp->parent) {
5818 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5819 goto parent_failure;
5821 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5822 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5823 goto parent_failure;
5828 mono_class_setup_parent (klass, parent);
5830 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5831 mono_class_setup_mono_type (klass);
5833 if (klass->generic_container)
5834 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5837 * This might access klass->byval_arg for recursion generated by generic constraints,
5838 * so it has to come after setup_mono_type ().
5840 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5841 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5842 if (!mono_error_ok (error)) {
5843 /*FIXME implement a mono_class_set_failure_from_mono_error */
5844 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5845 mono_loader_unlock ();
5846 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5851 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5855 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5859 klass->cast_class = klass->element_class = klass;
5861 if (!klass->enumtype) {
5862 if (!mono_metadata_interfaces_from_typedef_full (
5863 image, type_token, &interfaces, &icount, FALSE, context, error)){
5865 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5866 mono_loader_unlock ();
5867 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5871 klass->interfaces = interfaces;
5872 klass->interface_count = icount;
5873 klass->interfaces_inited = 1;
5876 /*g_print ("Load class %s\n", name);*/
5879 * Compute the field and method lists
5881 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5882 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5884 if (tt->rows > tidx){
5885 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5886 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5887 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5889 field_last = image->tables [MONO_TABLE_FIELD].rows;
5890 method_last = image->tables [MONO_TABLE_METHOD].rows;
5893 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5894 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5895 klass->field.count = field_last - klass->field.first;
5897 klass->field.count = 0;
5899 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5900 klass->method.count = method_last - klass->method.first;
5902 klass->method.count = 0;
5904 /* reserve space to store vector pointer in arrays */
5905 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5906 klass->instance_size += 2 * sizeof (gpointer);
5907 g_assert (klass->field.count == 0);
5910 if (klass->enumtype) {
5911 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5912 if (!enum_basetype) {
5913 /*set it to a default value as the whole runtime can't handle this to be null*/
5914 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5915 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5916 mono_loader_unlock ();
5917 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5920 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5924 * If we're a generic type definition, load the constraints.
5925 * We must do this after the class has been constructed to make certain recursive scenarios
5928 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5929 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5930 mono_loader_unlock ();
5931 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5935 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5936 if (!strncmp (name, "Vector", 6))
5937 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");
5940 mono_loader_unlock ();
5942 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5947 mono_class_setup_mono_type (klass);
5948 mono_loader_unlock ();
5949 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5953 /** Is klass a Nullable<T> ginst? */
5955 mono_class_is_nullable (MonoClass *klass)
5957 return klass->generic_class != NULL &&
5958 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5962 /** if klass is T? return T */
5964 mono_class_get_nullable_param (MonoClass *klass)
5966 g_assert (mono_class_is_nullable (klass));
5967 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5971 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5975 MonoGenericClass *gclass = klass->generic_class;
5977 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5978 if (!mono_error_ok (&error)) {
5979 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5980 klass->parent = mono_defaults.object_class;
5981 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5982 mono_error_cleanup (&error);
5986 mono_class_setup_parent (klass, klass->parent);
5988 if (klass->enumtype) {
5989 klass->cast_class = gtd->cast_class;
5990 klass->element_class = gtd->element_class;
5996 * Create the `MonoClass' for an instantiation of a generic type.
5997 * We only do this if we actually need it.
6000 mono_generic_class_get_class (MonoGenericClass *gclass)
6002 MonoClass *klass, *gklass;
6004 if (gclass->cached_class)
6005 return gclass->cached_class;
6007 mono_loader_lock ();
6008 if (gclass->cached_class) {
6009 mono_loader_unlock ();
6010 return gclass->cached_class;
6013 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6015 gklass = gclass->container_class;
6017 if (record_gclass_instantiation > 0)
6018 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6020 if (gklass->nested_in) {
6021 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6022 klass->nested_in = gklass->nested_in;
6025 klass->name = gklass->name;
6026 klass->name_space = gklass->name_space;
6028 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6030 klass->image = gklass->image;
6031 klass->flags = gklass->flags;
6032 klass->type_token = gklass->type_token;
6033 klass->field.count = gklass->field.count;
6035 klass->class_kind = MONO_CLASS_GINST;
6036 klass->generic_class = gclass;
6038 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6039 klass->this_arg.type = klass->byval_arg.type;
6040 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6041 klass->this_arg.byref = TRUE;
6042 klass->enumtype = gklass->enumtype;
6043 klass->valuetype = gklass->valuetype;
6045 klass->cast_class = klass->element_class = klass;
6047 if (mono_class_is_nullable (klass))
6048 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6051 * We're not interested in the nested classes of a generic instance.
6052 * We use the generic type definition to look for nested classes.
6055 mono_generic_class_setup_parent (klass, gklass);
6057 if (gclass->is_dynamic) {
6059 * 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.
6060 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6061 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6063 if (!gklass->wastypebuilder)
6066 mono_class_setup_supertypes (klass);
6068 if (klass->enumtype) {
6070 * For enums, gklass->fields might not been set, but instance_size etc. is
6071 * already set in mono_reflection_create_internal_class (). For non-enums,
6072 * these will be computed normally in mono_class_layout_fields ().
6074 klass->instance_size = gklass->instance_size;
6075 klass->sizes.class_size = gklass->sizes.class_size;
6076 mono_memory_barrier ();
6077 klass->size_inited = 1;
6081 mono_memory_barrier ();
6082 gclass->cached_class = klass;
6084 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6086 inflated_classes ++;
6087 inflated_classes_size += sizeof (MonoClass);
6089 mono_loader_unlock ();
6095 get_image_for_container (MonoGenericContainer *container)
6098 if (container->is_anonymous) {
6099 result = container->owner.image;
6102 if (container->is_method) {
6103 MonoMethod *method = container->owner.method;
6104 g_assert_checked (method);
6105 klass = method->klass;
6107 klass = container->owner.klass;
6109 g_assert_checked (klass);
6110 result = klass->image;
6117 get_image_for_generic_param (MonoGenericParam *param)
6119 MonoGenericContainer *container = mono_generic_param_owner (param);
6120 g_assert_checked (container);
6121 return get_image_for_container (container);
6124 // Make a string in the designated image consisting of a single integer.
6125 #define INT_STRING_SIZE 16
6127 make_generic_name_string (MonoImage *image, int num)
6129 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6130 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6134 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6135 // pinfo is derived from param by the caller for us.
6137 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6139 MonoClass *klass, **ptr;
6141 MonoGenericContainer *container = mono_generic_param_owner (param);
6142 g_assert_checked (container);
6144 MonoImage *image = get_image_for_container (container);
6145 gboolean is_mvar = container->is_method;
6146 gboolean is_anonymous = container->is_anonymous;
6148 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6149 klass->class_kind = MONO_CLASS_GPARAM;
6150 classes_size += sizeof (MonoClass);
6153 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6155 int n = mono_generic_param_num (param);
6156 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6160 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6161 } else if (is_mvar) {
6162 MonoMethod *omethod = container->owner.method;
6163 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6165 MonoClass *oklass = container->owner.klass;
6166 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6169 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6171 // Count non-NULL items in pinfo->constraints
6174 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6178 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6179 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6181 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6182 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6184 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6187 if (count - pos > 0) {
6188 klass->interface_count = count - pos;
6189 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6190 klass->interfaces_inited = TRUE;
6191 for (i = pos; i < count; i++)
6192 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6195 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6197 klass->inited = TRUE;
6198 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6199 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6200 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6202 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6203 klass->this_arg.type = klass->byval_arg.type;
6204 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6205 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6206 klass->this_arg.byref = TRUE;
6208 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6209 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6211 /*Init these fields to sane values*/
6212 klass->min_align = 1;
6214 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6215 * constrained to, the JIT depends on this.
6217 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6218 mono_memory_barrier ();
6219 klass->size_inited = 1;
6221 mono_class_setup_supertypes (klass);
6223 if (count - pos > 0) {
6224 mono_class_setup_vtable (klass->parent);
6225 if (mono_class_has_failure (klass->parent))
6226 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6228 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6234 #define FAST_CACHE_SIZE 16
6237 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6238 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6239 * we cache the MonoClasses.
6240 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6241 * LOCKING: Takes the image lock depending on @take_lock.
6244 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6246 int n = mono_generic_param_num (param);
6247 MonoImage *image = get_image_for_generic_param (param);
6248 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6249 MonoClass *klass = NULL;
6254 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6255 // For high numbers or constraints we have to use pointer hashes.
6256 if (param->gshared_constraint) {
6257 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6260 mono_image_lock (image);
6261 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6263 mono_image_unlock (image);
6268 if (n < FAST_CACHE_SIZE) {
6270 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6272 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6274 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6277 mono_image_lock (image);
6278 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6280 mono_image_unlock (image);
6287 * LOCKING: Image lock (param->image) must be held
6290 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6292 int n = mono_generic_param_num (param);
6293 MonoImage *image = get_image_for_generic_param (param);
6294 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6298 if (param->gshared_constraint) {
6299 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6301 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6302 mono_memory_barrier ();
6304 image->mvar_cache_constrained = ht;
6306 image->var_cache_constrained = ht;
6308 g_hash_table_insert (ht, param, klass);
6309 } else if (n < FAST_CACHE_SIZE) {
6311 /* Requires locking to avoid droping an already published class */
6312 if (!image->mvar_cache_fast)
6313 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6314 image->mvar_cache_fast [n] = klass;
6316 if (!image->var_cache_fast)
6317 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6318 image->var_cache_fast [n] = klass;
6321 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6323 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6325 ht = g_hash_table_new (NULL, NULL);
6326 mono_memory_barrier ();
6328 image->mvar_cache_slow = ht;
6330 image->var_cache_slow = ht;
6333 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6338 * LOCKING: Acquires the image lock (@image).
6341 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6343 MonoImage *image = get_image_for_generic_param (param);
6344 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6345 MonoClass *klass, *klass2;
6347 // If a klass already exists for this object and is cached, return it.
6348 if (pinfo) // Non-anonymous
6349 klass = pinfo->pklass;
6351 klass = get_anon_gparam_class (param, TRUE);
6356 // Create a new klass
6357 klass = make_generic_param_class (param, pinfo);
6359 // Now we need to cache the klass we created.
6360 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6361 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6362 // and allow our newly-created klass object to just leak.
6363 mono_memory_barrier ();
6365 mono_image_lock (image);
6367 // Here "klass2" refers to the klass potentially created by the other thread.
6368 if (pinfo) // Repeat check from above
6369 klass2 = pinfo->pklass;
6371 klass2 = get_anon_gparam_class (param, FALSE);
6378 pinfo->pklass = klass;
6380 set_anon_gparam_class (param, klass);
6382 mono_image_unlock (image);
6384 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6386 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6388 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6394 * mono_class_from_generic_parameter:
6395 * @param: Parameter to find/construct a class for.
6396 * @arg2: Is ignored.
6397 * @arg3: Is ignored.
6400 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6402 return mono_class_from_generic_parameter_internal (param);
6407 mono_ptr_class_get (MonoType *type)
6410 MonoClass *el_class;
6414 el_class = mono_class_from_mono_type (type);
6415 image = el_class->image;
6417 mono_image_lock (image);
6418 if (image->ptr_cache) {
6419 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6420 mono_image_unlock (image);
6424 mono_image_unlock (image);
6426 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6428 classes_size += sizeof (MonoClass);
6430 result->parent = NULL; /* no parent for PTR types */
6431 result->name_space = el_class->name_space;
6432 name = g_strdup_printf ("%s*", el_class->name);
6433 result->name = mono_image_strdup (image, name);
6434 result->class_kind = MONO_CLASS_POINTER;
6437 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6439 result->image = el_class->image;
6440 result->inited = TRUE;
6441 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6442 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6443 result->cast_class = result->element_class = el_class;
6444 result->blittable = TRUE;
6446 result->byval_arg.type = MONO_TYPE_PTR;
6447 result->this_arg.type = result->byval_arg.type;
6448 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6449 result->this_arg.byref = TRUE;
6451 mono_class_setup_supertypes (result);
6453 mono_image_lock (image);
6454 if (image->ptr_cache) {
6456 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6457 mono_image_unlock (image);
6458 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6462 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6464 g_hash_table_insert (image->ptr_cache, el_class, result);
6465 mono_image_unlock (image);
6467 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6473 mono_fnptr_class_get (MonoMethodSignature *sig)
6476 static GHashTable *ptr_hash = NULL;
6478 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6480 mono_loader_lock ();
6483 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6485 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6486 mono_loader_unlock ();
6489 result = g_new0 (MonoClass, 1);
6491 result->parent = NULL; /* no parent for PTR types */
6492 result->name_space = "System";
6493 result->name = "MonoFNPtrFakeClass";
6494 result->class_kind = MONO_CLASS_POINTER;
6496 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6498 result->image = mono_defaults.corlib; /* need to fix... */
6499 result->inited = TRUE;
6500 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6501 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6502 result->cast_class = result->element_class = result;
6503 result->blittable = TRUE;
6505 result->byval_arg.type = MONO_TYPE_FNPTR;
6506 result->this_arg.type = result->byval_arg.type;
6507 result->this_arg.data.method = result->byval_arg.data.method = sig;
6508 result->this_arg.byref = TRUE;
6509 result->blittable = TRUE;
6511 mono_class_setup_supertypes (result);
6513 g_hash_table_insert (ptr_hash, sig, result);
6515 mono_loader_unlock ();
6517 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6523 * mono_class_from_mono_type:
6524 * @type: describes the type to return
6526 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6529 mono_class_from_mono_type (MonoType *type)
6531 switch (type->type) {
6532 case MONO_TYPE_OBJECT:
6533 return type->data.klass? type->data.klass: mono_defaults.object_class;
6534 case MONO_TYPE_VOID:
6535 return type->data.klass? type->data.klass: mono_defaults.void_class;
6536 case MONO_TYPE_BOOLEAN:
6537 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6538 case MONO_TYPE_CHAR:
6539 return type->data.klass? type->data.klass: mono_defaults.char_class;
6541 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6543 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6545 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6547 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6549 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6551 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6553 return type->data.klass? type->data.klass: mono_defaults.int_class;
6555 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6557 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6559 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6561 return type->data.klass? type->data.klass: mono_defaults.single_class;
6563 return type->data.klass? type->data.klass: mono_defaults.double_class;
6564 case MONO_TYPE_STRING:
6565 return type->data.klass? type->data.klass: mono_defaults.string_class;
6566 case MONO_TYPE_TYPEDBYREF:
6567 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6568 case MONO_TYPE_ARRAY:
6569 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6571 return mono_ptr_class_get (type->data.type);
6572 case MONO_TYPE_FNPTR:
6573 return mono_fnptr_class_get (type->data.method);
6574 case MONO_TYPE_SZARRAY:
6575 return mono_array_class_get (type->data.klass, 1);
6576 case MONO_TYPE_CLASS:
6577 case MONO_TYPE_VALUETYPE:
6578 return type->data.klass;
6579 case MONO_TYPE_GENERICINST:
6580 return mono_generic_class_get_class (type->data.generic_class);
6581 case MONO_TYPE_MVAR:
6583 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6585 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6586 g_assert_not_reached ();
6589 // Yes, this returns NULL, even if it is documented as not doing so, but there
6590 // is no way for the code to make it this far, due to the assert above.
6595 * mono_type_retrieve_from_typespec
6596 * @image: context where the image is created
6597 * @type_spec: typespec token
6598 * @context: the generic context used to evaluate generic instantiations in
6601 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6603 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6605 *did_inflate = FALSE;
6610 if (context && (context->class_inst || context->method_inst)) {
6611 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6613 if (!mono_error_ok (error)) {
6619 *did_inflate = TRUE;
6626 * mono_class_create_from_typespec
6627 * @image: context where the image is created
6628 * @type_spec: typespec token
6629 * @context: the generic context used to evaluate generic instantiations in
6632 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6635 gboolean inflated = FALSE;
6636 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6637 return_val_if_nok (error, NULL);
6638 ret = mono_class_from_mono_type (t);
6640 mono_metadata_free_type (t);
6645 * mono_bounded_array_class_get:
6646 * @element_class: element class
6647 * @rank: the dimension of the array class
6648 * @bounded: whenever the array has non-zero bounds
6650 * Returns: A class object describing the array with element type @element_type and
6654 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6658 MonoClass *parent = NULL;
6659 GSList *list, *rootlist = NULL;
6663 g_assert (rank <= 255);
6666 /* bounded only matters for one-dimensional arrays */
6669 image = eclass->image;
6671 if (rank == 1 && !bounded) {
6673 * This case is very frequent not just during compilation because of calls
6674 * from mono_class_from_mono_type (), mono_array_new (),
6675 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6677 mono_os_mutex_lock (&image->szarray_cache_lock);
6678 if (!image->szarray_cache)
6679 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6680 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6681 mono_os_mutex_unlock (&image->szarray_cache_lock);
6685 mono_loader_lock ();
6687 mono_loader_lock ();
6689 if (!image->array_cache)
6690 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6692 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6693 for (; list; list = list->next) {
6694 klass = (MonoClass *)list->data;
6695 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6696 mono_loader_unlock ();
6703 parent = mono_defaults.array_class;
6704 if (!parent->inited)
6705 mono_class_init (parent);
6707 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6709 klass->image = image;
6710 klass->name_space = eclass->name_space;
6711 klass->class_kind = MONO_CLASS_ARRAY;
6713 nsize = strlen (eclass->name);
6714 name = (char *)g_malloc (nsize + 2 + rank + 1);
6715 memcpy (name, eclass->name, nsize);
6718 memset (name + nsize + 1, ',', rank - 1);
6720 name [nsize + rank] = '*';
6721 name [nsize + rank + bounded] = ']';
6722 name [nsize + rank + bounded + 1] = 0;
6723 klass->name = mono_image_strdup (image, name);
6726 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6728 classes_size += sizeof (MonoClass);
6730 klass->type_token = 0;
6731 /* all arrays are marked serializable and sealed, bug #42779 */
6732 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6733 klass->parent = parent;
6734 klass->instance_size = mono_class_instance_size (klass->parent);
6736 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6737 /*Arrays of those two types are invalid.*/
6738 MonoError prepared_error;
6739 mono_error_init (&prepared_error);
6740 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6741 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6742 mono_error_cleanup (&prepared_error);
6743 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6744 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6745 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6746 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6748 /* element_size -1 is ok as this is not an instantitable type*/
6749 klass->sizes.element_size = -1;
6751 klass->sizes.element_size = mono_class_array_element_size (eclass);
6753 mono_class_setup_supertypes (klass);
6755 if (eclass->generic_class)
6756 mono_class_init (eclass);
6757 mono_class_init_sizes (eclass);
6758 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6759 /*FIXME we fail the array type, but we have to let other fields be set.*/
6761 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6765 if (eclass->enumtype)
6766 klass->cast_class = eclass->element_class;
6768 klass->cast_class = eclass;
6770 switch (klass->cast_class->byval_arg.type) {
6772 klass->cast_class = mono_defaults.byte_class;
6775 klass->cast_class = mono_defaults.int16_class;
6778 #if SIZEOF_VOID_P == 4
6782 klass->cast_class = mono_defaults.int32_class;
6785 #if SIZEOF_VOID_P == 8
6789 klass->cast_class = mono_defaults.int64_class;
6795 klass->element_class = eclass;
6797 if ((rank > 1) || bounded) {
6798 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6799 klass->byval_arg.type = MONO_TYPE_ARRAY;
6800 klass->byval_arg.data.array = at;
6801 at->eklass = eclass;
6803 /* FIXME: complete.... */
6805 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6806 klass->byval_arg.data.klass = eclass;
6808 klass->this_arg = klass->byval_arg;
6809 klass->this_arg.byref = 1;
6811 klass->generic_container = eclass->generic_container;
6813 if (rank == 1 && !bounded) {
6814 MonoClass *prev_class;
6816 mono_os_mutex_lock (&image->szarray_cache_lock);
6817 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6819 /* Someone got in before us */
6822 g_hash_table_insert (image->szarray_cache, eclass, klass);
6823 mono_os_mutex_unlock (&image->szarray_cache_lock);
6825 list = g_slist_append (rootlist, klass);
6826 g_hash_table_insert (image->array_cache, eclass, list);
6829 mono_loader_unlock ();
6831 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6837 * mono_array_class_get:
6838 * @element_class: element class
6839 * @rank: the dimension of the array class
6841 * Returns: A class object describing the array with element type @element_type and
6845 mono_array_class_get (MonoClass *eclass, guint32 rank)
6847 return mono_bounded_array_class_get (eclass, rank, FALSE);
6851 * mono_class_instance_size:
6854 * Use to get the size of a class in bytes.
6856 * Returns: The size of an object instance
6859 mono_class_instance_size (MonoClass *klass)
6861 if (!klass->size_inited)
6862 mono_class_init_sizes (klass);
6864 return klass->instance_size;
6868 * mono_class_min_align:
6871 * Use to get the computed minimum alignment requirements for the specified class.
6873 * Returns: minimum alignment requirements
6876 mono_class_min_align (MonoClass *klass)
6878 if (!klass->size_inited)
6879 mono_class_init_sizes (klass);
6881 return klass->min_align;
6885 * mono_class_value_size:
6888 * This function is used for value types, and return the
6889 * space and the alignment to store that kind of value object.
6891 * Returns: the size of a value of kind @klass
6894 mono_class_value_size (MonoClass *klass, guint32 *align)
6898 /* fixme: check disable, because we still have external revereces to
6899 * mscorlib and Dummy Objects
6901 /*g_assert (klass->valuetype);*/
6903 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6906 *align = klass->min_align;
6912 * mono_class_data_size:
6915 * Returns: The size of the static class data
6918 mono_class_data_size (MonoClass *klass)
6921 mono_class_init (klass);
6922 /* This can happen with dynamically created types */
6923 if (!klass->size_inited)
6924 mono_class_init_sizes (klass);
6926 /* in arrays, sizes.class_size is unioned with element_size
6927 * and arrays have no static fields
6931 return klass->sizes.class_size;
6935 * Auxiliary routine to mono_class_get_field
6937 * Takes a field index instead of a field token.
6939 static MonoClassField *
6940 mono_class_get_field_idx (MonoClass *klass, int idx)
6942 mono_class_setup_fields (klass);
6943 if (mono_class_has_failure (klass))
6947 if (klass->image->uncompressed_metadata) {
6949 * klass->field.first points to the FieldPtr table, while idx points into the
6950 * Field table, so we have to do a search.
6952 /*FIXME this is broken for types with multiple fields with the same name.*/
6953 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6956 for (i = 0; i < klass->field.count; ++i)
6957 if (mono_field_get_name (&klass->fields [i]) == name)
6958 return &klass->fields [i];
6959 g_assert_not_reached ();
6961 if (klass->field.count) {
6962 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6963 return &klass->fields [idx - klass->field.first];
6967 klass = klass->parent;
6973 * mono_class_get_field:
6974 * @class: the class to lookup the field.
6975 * @field_token: the field token
6977 * Returns: A MonoClassField representing the type and offset of
6978 * the field, or a NULL value if the field does not belong to this
6982 mono_class_get_field (MonoClass *klass, guint32 field_token)
6984 int idx = mono_metadata_token_index (field_token);
6986 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6988 return mono_class_get_field_idx (klass, idx - 1);
6992 * mono_class_get_field_from_name:
6993 * @klass: the class to lookup the field.
6994 * @name: the field name
6996 * Search the class @klass and it's parents for a field with the name @name.
6998 * Returns: The MonoClassField pointer of the named field or NULL
7001 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7003 return mono_class_get_field_from_name_full (klass, name, NULL);
7007 * mono_class_get_field_from_name_full:
7008 * @klass: the class to lookup the field.
7009 * @name: the field name
7010 * @type: the type of the fields. This optional.
7012 * Search the class @klass and it's parents for a field with the name @name and type @type.
7014 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7015 * of its generic type definition.
7017 * Returns: The MonoClassField pointer of the named field or NULL
7020 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7024 mono_class_setup_fields (klass);
7025 if (mono_class_has_failure (klass))
7029 for (i = 0; i < klass->field.count; ++i) {
7030 MonoClassField *field = &klass->fields [i];
7032 if (strcmp (name, mono_field_get_name (field)) != 0)
7036 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7037 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7042 klass = klass->parent;
7048 * mono_class_get_field_token:
7049 * @field: the field we need the token of
7051 * Get the token of a field. Note that the tokesn is only valid for the image
7052 * the field was loaded from. Don't use this function for fields in dynamic types.
7054 * Returns: The token representing the field in the image it was loaded from.
7057 mono_class_get_field_token (MonoClassField *field)
7059 MonoClass *klass = field->parent;
7062 mono_class_setup_fields (klass);
7067 for (i = 0; i < klass->field.count; ++i) {
7068 if (&klass->fields [i] == field) {
7069 int idx = klass->field.first + i + 1;
7071 if (klass->image->uncompressed_metadata)
7072 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7073 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7076 klass = klass->parent;
7079 g_assert_not_reached ();
7084 mono_field_get_index (MonoClassField *field)
7086 int index = field - field->parent->fields;
7088 g_assert (index >= 0 && index < field->parent->field.count);
7094 * mono_class_get_field_default_value:
7096 * Return the default value of the field as a pointer into the metadata blob.
7099 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7102 guint32 constant_cols [MONO_CONSTANT_SIZE];
7104 MonoClass *klass = field->parent;
7106 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7108 if (!klass->ext || !klass->ext->field_def_values) {
7109 MonoFieldDefaultValue *def_values;
7111 mono_class_alloc_ext (klass);
7113 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7115 mono_image_lock (klass->image);
7116 mono_memory_barrier ();
7117 if (!klass->ext->field_def_values)
7118 klass->ext->field_def_values = def_values;
7119 mono_image_unlock (klass->image);
7122 field_index = mono_field_get_index (field);
7124 if (!klass->ext->field_def_values [field_index].data) {
7125 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7129 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7131 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7132 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7133 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7136 *def_type = klass->ext->field_def_values [field_index].def_type;
7137 return klass->ext->field_def_values [field_index].data;
7141 mono_property_get_index (MonoProperty *prop)
7143 int index = prop - prop->parent->ext->properties;
7145 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7151 * mono_class_get_property_default_value:
7153 * Return the default value of the field as a pointer into the metadata blob.
7156 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7159 guint32 constant_cols [MONO_CONSTANT_SIZE];
7160 MonoClass *klass = property->parent;
7162 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7164 * We don't cache here because it is not used by C# so it's quite rare, but
7165 * we still do the lookup in klass->ext because that is where the data
7166 * is stored for dynamic assemblies.
7169 if (image_is_dynamic (klass->image)) {
7170 int prop_index = mono_property_get_index (property);
7171 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7172 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7173 return klass->ext->prop_def_values [prop_index].data;
7177 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7181 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7182 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7183 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7187 mono_class_get_event_token (MonoEvent *event)
7189 MonoClass *klass = event->parent;
7194 for (i = 0; i < klass->ext->event.count; ++i) {
7195 if (&klass->ext->events [i] == event)
7196 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7199 klass = klass->parent;
7202 g_assert_not_reached ();
7207 * mono_class_get_property_from_name:
7209 * @name: name of the property to lookup in the specified class
7211 * Use this method to lookup a property in a class
7212 * Returns: the MonoProperty with the given name, or NULL if the property
7213 * does not exist on the @klass.
7216 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7220 gpointer iter = NULL;
7221 while ((p = mono_class_get_properties (klass, &iter))) {
7222 if (! strcmp (name, p->name))
7225 klass = klass->parent;
7231 * mono_class_get_property_token:
7232 * @prop: MonoProperty to query
7234 * Returns: The ECMA token for the specified property.
7237 mono_class_get_property_token (MonoProperty *prop)
7239 MonoClass *klass = prop->parent;
7243 gpointer iter = NULL;
7244 while ((p = mono_class_get_properties (klass, &iter))) {
7245 if (&klass->ext->properties [i] == prop)
7246 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7250 klass = klass->parent;
7253 g_assert_not_reached ();
7258 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7260 const char *name, *nspace;
7261 if (image_is_dynamic (image))
7262 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7264 switch (type_token & 0xff000000){
7265 case MONO_TOKEN_TYPE_DEF: {
7266 guint32 cols [MONO_TYPEDEF_SIZE];
7267 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7268 guint tidx = mono_metadata_token_index (type_token);
7270 if (tidx > tt->rows)
7271 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7273 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7274 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7275 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7276 if (strlen (nspace) == 0)
7277 return g_strdup_printf ("%s", name);
7279 return g_strdup_printf ("%s.%s", nspace, name);
7282 case MONO_TOKEN_TYPE_REF: {
7284 guint32 cols [MONO_TYPEREF_SIZE];
7285 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7286 guint tidx = mono_metadata_token_index (type_token);
7289 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7291 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7292 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7293 mono_error_cleanup (&error);
7297 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7298 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7299 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7300 if (strlen (nspace) == 0)
7301 return g_strdup_printf ("%s", name);
7303 return g_strdup_printf ("%s.%s", nspace, name);
7306 case MONO_TOKEN_TYPE_SPEC:
7307 return g_strdup_printf ("Typespec 0x%08x", type_token);
7309 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7314 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7316 if (image_is_dynamic (image))
7317 return g_strdup_printf ("DynamicAssembly %s", image->name);
7319 switch (type_token & 0xff000000){
7320 case MONO_TOKEN_TYPE_DEF:
7321 if (image->assembly)
7322 return mono_stringify_assembly_name (&image->assembly->aname);
7323 else if (image->assembly_name)
7324 return g_strdup (image->assembly_name);
7325 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7326 case MONO_TOKEN_TYPE_REF: {
7328 MonoAssemblyName aname;
7329 guint32 cols [MONO_TYPEREF_SIZE];
7330 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7331 guint32 idx = mono_metadata_token_index (type_token);
7334 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7336 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7337 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7338 mono_error_cleanup (&error);
7341 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7343 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7344 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7345 case MONO_RESOLUTION_SCOPE_MODULE:
7347 return g_strdup ("");
7348 case MONO_RESOLUTION_SCOPE_MODULEREF:
7350 return g_strdup ("");
7351 case MONO_RESOLUTION_SCOPE_TYPEREF:
7353 return g_strdup ("");
7354 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7355 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7356 return mono_stringify_assembly_name (&aname);
7358 g_assert_not_reached ();
7362 case MONO_TOKEN_TYPE_SPEC:
7364 return g_strdup ("");
7366 g_assert_not_reached ();
7373 * mono_class_get_full:
7374 * @image: the image where the class resides
7375 * @type_token: the token for the class
7376 * @context: the generic context used to evaluate generic instantiations in
7377 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7379 * Returns: The MonoClass that represents @type_token in @image
7382 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7386 klass = mono_class_get_checked (image, type_token, &error);
7388 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7389 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7391 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7397 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7401 mono_error_init (error);
7402 klass = mono_class_get_checked (image, type_token, error);
7404 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7405 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7410 * mono_class_get_checked:
7411 * @image: the image where the class resides
7412 * @type_token: the token for the class
7413 * @error: error object to return any error
7415 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7418 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7420 MonoClass *klass = NULL;
7422 mono_error_init (error);
7424 if (image_is_dynamic (image)) {
7425 int table = mono_metadata_token_table (type_token);
7427 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7428 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7431 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7435 switch (type_token & 0xff000000){
7436 case MONO_TOKEN_TYPE_DEF:
7437 klass = mono_class_create_from_typedef (image, type_token, error);
7439 case MONO_TOKEN_TYPE_REF:
7440 klass = mono_class_from_typeref_checked (image, type_token, error);
7442 case MONO_TOKEN_TYPE_SPEC:
7443 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7446 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7450 /* Generic case, should be avoided for when a better error is possible. */
7451 if (!klass && mono_error_ok (error)) {
7452 char *name = mono_class_name_from_token (image, type_token);
7453 char *assembly = mono_assembly_name_from_token (image, type_token);
7454 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7462 * mono_type_get_checked:
7463 * @image: the image where the type resides
7464 * @type_token: the token for the type
7465 * @context: the generic context used to evaluate generic instantiations in
7466 * @error: Error handling context
7468 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7470 * Returns: The MonoType that represents @type_token in @image
7473 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7475 MonoType *type = NULL;
7476 gboolean inflated = FALSE;
7478 mono_error_init (error);
7480 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7481 if (image_is_dynamic (image)) {
7482 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7483 return_val_if_nok (error, NULL);
7484 return mono_class_get_type (klass);
7487 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7488 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7495 return mono_class_get_type (klass);
7498 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7505 MonoType *tmp = type;
7506 type = mono_class_get_type (mono_class_from_mono_type (type));
7507 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7508 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7509 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7511 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7513 if (type->type != tmp->type)
7516 mono_metadata_free_type (tmp);
7523 * @image: image where the class token will be looked up.
7524 * @type_token: a type token from the image
7526 * Returns the MonoClass with the given @type_token on the @image
7529 mono_class_get (MonoImage *image, guint32 type_token)
7531 return mono_class_get_full (image, type_token, NULL);
7535 * mono_image_init_name_cache:
7537 * Initializes the class name cache stored in image->name_cache.
7539 * LOCKING: Acquires the corresponding image lock.
7542 mono_image_init_name_cache (MonoImage *image)
7544 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7545 guint32 cols [MONO_TYPEDEF_SIZE];
7548 guint32 i, visib, nspace_index;
7549 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7551 if (image->name_cache)
7554 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7556 if (image_is_dynamic (image)) {
7557 mono_image_lock (image);
7558 if (image->name_cache) {
7559 /* Somebody initialized it before us */
7560 g_hash_table_destroy (the_name_cache);
7562 mono_atomic_store_release (&image->name_cache, the_name_cache);
7564 mono_image_unlock (image);
7568 /* Temporary hash table to avoid lookups in the nspace_table */
7569 name_cache2 = g_hash_table_new (NULL, NULL);
7571 for (i = 1; i <= t->rows; ++i) {
7572 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7573 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7575 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7576 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7578 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7580 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7581 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7583 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7584 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7585 if (!nspace_table) {
7586 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7587 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7588 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7591 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7594 /* Load type names from EXPORTEDTYPES table */
7596 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7597 guint32 cols [MONO_EXP_TYPE_SIZE];
7600 for (i = 0; i < t->rows; ++i) {
7601 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7603 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7604 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7608 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7609 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7611 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7612 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7613 if (!nspace_table) {
7614 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7615 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7616 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7619 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7623 g_hash_table_destroy (name_cache2);
7625 mono_image_lock (image);
7626 if (image->name_cache) {
7627 /* Somebody initialized it before us */
7628 g_hash_table_destroy (the_name_cache);
7630 mono_atomic_store_release (&image->name_cache, the_name_cache);
7632 mono_image_unlock (image);
7635 /*FIXME Only dynamic assemblies should allow this operation.*/
7637 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7638 const char *name, guint32 index)
7640 GHashTable *nspace_table;
7641 GHashTable *name_cache;
7644 mono_image_init_name_cache (image);
7645 mono_image_lock (image);
7647 name_cache = image->name_cache;
7648 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7649 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7650 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7653 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7654 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7656 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7658 mono_image_unlock (image);
7667 find_nocase (gpointer key, gpointer value, gpointer user_data)
7669 char *name = (char*)key;
7670 FindUserData *data = (FindUserData*)user_data;
7672 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7673 data->value = value;
7677 * mono_class_from_name_case:
7678 * @image: The MonoImage where the type is looked up in
7679 * @name_space: the type namespace
7680 * @name: the type short name.
7681 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7683 * Obtains a MonoClass with a given namespace and a given name which
7684 * is located in the given MonoImage. The namespace and name
7685 * lookups are case insensitive.
7688 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7691 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7692 mono_error_cleanup (&error);
7698 * mono_class_from_name_case:
7699 * @image: The MonoImage where the type is looked up in
7700 * @name_space: the type namespace
7701 * @name: the type short name.
7704 * Obtains a MonoClass with a given namespace and a given name which
7705 * is located in the given MonoImage. The namespace and name
7706 * lookups are case insensitive.
7708 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7709 * was not found. The @error object will contain information about the problem
7713 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7715 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7716 guint32 cols [MONO_TYPEDEF_SIZE];
7721 mono_error_init (error);
7723 if (image_is_dynamic (image)) {
7725 FindUserData user_data;
7727 mono_image_init_name_cache (image);
7728 mono_image_lock (image);
7730 user_data.key = name_space;
7731 user_data.value = NULL;
7732 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7734 if (user_data.value) {
7735 GHashTable *nspace_table = (GHashTable*)user_data.value;
7737 user_data.key = name;
7738 user_data.value = NULL;
7740 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7742 if (user_data.value)
7743 token = GPOINTER_TO_UINT (user_data.value);
7746 mono_image_unlock (image);
7749 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7755 /* add a cache if needed */
7756 for (i = 1; i <= t->rows; ++i) {
7757 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7758 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7760 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7761 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7763 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7765 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7766 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7767 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7768 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7774 return_nested_in (MonoClass *klass, char *nested)
7777 char *s = strchr (nested, '/');
7778 gpointer iter = NULL;
7785 while ((found = mono_class_get_nested_types (klass, &iter))) {
7786 if (strcmp (found->name, nested) == 0) {
7788 return return_nested_in (found, s);
7796 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7798 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7799 MonoImage *file_image;
7803 mono_error_init (error);
7806 * The EXPORTEDTYPES table only contains public types, so have to search the
7808 * Note: image->modules contains the contents of the MODULEREF table, while
7809 * the real module list is in the FILE table.
7811 for (i = 0; i < file_table->rows; i++) {
7812 guint32 cols [MONO_FILE_SIZE];
7813 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7814 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7817 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7819 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7820 if (klass || !is_ok (error))
7829 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7831 GHashTable *nspace_table;
7832 MonoImage *loaded_image;
7839 mono_error_init (error);
7841 // Checking visited images avoids stack overflows when cyclic references exist.
7842 if (g_hash_table_lookup (visited_images, image))
7845 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7847 if ((nested = strchr (name, '/'))) {
7848 int pos = nested - name;
7849 int len = strlen (name);
7852 memcpy (buf, name, len + 1);
7854 nested = buf + pos + 1;
7858 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7859 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7860 gboolean res = get_class_from_name (image, name_space, name, &klass);
7863 klass = search_modules (image, name_space, name, error);
7868 return klass ? return_nested_in (klass, nested) : NULL;
7874 mono_image_init_name_cache (image);
7875 mono_image_lock (image);
7877 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7880 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7882 mono_image_unlock (image);
7884 if (!token && image_is_dynamic (image) && image->modules) {
7885 /* Search modules as well */
7886 for (i = 0; i < image->module_count; ++i) {
7887 MonoImage *module = image->modules [i];
7889 klass = mono_class_from_name_checked (module, name_space, name, error);
7890 if (klass || !is_ok (error))
7896 klass = search_modules (image, name_space, name, error);
7897 if (klass || !is_ok (error))
7902 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7903 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7904 guint32 cols [MONO_EXP_TYPE_SIZE];
7907 idx = mono_metadata_token_index (token);
7909 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7911 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7912 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7913 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7916 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7918 return klass ? return_nested_in (klass, nested) : NULL;
7920 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7921 guint32 assembly_idx;
7923 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7925 mono_assembly_load_reference (image, assembly_idx - 1);
7926 g_assert (image->references [assembly_idx - 1]);
7927 if (image->references [assembly_idx - 1] == (gpointer)-1)
7929 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7931 return klass ? return_nested_in (klass, nested) : NULL;
7934 g_assert_not_reached ();
7938 token = MONO_TOKEN_TYPE_DEF | token;
7940 klass = mono_class_get_checked (image, token, error);
7942 return return_nested_in (klass, nested);
7947 * mono_class_from_name_checked:
7948 * @image: The MonoImage where the type is looked up in
7949 * @name_space: the type namespace
7950 * @name: the type short name.
7952 * Obtains a MonoClass with a given namespace and a given name which
7953 * is located in the given MonoImage.
7955 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7956 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7959 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7962 GHashTable *visited_images;
7964 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7966 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7968 g_hash_table_destroy (visited_images);
7974 * mono_class_from_name:
7975 * @image: The MonoImage where the type is looked up in
7976 * @name_space: the type namespace
7977 * @name: the type short name.
7979 * Obtains a MonoClass with a given namespace and a given name which
7980 * is located in the given MonoImage.
7982 * To reference nested classes, use the "/" character as a separator.
7983 * For example use "Foo/Bar" to reference the class Bar that is nested
7984 * inside Foo, like this: "class Foo { class Bar {} }".
7987 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7992 klass = mono_class_from_name_checked (image, name_space, name, &error);
7993 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7999 * mono_class_load_from_name:
8000 * @image: The MonoImage where the type is looked up in
8001 * @name_space: the type namespace
8002 * @name: the type short name.
8004 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8005 * This function should be used by the runtime for critical types to which there's no way to recover but crash
8006 * If they are missing. Thing of System.Object or System.String.
8009 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8014 klass = mono_class_from_name_checked (image, name_space, name, &error);
8016 g_error ("Runtime critical type %s.%s not found", name_space, name);
8017 if (!mono_error_ok (&error))
8018 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8023 * mono_class_try_load_from_name:
8024 * @image: The MonoImage where the type is looked up in
8025 * @name_space: the type namespace
8026 * @name: the type short name.
8028 * This function tries to load a type, returning the class was found or NULL otherwise.
8029 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8031 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8032 * a type that we would otherwise assume to be available but was not due some error.
8036 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8041 klass = mono_class_from_name_checked (image, name_space, name, &error);
8042 if (!mono_error_ok (&error))
8043 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8049 * mono_class_is_subclass_of:
8050 * @klass: class to probe if it is a subclass of another one
8051 * @klassc: the class we suspect is the base class
8052 * @check_interfaces: whether we should perform interface checks
8054 * This method determines whether @klass is a subclass of @klassc.
8056 * If the @check_interfaces flag is set, then if @klassc is an interface
8057 * this method return TRUE if the @klass implements the interface or
8058 * if @klass is an interface, if one of its base classes is @klass.
8060 * If @check_interfaces is false then, then if @klass is not an interface
8061 * then it returns TRUE if the @klass is a subclass of @klassc.
8063 * if @klass is an interface and @klassc is System.Object, then this function
8068 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8069 gboolean check_interfaces)
8071 /* FIXME test for interfaces with variant generic arguments */
8072 mono_class_init (klass);
8073 mono_class_init (klassc);
8075 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8076 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8078 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8081 for (i = 0; i < klass->interface_count; i ++) {
8082 MonoClass *ic = klass->interfaces [i];
8087 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8092 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8095 if (klassc == mono_defaults.object_class)
8102 mono_type_is_generic_argument (MonoType *type)
8104 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8108 mono_class_has_variant_generic_params (MonoClass *klass)
8111 MonoGenericContainer *container;
8113 if (!klass->generic_class)
8116 container = klass->generic_class->container_class->generic_container;
8118 for (i = 0; i < container->type_argc; ++i)
8119 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8126 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8128 if (target == candidate)
8131 if (check_for_reference_conv &&
8132 mono_type_is_generic_argument (&target->byval_arg) &&
8133 mono_type_is_generic_argument (&candidate->byval_arg)) {
8134 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8135 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8137 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8140 if (!mono_class_is_assignable_from (target, candidate))
8146 * @container the generic container from the GTD
8147 * @klass: the class to be assigned to
8148 * @oklass: the source class
8150 * Both @klass and @oklass must be instances of the same generic interface.
8152 * Returns: TRUE if @klass can be assigned to a @klass variable
8155 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8158 MonoType **klass_argv, **oklass_argv;
8159 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8160 MonoGenericContainer *container = klass_gtd->generic_container;
8162 if (klass == oklass)
8165 /*Viable candidates are instances of the same generic interface*/
8166 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8169 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8170 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8172 for (j = 0; j < container->type_argc; ++j) {
8173 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8174 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8176 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8180 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8181 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8183 if (param1_class != param2_class) {
8184 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8185 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8187 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8188 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8198 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8200 MonoGenericParam *gparam, *ogparam;
8201 MonoGenericParamInfo *tinfo, *cinfo;
8202 MonoClass **candidate_class;
8203 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8206 if (target == candidate)
8208 if (target->byval_arg.type != candidate->byval_arg.type)
8211 gparam = target->byval_arg.data.generic_param;
8212 ogparam = candidate->byval_arg.data.generic_param;
8213 tinfo = mono_generic_param_info (gparam);
8214 cinfo = mono_generic_param_info (ogparam);
8216 class_constraint_satisfied = FALSE;
8217 valuetype_constraint_satisfied = FALSE;
8219 /*candidate must have a super set of target's special constraints*/
8220 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8221 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8223 if (cinfo->constraints) {
8224 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8225 MonoClass *cc = *candidate_class;
8227 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8228 class_constraint_satisfied = TRUE;
8229 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8230 valuetype_constraint_satisfied = TRUE;
8233 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8234 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8236 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8238 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8240 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8241 valuetype_constraint_satisfied)) {
8246 /*candidate type constraints must be a superset of target's*/
8247 if (tinfo->constraints) {
8248 MonoClass **target_class;
8249 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8250 MonoClass *tc = *target_class;
8253 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8254 * check it's constraints since it satisfy the constraint by itself.
8256 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8259 if (!cinfo->constraints)
8262 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8263 MonoClass *cc = *candidate_class;
8265 if (mono_class_is_assignable_from (tc, cc))
8269 * This happens when we have the following:
8271 * Bar<K> where K : IFace
8272 * Foo<T, U> where T : U where U : IFace
8274 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8277 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8278 if (mono_gparam_is_assignable_from (target, cc))
8282 if (!*candidate_class)
8287 /*candidate itself must have a constraint that satisfy target*/
8288 if (cinfo->constraints) {
8289 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8290 MonoClass *cc = *candidate_class;
8291 if (mono_class_is_assignable_from (target, cc))
8299 * mono_class_is_assignable_from:
8300 * @klass: the class to be assigned to
8301 * @oklass: the source class
8303 * Returns: TRUE if an instance of object oklass can be assigned to an
8304 * instance of object @klass
8307 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8310 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8312 mono_class_init (klass);
8314 if (!oklass->inited)
8315 mono_class_init (oklass);
8317 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8320 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8321 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8323 return mono_gparam_is_assignable_from (klass, oklass);
8326 if (MONO_CLASS_IS_INTERFACE (klass)) {
8327 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8328 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8329 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8333 for (i = 0; constraints [i]; ++i) {
8334 if (mono_class_is_assignable_from (klass, constraints [i]))
8342 /* interface_offsets might not be set for dynamic classes */
8343 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8345 * oklass might be a generic type parameter but they have
8346 * interface_offsets set.
8348 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8349 if (!is_ok (&error)) {
8350 mono_error_cleanup (&error);
8355 if (!oklass->interface_bitmap)
8356 /* Happens with generic instances of not-yet created dynamic types */
8358 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8361 if (mono_class_has_variant_generic_params (klass)) {
8363 mono_class_setup_interfaces (oklass, &error);
8364 if (!mono_error_ok (&error)) {
8365 mono_error_cleanup (&error);
8369 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8370 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8371 MonoClass *iface = oklass->interfaces_packed [i];
8373 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8378 } else if (klass->delegate) {
8379 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8381 }else if (klass->rank) {
8382 MonoClass *eclass, *eoclass;
8384 if (oklass->rank != klass->rank)
8387 /* vectors vs. one dimensional arrays */
8388 if (oklass->byval_arg.type != klass->byval_arg.type)
8391 eclass = klass->cast_class;
8392 eoclass = oklass->cast_class;
8395 * a is b does not imply a[] is b[] when a is a valuetype, and
8396 * b is a reference type.
8399 if (eoclass->valuetype) {
8400 if ((eclass == mono_defaults.enum_class) ||
8401 (eclass == mono_defaults.enum_class->parent) ||
8402 (eclass == mono_defaults.object_class))
8406 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8407 } else if (mono_class_is_nullable (klass)) {
8408 if (mono_class_is_nullable (oklass))
8409 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8411 return mono_class_is_assignable_from (klass->cast_class, oklass);
8412 } else if (klass == mono_defaults.object_class)
8415 return mono_class_has_parent (oklass, klass);
8418 /*Check if @oklass is variant compatible with @klass.*/
8420 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8423 MonoType **klass_argv, **oklass_argv;
8424 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8425 MonoGenericContainer *container = klass_gtd->generic_container;
8427 /*Viable candidates are instances of the same generic interface*/
8428 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8431 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8432 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8434 for (j = 0; j < container->type_argc; ++j) {
8435 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8436 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8438 if (param1_class->valuetype != param2_class->valuetype)
8442 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8443 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8445 if (param1_class != param2_class) {
8446 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8447 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8449 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8450 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8458 /*Check if @candidate implements the interface @target*/
8460 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8464 gboolean is_variant = mono_class_has_variant_generic_params (target);
8466 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8467 if (mono_class_is_variant_compatible_slow (target, candidate))
8472 if (candidate == target)
8475 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8476 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8477 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8479 if (tb && tb->interfaces) {
8480 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8481 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8482 MonoClass *iface_class;
8484 /* we can't realize the type here since it can do pretty much anything. */
8487 iface_class = mono_class_from_mono_type (iface->type);
8488 if (iface_class == target)
8490 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8492 if (mono_class_implement_interface_slow (target, iface_class))
8497 /*setup_interfaces don't mono_class_init anything*/
8498 /*FIXME this doesn't handle primitive type arrays.
8499 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8500 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8502 mono_class_setup_interfaces (candidate, &error);
8503 if (!mono_error_ok (&error)) {
8504 mono_error_cleanup (&error);
8508 for (i = 0; i < candidate->interface_count; ++i) {
8509 if (candidate->interfaces [i] == target)
8512 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8515 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8519 candidate = candidate->parent;
8520 } while (candidate);
8526 * Check if @oklass can be assigned to @klass.
8527 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8530 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8532 if (candidate == target)
8534 if (target == mono_defaults.object_class)
8537 if (mono_class_has_parent (candidate, target))
8540 /*If target is not an interface there is no need to check them.*/
8541 if (MONO_CLASS_IS_INTERFACE (target))
8542 return mono_class_implement_interface_slow (target, candidate);
8544 if (target->delegate && mono_class_has_variant_generic_params (target))
8545 return mono_class_is_variant_compatible (target, candidate, FALSE);
8548 MonoClass *eclass, *eoclass;
8550 if (target->rank != candidate->rank)
8553 /* vectors vs. one dimensional arrays */
8554 if (target->byval_arg.type != candidate->byval_arg.type)
8557 eclass = target->cast_class;
8558 eoclass = candidate->cast_class;
8561 * a is b does not imply a[] is b[] when a is a valuetype, and
8562 * b is a reference type.
8565 if (eoclass->valuetype) {
8566 if ((eclass == mono_defaults.enum_class) ||
8567 (eclass == mono_defaults.enum_class->parent) ||
8568 (eclass == mono_defaults.object_class))
8572 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8574 /*FIXME properly handle nullables */
8575 /*FIXME properly handle (M)VAR */
8580 * mono_class_get_cctor:
8581 * @klass: A MonoClass pointer
8583 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8586 mono_class_get_cctor (MonoClass *klass)
8588 MonoCachedClassInfo cached_info;
8590 if (image_is_dynamic (klass->image)) {
8592 * has_cctor is not set for these classes because mono_class_init () is
8595 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8598 if (!klass->has_cctor)
8601 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8603 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8604 if (!mono_error_ok (&error))
8605 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8609 if (klass->generic_class && !klass->methods)
8610 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8612 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8616 * mono_class_get_finalizer:
8617 * @klass: The MonoClass pointer
8619 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8622 mono_class_get_finalizer (MonoClass *klass)
8624 MonoCachedClassInfo cached_info;
8627 mono_class_init (klass);
8628 if (!mono_class_has_finalizer (klass))
8631 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8633 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8634 if (!mono_error_ok (&error))
8635 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8638 mono_class_setup_vtable (klass);
8639 return klass->vtable [finalize_slot];
8644 * mono_class_needs_cctor_run:
8645 * @klass: the MonoClass pointer
8646 * @caller: a MonoMethod describing the caller
8648 * Determines whenever the class has a static constructor and whenever it
8649 * needs to be called when executing CALLER.
8652 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8656 method = mono_class_get_cctor (klass);
8658 return (method == caller) ? FALSE : TRUE;
8664 * mono_class_array_element_size:
8667 * Returns: The number of bytes an element of type @klass
8668 * uses when stored into an array.
8671 mono_class_array_element_size (MonoClass *klass)
8673 MonoType *type = &klass->byval_arg;
8676 switch (type->type) {
8679 case MONO_TYPE_BOOLEAN:
8683 case MONO_TYPE_CHAR:
8692 case MONO_TYPE_CLASS:
8693 case MONO_TYPE_STRING:
8694 case MONO_TYPE_OBJECT:
8695 case MONO_TYPE_SZARRAY:
8696 case MONO_TYPE_ARRAY:
8697 return sizeof (gpointer);
8702 case MONO_TYPE_VALUETYPE:
8703 if (type->data.klass->enumtype) {
8704 type = mono_class_enum_basetype (type->data.klass);
8705 klass = klass->element_class;
8708 return mono_class_instance_size (klass) - sizeof (MonoObject);
8709 case MONO_TYPE_GENERICINST:
8710 type = &type->data.generic_class->container_class->byval_arg;
8713 case MONO_TYPE_MVAR: {
8716 return mono_type_size (type, &align);
8718 case MONO_TYPE_VOID:
8722 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8728 * mono_array_element_size:
8729 * @ac: pointer to a #MonoArrayClass
8731 * Returns: The size of single array element.
8734 mono_array_element_size (MonoClass *ac)
8736 g_assert (ac->rank);
8737 return ac->sizes.element_size;
8741 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8742 MonoGenericContext *context)
8745 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8746 g_assert (mono_error_ok (&error));
8751 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8752 MonoGenericContext *context, MonoError *error)
8754 mono_error_init (error);
8756 if (image_is_dynamic (image)) {
8757 MonoClass *tmp_handle_class;
8758 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8760 mono_error_assert_ok (error);
8761 g_assert (tmp_handle_class);
8763 *handle_class = tmp_handle_class;
8765 if (tmp_handle_class == mono_defaults.typehandle_class)
8766 return &((MonoClass*)obj)->byval_arg;
8771 switch (token & 0xff000000) {
8772 case MONO_TOKEN_TYPE_DEF:
8773 case MONO_TOKEN_TYPE_REF:
8774 case MONO_TOKEN_TYPE_SPEC: {
8777 *handle_class = mono_defaults.typehandle_class;
8778 type = mono_type_get_checked (image, token, context, error);
8782 mono_class_init (mono_class_from_mono_type (type));
8783 /* We return a MonoType* as handle */
8786 case MONO_TOKEN_FIELD_DEF: {
8788 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8790 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8794 *handle_class = mono_defaults.fieldhandle_class;
8795 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8799 mono_class_init (klass);
8800 return mono_class_get_field (klass, token);
8802 case MONO_TOKEN_METHOD_DEF:
8803 case MONO_TOKEN_METHOD_SPEC: {
8805 meth = mono_get_method_checked (image, token, NULL, context, error);
8807 *handle_class = mono_defaults.methodhandle_class;
8813 case MONO_TOKEN_MEMBER_REF: {
8814 guint32 cols [MONO_MEMBERREF_SIZE];
8816 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8817 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8818 mono_metadata_decode_blob_size (sig, &sig);
8819 if (*sig == 0x6) { /* it's a field */
8821 MonoClassField *field;
8822 field = mono_field_from_token_checked (image, token, &klass, context, error);
8824 *handle_class = mono_defaults.fieldhandle_class;
8828 meth = mono_get_method_checked (image, token, NULL, context, error);
8830 *handle_class = mono_defaults.methodhandle_class;
8835 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8841 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8843 MonoClass *handle_class;
8844 mono_error_init (error);
8845 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8849 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8851 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8854 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8857 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8859 get_cached_class_info = func;
8863 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8865 if (!get_cached_class_info)
8868 return get_cached_class_info (klass, res);
8872 mono_install_get_class_from_name (MonoGetClassFromName func)
8874 get_class_from_name = func;
8878 * mono_class_get_image:
8880 * Use this method to get the `MonoImage*` where this class came from.
8882 * Returns: The image where this class is defined.
8885 mono_class_get_image (MonoClass *klass)
8887 return klass->image;
8891 * mono_class_get_element_class:
8892 * @klass: the MonoClass to act on
8894 * Use this function to get the element class of an array.
8896 * Returns: The element class of an array.
8899 mono_class_get_element_class (MonoClass *klass)
8901 return klass->element_class;
8905 * mono_class_is_valuetype:
8906 * @klass: the MonoClass to act on
8908 * Use this method to determine if the provided `MonoClass*` represents a value type,
8909 * or a reference type.
8911 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8914 mono_class_is_valuetype (MonoClass *klass)
8916 return klass->valuetype;
8920 * mono_class_is_enum:
8921 * @klass: the MonoClass to act on
8923 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8925 * Returns: TRUE if the MonoClass represents an enumeration.
8928 mono_class_is_enum (MonoClass *klass)
8930 return klass->enumtype;
8934 * mono_class_enum_basetype:
8935 * @klass: the MonoClass to act on
8937 * Use this function to get the underlying type for an enumeration value.
8939 * Returns: The underlying type representation for an enumeration.
8942 mono_class_enum_basetype (MonoClass *klass)
8944 if (klass->element_class == klass)
8945 /* SRE or broken types */
8948 return &klass->element_class->byval_arg;
8952 * mono_class_get_parent
8953 * @klass: the MonoClass to act on
8955 * Returns: The parent class for this class.
8958 mono_class_get_parent (MonoClass *klass)
8960 return klass->parent;
8964 * mono_class_get_nesting_type:
8965 * @klass: the MonoClass to act on
8967 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8969 * If the return is NULL, this indicates that this class is not nested.
8971 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8974 mono_class_get_nesting_type (MonoClass *klass)
8976 return klass->nested_in;
8980 * mono_class_get_rank:
8981 * @klass: the MonoClass to act on
8983 * Returns: The rank for the array (the number of dimensions).
8986 mono_class_get_rank (MonoClass *klass)
8992 * mono_class_get_flags:
8993 * @klass: the MonoClass to act on
8995 * The type flags from the TypeDef table from the metadata.
8996 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8999 * Returns: The flags from the TypeDef table.
9002 mono_class_get_flags (MonoClass *klass)
9004 return klass->flags;
9008 * mono_class_get_name
9009 * @klass: the MonoClass to act on
9011 * Returns: The name of the class.
9014 mono_class_get_name (MonoClass *klass)
9020 * mono_class_get_namespace:
9021 * @klass: the MonoClass to act on
9023 * Returns: The namespace of the class.
9026 mono_class_get_namespace (MonoClass *klass)
9028 return klass->name_space;
9032 * mono_class_get_type:
9033 * @klass: the MonoClass to act on
9035 * This method returns the internal Type representation for the class.
9037 * Returns: The MonoType from the class.
9040 mono_class_get_type (MonoClass *klass)
9042 return &klass->byval_arg;
9046 * mono_class_get_type_token:
9047 * @klass: the MonoClass to act on
9049 * This method returns type token for the class.
9051 * Returns: The type token for the class.
9054 mono_class_get_type_token (MonoClass *klass)
9056 return klass->type_token;
9060 * mono_class_get_byref_type:
9061 * @klass: the MonoClass to act on
9066 mono_class_get_byref_type (MonoClass *klass)
9068 return &klass->this_arg;
9072 * mono_class_num_fields:
9073 * @klass: the MonoClass to act on
9075 * Returns: The number of static and instance fields in the class.
9078 mono_class_num_fields (MonoClass *klass)
9080 return klass->field.count;
9084 * mono_class_num_methods:
9085 * @klass: the MonoClass to act on
9087 * Returns: The number of methods in the class.
9090 mono_class_num_methods (MonoClass *klass)
9092 return klass->method.count;
9096 * mono_class_num_properties
9097 * @klass: the MonoClass to act on
9099 * Returns: The number of properties in the class.
9102 mono_class_num_properties (MonoClass *klass)
9104 mono_class_setup_properties (klass);
9106 return klass->ext->property.count;
9110 * mono_class_num_events:
9111 * @klass: the MonoClass to act on
9113 * Returns: The number of events in the class.
9116 mono_class_num_events (MonoClass *klass)
9118 mono_class_setup_events (klass);
9120 return klass->ext->event.count;
9124 * mono_class_get_fields:
9125 * @klass: the MonoClass to act on
9127 * This routine is an iterator routine for retrieving the fields in a class.
9129 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9130 * iterate over all of the elements. When no more values are
9131 * available, the return value is NULL.
9133 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9136 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9138 MonoClassField* field;
9142 mono_class_setup_fields (klass);
9143 if (mono_class_has_failure (klass))
9145 /* start from the first */
9146 if (klass->field.count) {
9147 *iter = &klass->fields [0];
9148 return &klass->fields [0];
9154 field = (MonoClassField *)*iter;
9156 if (field < &klass->fields [klass->field.count]) {
9164 * mono_class_get_methods
9165 * @klass: the MonoClass to act on
9167 * This routine is an iterator routine for retrieving the fields in a class.
9169 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9170 * iterate over all of the elements. When no more values are
9171 * available, the return value is NULL.
9173 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9176 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9178 MonoMethod** method;
9182 mono_class_setup_methods (klass);
9185 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9186 * FIXME we should better report this error to the caller
9188 if (!klass->methods)
9190 /* start from the first */
9191 if (klass->method.count) {
9192 *iter = &klass->methods [0];
9193 return klass->methods [0];
9199 method = (MonoMethod **)*iter;
9201 if (method < &klass->methods [klass->method.count]) {
9209 * mono_class_get_virtual_methods:
9211 * Iterate over the virtual methods of KLASS.
9213 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9216 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9218 MonoMethod** method;
9221 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9223 mono_class_setup_methods (klass);
9225 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9226 * FIXME we should better report this error to the caller
9228 if (!klass->methods)
9230 /* start from the first */
9231 method = &klass->methods [0];
9233 method = (MonoMethod **)*iter;
9236 while (method < &klass->methods [klass->method.count]) {
9237 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9241 if (method < &klass->methods [klass->method.count]) {
9248 /* Search directly in metadata to avoid calling setup_methods () */
9249 MonoMethod *res = NULL;
9255 start_index = GPOINTER_TO_UINT (*iter);
9258 for (i = start_index; i < klass->method.count; ++i) {
9261 /* klass->method.first points into the methodptr table */
9262 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9264 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9268 if (i < klass->method.count) {
9270 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9271 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9273 /* Add 1 here so the if (*iter) check fails */
9274 *iter = GUINT_TO_POINTER (i + 1);
9283 * mono_class_get_properties:
9284 * @klass: the MonoClass to act on
9286 * This routine is an iterator routine for retrieving the properties in a class.
9288 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9289 * iterate over all of the elements. When no more values are
9290 * available, the return value is NULL.
9292 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9295 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9297 MonoProperty* property;
9301 mono_class_setup_properties (klass);
9302 /* start from the first */
9303 if (klass->ext->property.count) {
9304 *iter = &klass->ext->properties [0];
9305 return (MonoProperty *)*iter;
9311 property = (MonoProperty *)*iter;
9313 if (property < &klass->ext->properties [klass->ext->property.count]) {
9315 return (MonoProperty *)*iter;
9321 * mono_class_get_events:
9322 * @klass: the MonoClass to act on
9324 * This routine is an iterator routine for retrieving the properties in a class.
9326 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9327 * iterate over all of the elements. When no more values are
9328 * available, the return value is NULL.
9330 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9333 mono_class_get_events (MonoClass* klass, gpointer *iter)
9339 mono_class_setup_events (klass);
9340 /* start from the first */
9341 if (klass->ext->event.count) {
9342 *iter = &klass->ext->events [0];
9343 return (MonoEvent *)*iter;
9349 event = (MonoEvent *)*iter;
9351 if (event < &klass->ext->events [klass->ext->event.count]) {
9353 return (MonoEvent *)*iter;
9359 * mono_class_get_interfaces
9360 * @klass: the MonoClass to act on
9362 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9364 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9365 * iterate over all of the elements. When no more values are
9366 * available, the return value is NULL.
9368 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9371 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9379 mono_class_init (klass);
9380 if (!klass->interfaces_inited) {
9381 mono_class_setup_interfaces (klass, &error);
9382 if (!mono_error_ok (&error)) {
9383 mono_error_cleanup (&error);
9387 /* start from the first */
9388 if (klass->interface_count) {
9389 *iter = &klass->interfaces [0];
9390 return klass->interfaces [0];
9396 iface = (MonoClass **)*iter;
9398 if (iface < &klass->interfaces [klass->interface_count]) {
9406 setup_nested_types (MonoClass *klass)
9409 GList *classes, *nested_classes, *l;
9412 if (klass->nested_classes_inited)
9415 if (!klass->type_token)
9416 klass->nested_classes_inited = TRUE;
9418 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9422 guint32 cols [MONO_NESTED_CLASS_SIZE];
9423 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9424 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9425 if (!mono_error_ok (&error)) {
9426 /*FIXME don't swallow the error message*/
9427 mono_error_cleanup (&error);
9429 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9433 classes = g_list_prepend (classes, nclass);
9435 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9438 mono_class_alloc_ext (klass);
9440 nested_classes = NULL;
9441 for (l = classes; l; l = l->next)
9442 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9443 g_list_free (classes);
9445 mono_image_lock (klass->image);
9447 mono_memory_barrier ();
9448 if (!klass->nested_classes_inited) {
9449 klass->ext->nested_classes = nested_classes;
9450 mono_memory_barrier ();
9451 klass->nested_classes_inited = TRUE;
9454 mono_image_unlock (klass->image);
9458 * mono_class_get_nested_types
9459 * @klass: the MonoClass to act on
9461 * This routine is an iterator routine for retrieving the nested types of a class.
9462 * This works only if @klass is non-generic, or a generic type definition.
9464 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9465 * iterate over all of the elements. When no more values are
9466 * available, the return value is NULL.
9468 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9471 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9477 if (!klass->nested_classes_inited)
9478 setup_nested_types (klass);
9481 /* start from the first */
9482 if (klass->ext && klass->ext->nested_classes) {
9483 *iter = klass->ext->nested_classes;
9484 return (MonoClass *)klass->ext->nested_classes->data;
9486 /* no nested types */
9490 item = (GList *)*iter;
9494 return (MonoClass *)item->data;
9501 * mono_class_is_delegate
9502 * @klass: the MonoClass to act on
9504 * Returns: TRUE if the MonoClass represents a System.Delegate.
9507 mono_class_is_delegate (MonoClass *klass)
9509 return klass->delegate;
9513 * mono_class_implements_interface
9514 * @klass: The MonoClass to act on
9515 * @interface: The interface to check if @klass implements.
9517 * Returns: TRUE if @klass implements @interface.
9520 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9522 return mono_class_is_assignable_from (iface, klass);
9526 * mono_field_get_name:
9527 * @field: the MonoClassField to act on
9529 * Returns: The name of the field.
9532 mono_field_get_name (MonoClassField *field)
9538 * mono_field_get_type:
9539 * @field: the MonoClassField to act on
9541 * Returns: MonoType of the field.
9544 mono_field_get_type (MonoClassField *field)
9547 MonoType *type = mono_field_get_type_checked (field, &error);
9548 if (!mono_error_ok (&error)) {
9549 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9550 mono_error_cleanup (&error);
9557 * mono_field_get_type_checked:
9558 * @field: the MonoClassField to act on
9559 * @error: used to return any erro found while retrieving @field type
9561 * Returns: MonoType of the field.
9564 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9566 mono_error_init (error);
9568 mono_field_resolve_type (field, error);
9573 * mono_field_get_parent:
9574 * @field: the MonoClassField to act on
9576 * Returns: MonoClass where the field was defined.
9579 mono_field_get_parent (MonoClassField *field)
9581 return field->parent;
9585 * mono_field_get_flags;
9586 * @field: the MonoClassField to act on
9588 * The metadata flags for a field are encoded using the
9589 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9591 * Returns: The flags for the field.
9594 mono_field_get_flags (MonoClassField *field)
9597 return mono_field_resolve_flags (field);
9598 return field->type->attrs;
9602 * mono_field_get_offset:
9603 * @field: the MonoClassField to act on
9605 * Returns: The field offset.
9608 mono_field_get_offset (MonoClassField *field)
9610 return field->offset;
9614 mono_field_get_rva (MonoClassField *field)
9618 MonoClass *klass = field->parent;
9619 MonoFieldDefaultValue *field_def_values;
9621 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9623 if (!klass->ext || !klass->ext->field_def_values) {
9624 mono_class_alloc_ext (klass);
9626 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9628 mono_image_lock (klass->image);
9629 if (!klass->ext->field_def_values)
9630 klass->ext->field_def_values = field_def_values;
9631 mono_image_unlock (klass->image);
9634 field_index = mono_field_get_index (field);
9636 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9637 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9639 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9640 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9643 return klass->ext->field_def_values [field_index].data;
9647 * mono_field_get_data:
9648 * @field: the MonoClassField to act on
9650 * Returns: A pointer to the metadata constant value or to the field
9651 * data if it has an RVA flag.
9654 mono_field_get_data (MonoClassField *field)
9656 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9657 MonoTypeEnum def_type;
9659 return mono_class_get_field_default_value (field, &def_type);
9660 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9661 return mono_field_get_rva (field);
9668 * mono_property_get_name:
9669 * @prop: the MonoProperty to act on
9671 * Returns: The name of the property
9674 mono_property_get_name (MonoProperty *prop)
9680 * mono_property_get_set_method
9681 * @prop: the MonoProperty to act on.
9683 * Returns: The setter method of the property (A MonoMethod)
9686 mono_property_get_set_method (MonoProperty *prop)
9692 * mono_property_get_get_method
9693 * @prop: the MonoProperty to act on.
9695 * Returns: The setter method of the property (A MonoMethod)
9698 mono_property_get_get_method (MonoProperty *prop)
9704 * mono_property_get_parent:
9705 * @prop: the MonoProperty to act on.
9707 * Returns: The MonoClass where the property was defined.
9710 mono_property_get_parent (MonoProperty *prop)
9712 return prop->parent;
9716 * mono_property_get_flags:
9717 * @prop: the MonoProperty to act on.
9719 * The metadata flags for a property are encoded using the
9720 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9722 * Returns: The flags for the property.
9725 mono_property_get_flags (MonoProperty *prop)
9731 * mono_event_get_name:
9732 * @event: the MonoEvent to act on
9734 * Returns: The name of the event.
9737 mono_event_get_name (MonoEvent *event)
9743 * mono_event_get_add_method:
9744 * @event: The MonoEvent to act on.
9746 * Returns: The @add' method for the event (a MonoMethod).
9749 mono_event_get_add_method (MonoEvent *event)
9755 * mono_event_get_remove_method:
9756 * @event: The MonoEvent to act on.
9758 * Returns: The @remove method for the event (a MonoMethod).
9761 mono_event_get_remove_method (MonoEvent *event)
9763 return event->remove;
9767 * mono_event_get_raise_method:
9768 * @event: The MonoEvent to act on.
9770 * Returns: The @raise method for the event (a MonoMethod).
9773 mono_event_get_raise_method (MonoEvent *event)
9775 return event->raise;
9779 * mono_event_get_parent:
9780 * @event: the MonoEvent to act on.
9782 * Returns: The MonoClass where the event is defined.
9785 mono_event_get_parent (MonoEvent *event)
9787 return event->parent;
9791 * mono_event_get_flags
9792 * @event: the MonoEvent to act on.
9794 * The metadata flags for an event are encoded using the
9795 * EVENT_* constants. See the tabledefs.h file for details.
9797 * Returns: The flags for the event.
9800 mono_event_get_flags (MonoEvent *event)
9802 return event->attrs;
9806 * mono_class_get_method_from_name:
9807 * @klass: where to look for the method
9808 * @name: name of the method
9809 * @param_count: number of parameters. -1 for any number.
9811 * Obtains a MonoMethod with a given name and number of parameters.
9812 * It only works if there are no multiple signatures for any given method name.
9815 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9817 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9821 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9823 MonoMethod *res = NULL;
9826 /* Search directly in the metadata to avoid calling setup_methods () */
9827 for (i = 0; i < klass->method.count; ++i) {
9829 guint32 cols [MONO_METHOD_SIZE];
9831 MonoMethodSignature *sig;
9833 /* klass->method.first points into the methodptr table */
9834 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9836 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9837 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9839 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9842 if (param_count == -1) {
9846 sig = mono_method_signature_checked (method, &error);
9848 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9851 if (sig->param_count == param_count) {
9862 * mono_class_get_method_from_name_flags:
9863 * @klass: where to look for the method
9864 * @name_space: name of the method
9865 * @param_count: number of parameters. -1 for any number.
9866 * @flags: flags which must be set in the method
9868 * Obtains a MonoMethod with a given name and number of parameters.
9869 * It only works if there are no multiple signatures for any given method name.
9872 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9874 MonoMethod *res = NULL;
9877 mono_class_init (klass);
9879 if (klass->generic_class && !klass->methods) {
9880 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9883 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9884 if (!mono_error_ok (&error))
9885 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9890 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9891 mono_class_setup_methods (klass);
9893 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9894 See mono/tests/array_load_exception.il
9895 FIXME we should better report this error to the caller
9897 if (!klass->methods)
9899 for (i = 0; i < klass->method.count; ++i) {
9900 MonoMethod *method = klass->methods [i];
9902 if (method->name[0] == name [0] &&
9903 !strcmp (name, method->name) &&
9904 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9905 ((method->flags & flags) == flags)) {
9912 res = find_method_in_metadata (klass, name, param_count, flags);
9919 * mono_class_set_failure:
9920 * @klass: class in which the failure was detected
9921 * @ex_type: the kind of exception/error to be thrown (later)
9922 * @ex_data: exception data (specific to each type of exception/error)
9924 * Keep a detected failure informations in the class for later processing.
9925 * Note that only the first failure is kept.
9927 * LOCKING: Acquires the loader lock.
9930 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9932 g_assert (boxed_error != NULL);
9934 if (mono_class_has_failure (klass))
9937 mono_loader_lock ();
9938 klass->has_failure = 1;
9939 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9940 mono_loader_unlock ();
9946 mono_class_has_failure (const MonoClass *klass)
9948 g_assert (klass != NULL);
9949 return klass->has_failure != 0;
9954 * mono_class_set_type_load_failure:
9955 * @klass: class in which the failure was detected
9956 * @fmt: Printf-style error message string.
9958 * Collect detected failure informaion in the class for later processing.
9959 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9960 * Note that only the first failure is kept.
9962 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9964 * LOCKING: Acquires the loader lock.
9967 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9969 MonoError prepare_error;
9972 if (mono_class_has_failure (klass))
9975 mono_error_init (&prepare_error);
9977 va_start (args, fmt);
9978 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9981 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9982 mono_error_cleanup (&prepare_error);
9983 return mono_class_set_failure (klass, box);
9987 * mono_class_get_exception_data:
9989 * Return the exception_data property of KLASS.
9991 * LOCKING: Acquires the loader lock.
9994 mono_class_get_exception_data (const MonoClass *klass)
9996 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10000 * mono_classes_init:
10002 * Initialize the resources used by this module.
10005 mono_classes_init (void)
10007 mono_os_mutex_init (&classes_mutex);
10009 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
10010 mono_native_tls_alloc (&init_pending_tls_id, NULL);
10012 mono_counters_register ("Inflated methods size",
10013 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10014 mono_counters_register ("Inflated classes",
10015 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10016 mono_counters_register ("Inflated classes size",
10017 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10018 mono_counters_register ("MonoClass size",
10019 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10020 mono_counters_register ("MonoClassExt size",
10021 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10025 * mono_classes_cleanup:
10027 * Free the resources used by this module.
10030 mono_classes_cleanup (void)
10032 mono_native_tls_free (setup_fields_tls_id);
10033 mono_native_tls_free (init_pending_tls_id);
10035 if (global_interface_bitset)
10036 mono_bitset_free (global_interface_bitset);
10037 global_interface_bitset = NULL;
10038 mono_os_mutex_destroy (&classes_mutex);
10042 * mono_class_get_exception_for_failure:
10043 * @klass: class in which the failure was detected
10045 * Return a constructed MonoException than the caller can then throw
10046 * using mono_raise_exception - or NULL if no failure is present (or
10047 * doesn't result in an exception).
10050 mono_class_get_exception_for_failure (MonoClass *klass)
10052 if (!mono_class_has_failure (klass))
10054 MonoError unboxed_error;
10055 mono_error_init (&unboxed_error);
10056 mono_error_set_for_class_failure (&unboxed_error, klass);
10057 return mono_error_convert_to_exception (&unboxed_error);
10061 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10063 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10064 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10066 if (outer_klass == inner_klass)
10068 inner_klass = inner_klass->nested_in;
10069 } while (inner_klass);
10074 mono_class_get_generic_type_definition (MonoClass *klass)
10076 return klass->generic_class ? klass->generic_class->container_class : klass;
10080 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10082 * Generic instantiations are ignored for all super types of @klass.
10084 * Visibility checks ignoring generic instantiations.
10087 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10090 klass = mono_class_get_generic_type_definition (klass);
10091 parent = mono_class_get_generic_type_definition (parent);
10092 mono_class_setup_supertypes (klass);
10094 for (i = 0; i < klass->idepth; ++i) {
10095 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10101 * Subtype can only access parent members with family protection if the site object
10102 * is subclass of Subtype. For example:
10103 * class A { protected int x; }
10105 * void valid_access () {
10109 * void invalid_access () {
10116 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10118 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10121 if (context_klass == NULL)
10123 /*if access_klass is not member_klass context_klass must be type compat*/
10124 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10130 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10133 if (accessing == accessed)
10135 if (!accessed || !accessing)
10138 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10139 * anywhere so untrusted friends are not safe to access platform's code internals */
10140 if (mono_security_core_clr_enabled ()) {
10141 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10145 mono_assembly_load_friends (accessed);
10146 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10147 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10148 /* Be conservative with checks */
10149 if (!friend_->name)
10151 if (strcmp (accessing->aname.name, friend_->name))
10153 if (friend_->public_key_token [0]) {
10154 if (!accessing->aname.public_key_token [0])
10156 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10165 * If klass is a generic type or if it is derived from a generic type, return the
10166 * MonoClass of the generic definition
10167 * Returns NULL if not found
10170 get_generic_definition_class (MonoClass *klass)
10173 if (klass->generic_class && klass->generic_class->container_class)
10174 return klass->generic_class->container_class;
10175 klass = klass->parent;
10181 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10184 for (i = 0; i < ginst->type_argc; ++i) {
10185 MonoType *type = ginst->type_argv[i];
10186 switch (type->type) {
10187 case MONO_TYPE_SZARRAY:
10188 if (!can_access_type (access_klass, type->data.klass))
10191 case MONO_TYPE_ARRAY:
10192 if (!can_access_type (access_klass, type->data.array->eklass))
10195 case MONO_TYPE_PTR:
10196 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10199 case MONO_TYPE_CLASS:
10200 case MONO_TYPE_VALUETYPE:
10201 case MONO_TYPE_GENERICINST:
10202 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10212 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10216 if (access_klass == member_klass)
10219 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10222 if (access_klass->element_class && !access_klass->enumtype)
10223 access_klass = access_klass->element_class;
10225 if (member_klass->element_class && !member_klass->enumtype)
10226 member_klass = member_klass->element_class;
10228 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10230 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10233 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10236 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10239 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10242 /*Non nested type with nested visibility. We just fail it.*/
10243 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10246 switch (access_level) {
10247 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10248 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10250 case TYPE_ATTRIBUTE_PUBLIC:
10253 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10256 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10257 return is_nesting_type (member_klass, access_klass);
10259 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10260 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10262 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10263 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10265 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10266 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10267 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10269 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10270 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10271 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10276 /* FIXME: check visibility of type, too */
10278 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10280 MonoClass *member_generic_def;
10281 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10284 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10285 access_klass->generic_container) &&
10286 (member_generic_def = get_generic_definition_class (member_klass))) {
10287 MonoClass *access_container;
10289 if (access_klass->generic_container)
10290 access_container = access_klass;
10292 access_container = access_klass->generic_class->container_class;
10294 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10298 /* Partition I 8.5.3.2 */
10299 /* the access level values are the same for fields and methods */
10300 switch (access_level) {
10301 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10302 /* same compilation unit */
10303 return access_klass->image == member_klass->image;
10304 case FIELD_ATTRIBUTE_PRIVATE:
10305 return access_klass == member_klass;
10306 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10307 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10308 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10311 case FIELD_ATTRIBUTE_ASSEMBLY:
10312 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10313 case FIELD_ATTRIBUTE_FAMILY:
10314 if (is_valid_family_access (access_klass, member_klass, context_klass))
10317 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10318 if (is_valid_family_access (access_klass, member_klass, context_klass))
10320 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10321 case FIELD_ATTRIBUTE_PUBLIC:
10328 * mono_method_can_access_field:
10329 * @method: Method that will attempt to access the field
10330 * @field: the field to access
10332 * Used to determine if a method is allowed to access the specified field.
10334 * Returns: TRUE if the given @method is allowed to access the @field while following
10335 * the accessibility rules of the CLI.
10338 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10340 /* FIXME: check all overlapping fields */
10341 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10343 MonoClass *nested = method->klass->nested_in;
10345 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10348 nested = nested->nested_in;
10355 * mono_method_can_access_method:
10356 * @method: Method that will attempt to access the other method
10357 * @called: the method that we want to probe for accessibility.
10359 * Used to determine if the @method is allowed to access the specified @called method.
10361 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10362 * the accessibility rules of the CLI.
10365 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10367 method = mono_method_get_method_definition (method);
10368 called = mono_method_get_method_definition (called);
10369 return mono_method_can_access_method_full (method, called, NULL);
10373 * mono_method_can_access_method_full:
10374 * @method: The caller method
10375 * @called: The called method
10376 * @context_klass: The static type on stack of the owner @called object used
10378 * This function must be used with instance calls, as they have more strict family accessibility.
10379 * It can be used with static methods, but context_klass should be NULL.
10381 * Returns: TRUE if caller have proper visibility and acessibility to @called
10384 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10386 /* Wrappers are except from access checks */
10387 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10390 MonoClass *access_class = method->klass;
10391 MonoClass *member_class = called->klass;
10392 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10394 MonoClass *nested = access_class->nested_in;
10396 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10399 nested = nested->nested_in;
10406 can = can_access_type (access_class, member_class);
10408 MonoClass *nested = access_class->nested_in;
10410 can = can_access_type (nested, member_class);
10413 nested = nested->nested_in;
10420 if (called->is_inflated) {
10421 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10422 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10431 * mono_method_can_access_field_full:
10432 * @method: The caller method
10433 * @field: The accessed field
10434 * @context_klass: The static type on stack of the owner @field object used
10436 * This function must be used with instance fields, as they have more strict family accessibility.
10437 * It can be used with static fields, but context_klass should be NULL.
10439 * Returns: TRUE if caller have proper visibility and acessibility to @field
10442 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10444 MonoClass *access_class = method->klass;
10445 MonoClass *member_class = field->parent;
10446 /* FIXME: check all overlapping fields */
10447 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10449 MonoClass *nested = access_class->nested_in;
10451 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10454 nested = nested->nested_in;
10461 can = can_access_type (access_class, member_class);
10463 MonoClass *nested = access_class->nested_in;
10465 can = can_access_type (nested, member_class);
10468 nested = nested->nested_in;
10478 * mono_class_can_access_class:
10479 * @source_class: The source class
10480 * @target_class: The accessed class
10482 * This function returns is @target_class is visible to @source_class
10484 * Returns: TRUE if source have proper visibility and acessibility to target
10487 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10489 return can_access_type (source_class, target_class);
10493 * mono_type_is_valid_enum_basetype:
10494 * @type: The MonoType to check
10496 * Returns: TRUE if the type can be used as the basetype of an enum
10498 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10499 switch (type->type) {
10502 case MONO_TYPE_BOOLEAN:
10505 case MONO_TYPE_CHAR:
10519 * mono_class_is_valid_enum:
10520 * @klass: An enum class to be validated
10522 * This method verify the required properties an enum should have.
10524 * Returns: TRUE if the informed enum class is valid
10526 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10527 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10528 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10530 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10531 MonoClassField * field;
10532 gpointer iter = NULL;
10533 gboolean found_base_field = FALSE;
10535 g_assert (klass->enumtype);
10536 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10537 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10541 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10544 while ((field = mono_class_get_fields (klass, &iter))) {
10545 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10546 if (found_base_field)
10548 found_base_field = TRUE;
10549 if (!mono_type_is_valid_enum_basetype (field->type))
10554 if (!found_base_field)
10557 if (klass->method.count > 0)
10564 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10566 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10570 * mono_class_setup_interface_id:
10572 * Initializes MonoClass::interface_id if required.
10574 * LOCKING: Acquires the loader lock.
10577 mono_class_setup_interface_id (MonoClass *klass)
10579 mono_loader_lock ();
10580 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10581 klass->interface_id = mono_get_unique_iid (klass);
10582 mono_loader_unlock ();
10586 * mono_class_alloc_ext:
10588 * Allocate klass->ext if not already done.
10591 mono_class_alloc_ext (MonoClass *klass)
10598 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10599 mono_image_lock (klass->image);
10600 mono_memory_barrier ();
10603 class_ext_size += sizeof (MonoClassExt);
10604 mono_image_unlock (klass->image);
10608 * mono_class_setup_interfaces:
10610 * Initialize klass->interfaces/interfaces_count.
10611 * LOCKING: Acquires the loader lock.
10612 * This function can fail the type.
10615 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10617 int i, interface_count;
10618 MonoClass **interfaces;
10620 mono_error_init (error);
10622 if (klass->interfaces_inited)
10625 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10626 MonoType *args [1];
10628 /* generic IList, ICollection, IEnumerable */
10629 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10630 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10632 args [0] = &klass->element_class->byval_arg;
10633 interfaces [0] = mono_class_bind_generic_parameters (
10634 mono_defaults.generic_ilist_class, 1, args, FALSE);
10635 if (interface_count > 1)
10636 interfaces [1] = mono_class_bind_generic_parameters (
10637 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10638 } else if (klass->generic_class) {
10639 MonoClass *gklass = klass->generic_class->container_class;
10641 mono_class_setup_interfaces (gklass, error);
10642 if (!mono_error_ok (error)) {
10643 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10647 interface_count = gklass->interface_count;
10648 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10649 for (i = 0; i < interface_count; i++) {
10650 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10651 if (!mono_error_ok (error)) {
10652 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10657 interface_count = 0;
10661 mono_image_lock (klass->image);
10663 if (!klass->interfaces_inited) {
10664 klass->interface_count = interface_count;
10665 klass->interfaces = interfaces;
10667 mono_memory_barrier ();
10669 klass->interfaces_inited = TRUE;
10672 mono_image_unlock (klass->image);
10676 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10678 MonoClass *klass = field->parent;
10679 MonoImage *image = klass->image;
10680 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10681 int field_idx = field - klass->fields;
10683 mono_error_init (error);
10686 MonoClassField *gfield = >d->fields [field_idx];
10687 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10688 if (!mono_error_ok (error)) {
10689 char *full_name = mono_type_get_full_name (gtd);
10690 mono_class_set_type_load_failure (klass, "Could not load generic type of field '%s:%s' (%d) due to: %s", full_name, gfield->name, field_idx, mono_error_get_message (error));
10691 g_free (full_name);
10694 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10695 if (!mono_error_ok (error)) {
10696 char *full_name = mono_type_get_full_name (klass);
10697 mono_class_set_type_load_failure (klass, "Could not load instantiated type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10698 g_free (full_name);
10702 guint32 cols [MONO_FIELD_SIZE];
10703 MonoGenericContainer *container = NULL;
10704 int idx = klass->field.first + field_idx;
10706 /*FIXME, in theory we do not lazy load SRE fields*/
10707 g_assert (!image_is_dynamic (image));
10709 if (klass->generic_container) {
10710 container = klass->generic_container;
10712 container = gtd->generic_container;
10713 g_assert (container);
10716 /* klass->field.first and idx points into the fieldptr table */
10717 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10719 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10720 char *full_name = mono_type_get_full_name (klass);
10721 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10722 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10723 g_free (full_name);
10727 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10729 mono_metadata_decode_value (sig, &sig);
10730 /* FIELD signature == 0x06 */
10731 g_assert (*sig == 0x06);
10733 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10734 if (!field->type) {
10735 char *full_name = mono_type_get_full_name (klass);
10736 mono_class_set_type_load_failure (klass, "Could not load type of field '%s:%s' (%d) due to: %s", full_name, field->name, field_idx, mono_error_get_message (error));
10737 g_free (full_name);
10743 mono_field_resolve_flags (MonoClassField *field)
10745 MonoClass *klass = field->parent;
10746 MonoImage *image = klass->image;
10747 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10748 int field_idx = field - klass->fields;
10752 MonoClassField *gfield = >d->fields [field_idx];
10753 return mono_field_get_flags (gfield);
10755 int idx = klass->field.first + field_idx;
10757 /*FIXME, in theory we do not lazy load SRE fields*/
10758 g_assert (!image_is_dynamic (image));
10760 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10765 * mono_class_get_fields_lazy:
10766 * @klass: the MonoClass to act on
10768 * This routine is an iterator routine for retrieving the fields in a class.
10769 * Only minimal information about fields are loaded. Accessors must be used
10770 * for all MonoClassField returned.
10772 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10773 * iterate over all of the elements. When no more values are
10774 * available, the return value is NULL.
10776 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10779 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10781 MonoClassField* field;
10785 mono_class_setup_basic_field_info (klass);
10786 if (!klass->fields)
10788 /* start from the first */
10789 if (klass->field.count) {
10790 *iter = &klass->fields [0];
10791 return (MonoClassField *)*iter;
10797 field = (MonoClassField *)*iter;
10799 if (field < &klass->fields [klass->field.count]) {
10801 return (MonoClassField *)*iter;
10807 mono_class_full_name (MonoClass *klass)
10809 return mono_type_full_name (&klass->byval_arg);
10812 /* Declare all shared lazy type lookup functions */
10813 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)