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 (mono_class_is_ginst (klass)) {
510 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
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 (mono_class_is_gtd (klass) &&
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 < mono_class_get_generic_container (klass)->type_argc; i++) {
550 g_string_append_c (str, ',');
551 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), 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 mono_class_is_gtd (t->data.klass);
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 = mono_class_try_get_generic_container (klass);
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 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
831 return gklass ? mono_generic_class_get_context (gklass) : NULL;
835 * mono_class_inflate_generic_type_with_mempool:
836 * @mempool: a mempool
838 * @context: a generics context
839 * @error: error context
841 * The same as mono_class_inflate_generic_type, but allocates the MonoType
842 * from mempool if it is non-NULL. If it is NULL, the MonoType is
843 * allocated on the heap and is owned by the caller.
844 * The returned type can potentially be the same as TYPE, so it should not be
845 * modified by the caller, and it should be freed using mono_metadata_free_type ().
848 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
850 MonoType *inflated = NULL;
851 mono_error_init (error);
854 inflated = inflate_generic_type (image, type, context, error);
855 return_val_if_nok (error, NULL);
858 MonoType *shared = mono_metadata_get_shared_type (type);
863 return mono_metadata_type_dup (image, type);
867 mono_stats.inflated_type_count++;
872 * mono_class_inflate_generic_type:
874 * @context: a generics context
876 * If @type is a generic type and @context is not NULL, instantiate it using the
877 * generics context @context.
879 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
880 * on the heap and is owned by the caller. Returns NULL on error.
882 * @deprecated Please use mono_class_inflate_generic_type_checked instead
885 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
889 result = mono_class_inflate_generic_type_checked (type, context, &error);
890 mono_error_cleanup (&error);
895 * mono_class_inflate_generic_type:
897 * @context: a generics context
898 * @error: error context to use
900 * If @type is a generic type and @context is not NULL, instantiate it using the
901 * generics context @context.
903 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
904 * on the heap and is owned by the caller.
907 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
909 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
913 * mono_class_inflate_generic_type_no_copy:
915 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
919 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
921 MonoType *inflated = NULL;
923 mono_error_init (error);
925 inflated = inflate_generic_type (image, type, context, error);
926 return_val_if_nok (error, NULL);
932 mono_stats.inflated_type_count++;
937 * mono_class_inflate_generic_class:
939 * Inflate the class @gklass with @context. Set @error on failure.
942 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
947 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
948 return_val_if_nok (error, NULL);
950 res = mono_class_from_mono_type (inflated);
951 mono_metadata_free_type (inflated);
956 static MonoGenericContext
957 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
959 MonoGenericInst *class_inst = NULL;
960 MonoGenericInst *method_inst = NULL;
961 MonoGenericContext res = { NULL, NULL };
963 mono_error_init (error);
965 if (context->class_inst) {
966 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
967 if (!mono_error_ok (error))
971 if (context->method_inst) {
972 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
973 if (!mono_error_ok (error))
977 res.class_inst = class_inst;
978 res.method_inst = method_inst;
984 * mono_class_inflate_generic_method:
985 * @method: a generic method
986 * @context: a generics context
988 * Instantiate the generic method @method using the generics context @context.
990 * Returns: The new instantiated method
993 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
995 return mono_class_inflate_generic_method_full (method, NULL, context);
999 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1001 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1005 * mono_class_inflate_generic_method_full:
1007 * Instantiate method @method with the generic context @context.
1008 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1009 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1012 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1015 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1016 if (!mono_error_ok (&error))
1017 /*FIXME do proper error handling - on this case, kill this function. */
1018 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1024 * mono_class_inflate_generic_method_full_checked:
1025 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1028 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1031 MonoMethodInflated *iresult, *cached;
1032 MonoMethodSignature *sig;
1033 MonoGenericContext tmp_context;
1035 mono_error_init (error);
1037 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1038 while (method->is_inflated) {
1039 MonoGenericContext *method_context = mono_method_get_context (method);
1040 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1042 tmp_context = inflate_generic_context (method_context, context, error);
1043 return_val_if_nok (error, NULL);
1045 context = &tmp_context;
1047 if (mono_metadata_generic_context_equal (method_context, context))
1050 method = imethod->declaring;
1054 * A method only needs to be inflated if the context has argument for which it is
1057 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1058 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1061 if (!((method->is_generic && context->method_inst) ||
1062 (mono_class_is_gtd (method->klass) && context->class_inst)))
1065 iresult = g_new0 (MonoMethodInflated, 1);
1066 iresult->context = *context;
1067 iresult->declaring = method;
1069 if (!context->method_inst && method->is_generic)
1070 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1072 if (!context->class_inst) {
1073 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1074 if (mono_class_is_gtd (iresult->declaring->klass))
1075 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1077 /* This can happen with some callers like mono_object_get_virtual_method () */
1078 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1079 iresult->context.class_inst = NULL;
1081 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1084 mono_image_set_lock (set);
1085 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1086 mono_image_set_unlock (set);
1090 return (MonoMethod*)cached;
1093 mono_stats.inflated_method_count++;
1095 inflated_methods_size += sizeof (MonoMethodInflated);
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1117 if (method->wrapper_type) {
1118 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1119 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1120 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1122 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1123 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1126 if (iresult->context.method_inst) {
1127 /* Set the generic_container of the result to the generic_container of method */
1128 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1130 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1131 result->is_generic = 1;
1132 mono_method_set_generic_container (result, generic_container);
1137 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1138 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1142 if (mono_class_is_gtd (method->klass))
1143 result->klass = klass_hint;
1145 if (!result->klass) {
1146 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1147 if (!mono_error_ok (error))
1150 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1152 mono_metadata_free_type (inflated);
1156 * FIXME: This should hold, but it doesn't:
1158 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1159 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1160 * g_assert (result->is_generic);
1163 * Fixing this here causes other things to break, hence a very
1164 * ugly hack in mini-trampolines.c - see
1165 * is_generic_method_definition().
1169 mono_image_set_lock (set);
1170 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1172 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1173 iresult->owner = set;
1176 mono_image_set_unlock (set);
1178 return (MonoMethod*)cached;
1186 * mono_get_inflated_method:
1188 * Obsolete. We keep it around since it's mentioned in the public API.
1191 mono_get_inflated_method (MonoMethod *method)
1197 * mono_method_get_context_general:
1199 * @uninflated: handle uninflated methods?
1201 * Returns the generic context of a method or NULL if it doesn't have
1202 * one. For an inflated method that's the context stored in the
1203 * method. Otherwise it's in the method's generic container or in the
1204 * generic container of the method's class.
1207 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1209 if (method->is_inflated) {
1210 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1211 return &imethod->context;
1215 if (method->is_generic)
1216 return &(mono_method_get_generic_container (method)->context);
1217 if (mono_class_is_gtd (method->klass))
1218 return &mono_class_get_generic_container (method->klass)->context;
1223 * mono_method_get_context:
1226 * Returns the generic context for method if it's inflated, otherwise
1230 mono_method_get_context (MonoMethod *method)
1232 return mono_method_get_context_general (method, FALSE);
1236 * mono_method_get_generic_container:
1238 * Returns the generic container of METHOD, which should be a generic method definition.
1239 * Returns NULL if METHOD is not a generic method definition.
1240 * LOCKING: Acquires the loader lock.
1242 MonoGenericContainer*
1243 mono_method_get_generic_container (MonoMethod *method)
1245 MonoGenericContainer *container;
1247 if (!method->is_generic)
1250 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1251 g_assert (container);
1257 * mono_method_set_generic_container:
1259 * Sets the generic container of METHOD to CONTAINER.
1260 * LOCKING: Acquires the image lock.
1263 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1265 g_assert (method->is_generic);
1267 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1271 * mono_class_find_enum_basetype:
1272 * @class: The enum class
1274 * Determine the basetype of an enum by iterating through its fields. We do this
1275 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1278 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1280 MonoGenericContainer *container = NULL;
1281 MonoImage *m = klass->image;
1282 const int top = klass->field.count;
1285 g_assert (klass->enumtype);
1287 mono_error_init (error);
1289 container = mono_class_try_get_generic_container (klass);
1290 if (mono_class_is_ginst (klass)) {
1291 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1293 container = mono_class_get_generic_container (gklass);
1294 g_assert (container);
1298 * Fetch all the field information.
1300 for (i = 0; i < top; i++){
1302 guint32 cols [MONO_FIELD_SIZE];
1303 int idx = klass->field.first + i;
1306 /* klass->field.first and idx points into the fieldptr table */
1307 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1309 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1312 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1313 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1317 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1318 mono_metadata_decode_value (sig, &sig);
1319 /* FIELD signature == 0x06 */
1321 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1325 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1329 if (mono_class_is_ginst (klass)) {
1330 //FIXME do we leak here?
1331 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1332 if (!mono_error_ok (error))
1334 ftype->attrs = cols [MONO_FIELD_FLAGS];
1339 mono_error_set_type_load_class (error, klass, "Could not find base type");
1346 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1349 mono_type_has_exceptions (MonoType *type)
1351 switch (type->type) {
1352 case MONO_TYPE_CLASS:
1353 case MONO_TYPE_VALUETYPE:
1354 case MONO_TYPE_SZARRAY:
1355 return mono_class_has_failure (type->data.klass);
1356 case MONO_TYPE_ARRAY:
1357 return mono_class_has_failure (type->data.array->eklass);
1358 case MONO_TYPE_GENERICINST:
1359 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1366 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1368 g_assert (mono_class_has_failure (klass));
1369 MonoErrorBoxed *box = (MonoErrorBoxed*)mono_class_get_exception_data (klass);
1370 mono_error_set_from_boxed (oerror, box);
1377 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1381 mono_class_alloc (MonoClass *klass, int size)
1383 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1385 return mono_image_set_alloc (gklass->owner, size);
1387 return mono_image_alloc (klass->image, size);
1391 mono_class_alloc0 (MonoClass *klass, int size)
1395 res = mono_class_alloc (klass, size);
1396 memset (res, 0, size);
1400 #define mono_class_new0(klass,struct_type, n_structs) \
1401 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1404 * mono_class_setup_basic_field_info:
1405 * @class: The class to initialize
1407 * Initializes the following fields in MonoClass:
1408 * * klass->fields (only field->parent and field->name)
1409 * * klass->field.count
1410 * * klass->field.first
1411 * LOCKING: Acquires the loader lock
1414 mono_class_setup_basic_field_info (MonoClass *klass)
1416 MonoGenericClass *gklass;
1417 MonoClassField *field;
1418 MonoClassField *fields;
1426 gklass = mono_class_try_get_generic_class (klass);
1427 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1428 image = klass->image;
1431 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1433 * This happens when a generic instance of an unfinished generic typebuilder
1434 * is used as an element type for creating an array type. We can't initialize
1435 * the fields of this class using the fields of gklass, since gklass is not
1436 * finished yet, fields could be added to it later.
1442 mono_class_setup_basic_field_info (gtd);
1444 mono_loader_lock ();
1445 klass->field.first = gtd->field.first;
1446 klass->field.count = gtd->field.count;
1447 mono_loader_unlock ();
1450 top = klass->field.count;
1452 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1455 * Fetch all the field information.
1457 for (i = 0; i < top; i++){
1458 field = &fields [i];
1459 field->parent = klass;
1462 field->name = mono_field_get_name (>d->fields [i]);
1464 int idx = klass->field.first + i;
1465 /* klass->field.first and idx points into the fieldptr table */
1466 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1467 /* The name is needed for fieldrefs */
1468 field->name = mono_metadata_string_heap (image, name_idx);
1472 mono_memory_barrier ();
1474 mono_loader_lock ();
1476 klass->fields = fields;
1477 mono_loader_unlock ();
1481 * mono_class_set_failure_causedby_class:
1482 * @klass: the class that is failing
1483 * @caused_by: the class that caused the failure
1484 * @msg: Why @klass is failing.
1486 * If @caused_by has a failure, sets a TypeLoadException failure on
1487 * @klass with message "@msg, due to: {@caused_by message}".
1489 * Returns: TRUE if a failiure was set, or FALSE if @caused_by doesn't have a failure.
1492 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1494 if (mono_class_has_failure (caused_by)) {
1495 MonoError cause_error;
1496 mono_error_init (&cause_error);
1497 mono_error_set_for_class_failure (&cause_error, caused_by);
1498 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1499 mono_error_cleanup (&cause_error);
1508 * mono_class_setup_fields:
1509 * @klass: The class to initialize
1511 * Initializes klass->fields, computes class layout and sizes.
1512 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1513 * Sets the following fields in @klass:
1514 * - all the fields initialized by mono_class_init_sizes ()
1515 * - element_class/cast_class (for enums)
1516 * - field->type/offset for all fields
1519 * LOCKING: Acquires the loader lock.
1522 mono_class_setup_fields (MonoClass *klass)
1525 MonoImage *m = klass->image;
1527 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1529 guint32 real_size = 0;
1530 guint32 packing_size = 0;
1532 gboolean explicit_size;
1533 MonoClassField *field;
1534 MonoGenericContainer *container = NULL;
1535 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1538 if (klass->fields_inited)
1541 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1543 * This happens when a generic instance of an unfinished generic typebuilder
1544 * is used as an element type for creating an array type. We can't initialize
1545 * the fields of this class using the fields of gklass, since gklass is not
1546 * finished yet, fields could be added to it later.
1551 mono_class_setup_basic_field_info (klass);
1552 top = klass->field.count;
1554 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1556 mono_class_setup_fields (gtd);
1557 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1562 if (klass->parent) {
1563 /* For generic instances, klass->parent might not have been initialized */
1564 mono_class_init (klass->parent);
1565 mono_class_setup_fields (klass->parent);
1566 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1568 instance_size = klass->parent->instance_size;
1570 instance_size = sizeof (MonoObject);
1573 /* Get the real size */
1574 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1576 instance_size += real_size;
1579 * This function can recursively call itself.
1580 * Prevent infinite recursion by using a list in TLS.
1582 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1583 if (g_slist_find (init_list, klass))
1585 init_list = g_slist_prepend (init_list, klass);
1586 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1589 * Fetch all the field information.
1591 for (i = 0; i < top; i++) {
1592 int idx = klass->field.first + i;
1593 field = &klass->fields [i];
1596 mono_field_resolve_type (field, &error);
1597 if (!mono_error_ok (&error)) {
1598 /*mono_field_resolve_type already failed class*/
1599 mono_error_cleanup (&error);
1603 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604 g_assert (field->type);
1607 if (mono_field_is_deleted (field))
1609 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1611 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1612 int offset = uoffset;
1614 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1618 if (offset < -1) { /*-1 is used to encode special static fields */
1619 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1622 if (klass->generic_container) {
1623 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1627 if (mono_type_has_exceptions (field->type)) {
1628 char *class_name = mono_type_get_full_name (klass);
1629 char *type_name = mono_type_full_name (field->type);
1631 mono_class_set_type_load_failure (klass, "");
1632 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1633 g_free (class_name);
1637 /* The def_value of fields is compute lazily during vtable creation */
1640 if (!mono_class_has_failure (klass))
1641 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1643 init_list = g_slist_remove (init_list, klass);
1644 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1648 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1651 klass->instance_size = cached_info->instance_size;
1652 klass->sizes.class_size = cached_info->class_size;
1653 klass->packing_size = cached_info->packing_size;
1654 klass->min_align = cached_info->min_align;
1655 klass->blittable = cached_info->blittable;
1656 klass->has_references = cached_info->has_references;
1657 klass->has_static_refs = cached_info->has_static_refs;
1658 klass->no_special_static_fields = cached_info->no_special_static_fields;
1661 if (!klass->size_inited)
1662 mono_class_setup_fields (klass);
1667 * mono_class_init_sizes:
1669 * Initializes the size related fields of @klass without loading all field data if possible.
1670 * Sets the following fields in @klass:
1672 * - sizes.class_size
1679 * Can fail the class.
1681 * LOCKING: Acquires the loader lock.
1684 mono_class_init_sizes (MonoClass *klass)
1686 MonoCachedClassInfo cached_info;
1687 gboolean has_cached_info;
1689 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1691 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1695 * mono_type_get_basic_type_from_generic:
1698 * Returns a closed type corresponding to the possibly open type
1702 mono_type_get_basic_type_from_generic (MonoType *type)
1704 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1705 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1706 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1707 return &mono_defaults.object_class->byval_arg;
1712 class_has_references (MonoClass *klass)
1714 mono_class_init_sizes (klass);
1717 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1718 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1721 return klass->has_references;
1725 type_has_references (MonoClass *klass, MonoType *ftype)
1727 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1729 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1730 MonoGenericParam *gparam = ftype->data.generic_param;
1732 if (gparam->gshared_constraint)
1733 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1739 * mono_class_layout_fields:
1741 * @base_instance_size: base instance size
1744 * This contains the common code for computing the layout of classes and sizes.
1745 * This should only be called from mono_class_setup_fields () and
1746 * typebuilder_setup_fields ().
1748 * LOCKING: Acquires the loader lock
1751 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1754 const int top = klass->field.count;
1755 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1756 guint32 pass, passes, real_size;
1757 gboolean gc_aware_layout = FALSE;
1758 gboolean has_static_fields = FALSE;
1759 gboolean has_references = FALSE;
1760 gboolean has_static_refs = FALSE;
1761 MonoClassField *field;
1763 int instance_size = base_instance_size;
1764 int class_size, min_align;
1768 * We want to avoid doing complicated work inside locks, so we compute all the required
1769 * information and write it to @klass inside a lock.
1771 if (klass->fields_inited)
1774 if ((packing_size & 0xffffff00) != 0) {
1775 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1779 if (klass->parent) {
1780 min_align = klass->parent->min_align;
1781 /* we use | since it may have been set already */
1782 has_references = klass->has_references | klass->parent->has_references;
1786 /* We can't really enable 16 bytes alignment until the GC supports it.
1787 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1788 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1789 Bug #506144 is an example of this issue.
1791 if (klass->simd_type)
1796 * When we do generic sharing we need to have layout
1797 * information for open generic classes (either with a generic
1798 * context containing type variables or with a generic
1799 * container), so we don't return in that case anymore.
1802 if (klass->enumtype) {
1803 for (i = 0; i < top; i++) {
1804 field = &klass->fields [i];
1805 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1806 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1811 if (!mono_class_enum_basetype (klass)) {
1812 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1818 * Enable GC aware auto layout: in this mode, reference
1819 * fields are grouped together inside objects, increasing collector
1821 * Requires that all classes whose layout is known to native code be annotated
1822 * with [StructLayout (LayoutKind.Sequential)]
1823 * Value types have gc_aware_layout disabled by default, as per
1824 * what the default is for other runtimes.
1826 /* corlib is missing [StructLayout] directives in many places */
1827 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1828 if (!klass->valuetype)
1829 gc_aware_layout = TRUE;
1832 /* Compute klass->blittable */
1835 blittable = klass->parent->blittable;
1836 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1838 for (i = 0; i < top; i++) {
1839 field = &klass->fields [i];
1841 if (mono_field_is_deleted (field))
1843 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1846 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1849 MonoClass *field_class = mono_class_from_mono_type (field->type);
1851 mono_class_setup_fields (field_class);
1852 if (mono_class_has_failure (field_class)) {
1853 MonoError field_error;
1854 mono_error_init (&field_error);
1855 mono_error_set_for_class_failure (&field_error, field_class);
1856 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1857 mono_error_cleanup (&field_error);
1861 if (!field_class || !field_class->blittable)
1865 if (klass->enumtype)
1866 blittable = klass->element_class->blittable;
1868 if (mono_class_has_failure (klass))
1870 if (klass == mono_defaults.string_class)
1873 /* Compute klass->has_references */
1875 * Process non-static fields first, since static fields might recursively
1876 * refer to the class itself.
1878 for (i = 0; i < top; i++) {
1881 field = &klass->fields [i];
1883 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1884 ftype = mono_type_get_underlying_type (field->type);
1885 ftype = mono_type_get_basic_type_from_generic (ftype);
1886 if (type_has_references (klass, ftype))
1887 has_references = TRUE;
1892 * Compute field layout and total size (not considering static fields)
1894 field_offsets = g_new0 (int, top);
1896 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1897 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1898 if (gc_aware_layout)
1903 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1906 if (klass->parent) {
1907 mono_class_setup_fields (klass->parent);
1908 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1910 real_size = klass->parent->instance_size;
1912 real_size = sizeof (MonoObject);
1915 for (pass = 0; pass < passes; ++pass) {
1916 for (i = 0; i < top; i++){
1921 field = &klass->fields [i];
1923 if (mono_field_is_deleted (field))
1925 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1928 ftype = mono_type_get_underlying_type (field->type);
1929 ftype = mono_type_get_basic_type_from_generic (ftype);
1930 if (gc_aware_layout) {
1931 if (type_has_references (klass, ftype)) {
1940 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1941 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1942 /* This field is a hack inserted by MCS to empty structures */
1946 size = mono_type_size (field->type, &align);
1948 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1949 align = packing_size ? MIN (packing_size, align): align;
1950 /* if the field has managed references, we need to force-align it
1953 if (type_has_references (klass, ftype))
1954 align = MAX (align, sizeof (gpointer));
1956 min_align = MAX (align, min_align);
1957 field_offsets [i] = real_size;
1959 field_offsets [i] += align - 1;
1960 field_offsets [i] &= ~(align - 1);
1962 /*TypeBuilders produce all sort of weird things*/
1963 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1964 real_size = field_offsets [i] + size;
1967 instance_size = MAX (real_size, instance_size);
1969 if (instance_size & (min_align - 1)) {
1970 instance_size += min_align - 1;
1971 instance_size &= ~(min_align - 1);
1975 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1979 for (i = 0; i < top; i++) {
1984 field = &klass->fields [i];
1987 * There must be info about all the fields in a type if it
1988 * uses explicit layout.
1990 if (mono_field_is_deleted (field))
1992 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1995 size = mono_type_size (field->type, &align);
1996 align = packing_size ? MIN (packing_size, align): align;
1997 min_align = MAX (align, min_align);
2000 /* Already set by typebuilder_setup_fields () */
2001 field_offsets [i] = field->offset + sizeof (MonoObject);
2003 int idx = klass->field.first + i;
2005 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2006 field_offsets [i] = offset + sizeof (MonoObject);
2008 ftype = mono_type_get_underlying_type (field->type);
2009 ftype = mono_type_get_basic_type_from_generic (ftype);
2010 if (type_has_references (klass, ftype)) {
2011 if (field_offsets [i] % sizeof (gpointer)) {
2012 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2019 real_size = MAX (real_size, size + field_offsets [i]);
2022 if (klass->has_references) {
2023 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2025 /* Check for overlapping reference and non-reference fields */
2026 for (i = 0; i < top; i++) {
2029 field = &klass->fields [i];
2031 if (mono_field_is_deleted (field))
2033 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2035 ftype = mono_type_get_underlying_type (field->type);
2036 if (MONO_TYPE_IS_REFERENCE (ftype))
2037 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2039 for (i = 0; i < top; i++) {
2040 field = &klass->fields [i];
2042 if (mono_field_is_deleted (field))
2044 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2047 // FIXME: Too much code does this
2049 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2050 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]);
2054 g_free (ref_bitmap);
2057 instance_size = MAX (real_size, instance_size);
2058 if (instance_size & (min_align - 1)) {
2059 instance_size += min_align - 1;
2060 instance_size &= ~(min_align - 1);
2066 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2068 * This leads to all kinds of problems with nested structs, so only
2069 * enable it when a MONO_DEBUG property is set.
2071 * For small structs, set min_align to at least the struct size to improve
2072 * performance, and since the JIT memset/memcpy code assumes this and generates
2073 * unaligned accesses otherwise. See #78990 for a testcase.
2075 if (mono_align_small_structs && top) {
2076 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2077 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2081 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2082 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2083 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2084 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2086 /* Publish the data */
2087 mono_loader_lock ();
2088 if (klass->instance_size && !klass->image->dynamic) {
2089 /* Might be already set using cached info */
2090 g_assert (klass->instance_size == instance_size);
2092 klass->instance_size = instance_size;
2094 klass->blittable = blittable;
2095 klass->has_references = has_references;
2096 klass->packing_size = packing_size;
2097 klass->min_align = min_align;
2098 for (i = 0; i < top; ++i) {
2099 field = &klass->fields [i];
2100 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2101 klass->fields [i].offset = field_offsets [i];
2104 mono_memory_barrier ();
2105 klass->size_inited = 1;
2106 mono_loader_unlock ();
2109 * Compute static field layout and size
2110 * Static fields can reference the class itself, so this has to be
2111 * done after instance_size etc. are initialized.
2114 for (i = 0; i < top; i++) {
2118 field = &klass->fields [i];
2120 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2122 if (mono_field_is_deleted (field))
2125 if (mono_type_has_exceptions (field->type)) {
2126 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2130 has_static_fields = TRUE;
2132 size = mono_type_size (field->type, &align);
2133 field_offsets [i] = class_size;
2134 /*align is always non-zero here*/
2135 field_offsets [i] += align - 1;
2136 field_offsets [i] &= ~(align - 1);
2137 class_size = field_offsets [i] + size;
2140 if (has_static_fields && class_size == 0)
2141 /* Simplify code which depends on class_size != 0 if the class has static fields */
2144 /* Compute klass->has_static_refs */
2145 has_static_refs = FALSE;
2146 for (i = 0; i < top; i++) {
2149 field = &klass->fields [i];
2151 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2152 ftype = mono_type_get_underlying_type (field->type);
2153 ftype = mono_type_get_basic_type_from_generic (ftype);
2154 if (type_has_references (klass, ftype))
2155 has_static_refs = TRUE;
2159 /*valuetypes can't be neither bigger than 1Mb or empty. */
2160 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2161 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2163 /* Publish the data */
2164 mono_loader_lock ();
2166 klass->sizes.class_size = class_size;
2167 klass->has_static_refs = has_static_refs;
2168 for (i = 0; i < top; ++i) {
2169 field = &klass->fields [i];
2171 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2172 field->offset = field_offsets [i];
2175 mono_memory_barrier ();
2176 klass->fields_inited = 1;
2177 mono_loader_unlock ();
2179 g_free (field_offsets);
2183 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2187 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2188 method->klass = klass;
2189 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2190 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2191 method->signature = sig;
2192 method->name = name;
2195 if (name [0] == '.') {
2196 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2198 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2204 * mono_class_setup_methods:
2207 * Initializes the 'methods' array in CLASS.
2208 * Calling this method should be avoided if possible since it allocates a lot
2209 * of long-living MonoMethod structures.
2210 * Methods belonging to an interface are assigned a sequential slot starting
2213 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2216 mono_class_setup_methods (MonoClass *klass)
2219 MonoMethod **methods;
2224 if (mono_class_is_ginst (klass)) {
2226 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2228 mono_class_init (gklass);
2229 if (!mono_class_has_failure (gklass))
2230 mono_class_setup_methods (gklass);
2231 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2234 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2235 count = gklass->method.count;
2236 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2238 for (i = 0; i < count; i++) {
2239 methods [i] = mono_class_inflate_generic_method_full_checked (
2240 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2241 if (!mono_error_ok (&error)) {
2242 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2243 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2246 mono_error_cleanup (&error);
2250 } else if (klass->rank) {
2252 MonoMethod *amethod;
2253 MonoMethodSignature *sig;
2254 int count_generic = 0, first_generic = 0;
2256 gboolean jagged_ctor = FALSE;
2258 count = 3 + (klass->rank > 1? 2: 1);
2260 mono_class_setup_interfaces (klass, &error);
2261 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2263 if (klass->rank == 1 && klass->element_class->rank) {
2265 klass->method.count ++;
2268 if (klass->interface_count) {
2269 count_generic = generic_array_methods (klass);
2270 first_generic = count;
2271 count += klass->interface_count * count_generic;
2274 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2276 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2277 sig->ret = &mono_defaults.void_class->byval_arg;
2278 sig->pinvoke = TRUE;
2279 sig->hasthis = TRUE;
2280 for (i = 0; i < klass->rank; ++i)
2281 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2283 amethod = create_array_method (klass, ".ctor", sig);
2284 methods [method_num++] = amethod;
2285 if (klass->rank > 1) {
2286 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2287 sig->ret = &mono_defaults.void_class->byval_arg;
2288 sig->pinvoke = TRUE;
2289 sig->hasthis = TRUE;
2290 for (i = 0; i < klass->rank * 2; ++i)
2291 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2293 amethod = create_array_method (klass, ".ctor", sig);
2294 methods [method_num++] = amethod;
2298 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2299 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2300 sig->ret = &mono_defaults.void_class->byval_arg;
2301 sig->pinvoke = TRUE;
2302 sig->hasthis = TRUE;
2303 for (i = 0; i < klass->rank + 1; ++i)
2304 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2305 amethod = create_array_method (klass, ".ctor", sig);
2306 methods [method_num++] = amethod;
2309 /* element Get (idx11, [idx2, ...]) */
2310 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2311 sig->ret = &klass->element_class->byval_arg;
2312 sig->pinvoke = TRUE;
2313 sig->hasthis = TRUE;
2314 for (i = 0; i < klass->rank; ++i)
2315 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2316 amethod = create_array_method (klass, "Get", sig);
2317 methods [method_num++] = amethod;
2318 /* element& Address (idx11, [idx2, ...]) */
2319 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2320 sig->ret = &klass->element_class->this_arg;
2321 sig->pinvoke = TRUE;
2322 sig->hasthis = TRUE;
2323 for (i = 0; i < klass->rank; ++i)
2324 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2325 amethod = create_array_method (klass, "Address", sig);
2326 methods [method_num++] = amethod;
2327 /* void Set (idx11, [idx2, ...], element) */
2328 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2329 sig->ret = &mono_defaults.void_class->byval_arg;
2330 sig->pinvoke = TRUE;
2331 sig->hasthis = TRUE;
2332 for (i = 0; i < klass->rank; ++i)
2333 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2334 sig->params [i] = &klass->element_class->byval_arg;
2335 amethod = create_array_method (klass, "Set", sig);
2336 methods [method_num++] = amethod;
2338 for (i = 0; i < klass->interface_count; i++)
2339 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2343 count = klass->method.count;
2344 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2345 for (i = 0; i < count; ++i) {
2346 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2347 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2349 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2350 mono_error_cleanup (&error);
2355 if (MONO_CLASS_IS_INTERFACE (klass)) {
2357 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2358 for (i = 0; i < count; ++i) {
2359 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2360 methods [i]->slot = slot++;
2364 mono_image_lock (klass->image);
2366 if (!klass->methods) {
2367 klass->method.count = count;
2369 /* Needed because of the double-checking locking pattern */
2370 mono_memory_barrier ();
2372 klass->methods = methods;
2375 mono_image_unlock (klass->image);
2379 * mono_class_get_method_by_index:
2381 * Returns klass->methods [index], initializing klass->methods if neccesary.
2383 * LOCKING: Acquires the loader lock.
2386 mono_class_get_method_by_index (MonoClass *klass, int index)
2390 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2391 /* Avoid calling setup_methods () if possible */
2392 if (gklass && !klass->methods) {
2395 m = mono_class_inflate_generic_method_full_checked (
2396 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2397 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2399 * If setup_methods () is called later for this class, no duplicates are created,
2400 * since inflate_generic_method guarantees that only one instance of a method
2401 * is created for each context.
2404 mono_class_setup_methods (klass);
2405 g_assert (m == klass->methods [index]);
2409 mono_class_setup_methods (klass);
2410 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2412 g_assert (index >= 0 && index < klass->method.count);
2413 return klass->methods [index];
2418 * mono_class_get_inflated_method:
2420 * Given an inflated class CLASS and a method METHOD which should be a method of
2421 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2424 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2426 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2429 g_assert (method->klass == gklass);
2431 mono_class_setup_methods (gklass);
2432 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2434 for (i = 0; i < gklass->method.count; ++i) {
2435 if (gklass->methods [i] == method) {
2436 if (klass->methods) {
2437 return klass->methods [i];
2440 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2441 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2451 * mono_class_get_vtable_entry:
2453 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2454 * LOCKING: Acquires the loader lock.
2457 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2461 if (klass->rank == 1) {
2463 * szarrays do not overwrite any methods of Array, so we can avoid
2464 * initializing their vtables in some cases.
2466 mono_class_setup_vtable (klass->parent);
2467 if (offset < klass->parent->vtable_size)
2468 return klass->parent->vtable [offset];
2471 if (mono_class_is_ginst (klass)) {
2473 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2474 mono_class_setup_vtable (gklass);
2475 m = gklass->vtable [offset];
2477 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2478 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2480 mono_class_setup_vtable (klass);
2481 if (mono_class_has_failure (klass))
2483 m = klass->vtable [offset];
2490 * mono_class_get_vtable_size:
2492 * Return the vtable size for KLASS.
2495 mono_class_get_vtable_size (MonoClass *klass)
2497 mono_class_setup_vtable (klass);
2499 return klass->vtable_size;
2503 * mono_class_setup_properties:
2505 * Initialize klass->ext.property and klass->ext.properties.
2507 * This method can fail the class.
2510 mono_class_setup_properties (MonoClass *klass)
2512 guint startm, endm, i, j;
2513 guint32 cols [MONO_PROPERTY_SIZE];
2514 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2515 MonoProperty *properties;
2519 if (klass->ext && klass->ext->properties)
2522 if (mono_class_is_ginst (klass)) {
2523 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2525 mono_class_init (gklass);
2526 mono_class_setup_properties (gklass);
2527 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2530 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2532 for (i = 0; i < gklass->ext->property.count; i++) {
2534 MonoProperty *prop = &properties [i];
2536 *prop = gklass->ext->properties [i];
2539 prop->get = mono_class_inflate_generic_method_full_checked (
2540 prop->get, klass, mono_class_get_context (klass), &error);
2542 prop->set = mono_class_inflate_generic_method_full_checked (
2543 prop->set, klass, mono_class_get_context (klass), &error);
2545 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2546 prop->parent = klass;
2549 first = gklass->ext->property.first;
2550 count = gklass->ext->property.count;
2552 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2553 count = last - first;
2556 mono_class_setup_methods (klass);
2557 if (mono_class_has_failure (klass))
2561 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2562 for (i = first; i < last; ++i) {
2563 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2564 properties [i - first].parent = klass;
2565 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2566 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2568 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2569 for (j = startm; j < endm; ++j) {
2572 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2574 if (klass->image->uncompressed_metadata) {
2576 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2577 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2578 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2580 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2583 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2584 case METHOD_SEMANTIC_SETTER:
2585 properties [i - first].set = method;
2587 case METHOD_SEMANTIC_GETTER:
2588 properties [i - first].get = method;
2597 mono_class_alloc_ext (klass);
2599 mono_image_lock (klass->image);
2601 if (klass->ext->properties) {
2602 /* We leak 'properties' which was allocated from the image mempool */
2603 mono_image_unlock (klass->image);
2607 klass->ext->property.first = first;
2608 klass->ext->property.count = count;
2610 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2611 mono_memory_barrier ();
2613 /* Leave this assignment as the last op in the function */
2614 klass->ext->properties = properties;
2616 mono_image_unlock (klass->image);
2620 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2622 MonoMethod **om, **retval;
2625 for (om = methods, count = 0; *om; ++om, ++count)
2628 retval = g_new0 (MonoMethod*, count + 1);
2630 for (om = methods, count = 0; *om; ++om, ++count) {
2632 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2633 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2639 /*This method can fail the class.*/
2641 mono_class_setup_events (MonoClass *klass)
2644 guint startm, endm, i, j;
2645 guint32 cols [MONO_EVENT_SIZE];
2646 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2650 if (klass->ext && klass->ext->events)
2653 if (mono_class_is_ginst (klass)) {
2654 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2655 MonoGenericContext *context = NULL;
2657 mono_class_setup_events (gklass);
2658 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2661 first = gklass->ext->event.first;
2662 count = gklass->ext->event.count;
2664 events = mono_class_new0 (klass, MonoEvent, count);
2667 context = mono_class_get_context (klass);
2669 for (i = 0; i < count; i++) {
2671 MonoEvent *event = &events [i];
2672 MonoEvent *gevent = &gklass->ext->events [i];
2674 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2676 event->parent = klass;
2677 event->name = gevent->name;
2678 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2679 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2680 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2681 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2682 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2683 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2685 #ifndef MONO_SMALL_CONFIG
2686 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2688 event->attrs = gevent->attrs;
2691 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2692 count = last - first;
2695 mono_class_setup_methods (klass);
2696 if (mono_class_has_failure (klass)) {
2701 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2702 for (i = first; i < last; ++i) {
2703 MonoEvent *event = &events [i - first];
2705 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2706 event->parent = klass;
2707 event->attrs = cols [MONO_EVENT_FLAGS];
2708 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2710 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2711 for (j = startm; j < endm; ++j) {
2714 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2716 if (klass->image->uncompressed_metadata) {
2718 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2719 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2720 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2722 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2725 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2726 case METHOD_SEMANTIC_ADD_ON:
2727 event->add = method;
2729 case METHOD_SEMANTIC_REMOVE_ON:
2730 event->remove = method;
2732 case METHOD_SEMANTIC_FIRE:
2733 event->raise = method;
2735 case METHOD_SEMANTIC_OTHER: {
2736 #ifndef MONO_SMALL_CONFIG
2739 if (event->other == NULL) {
2740 event->other = g_new0 (MonoMethod*, 2);
2742 while (event->other [n])
2744 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2746 event->other [n] = method;
2747 /* NULL terminated */
2748 event->other [n + 1] = NULL;
2759 mono_class_alloc_ext (klass);
2761 mono_image_lock (klass->image);
2763 if (klass->ext->events) {
2764 mono_image_unlock (klass->image);
2768 klass->ext->event.first = first;
2769 klass->ext->event.count = count;
2771 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2772 mono_memory_barrier ();
2774 /* Leave this assignment as the last op in the function */
2775 klass->ext->events = events;
2777 mono_image_unlock (klass->image);
2781 * Global pool of interface IDs, represented as a bitset.
2782 * LOCKING: Protected by the classes lock.
2784 static MonoBitSet *global_interface_bitset = NULL;
2787 * mono_unload_interface_ids:
2788 * @bitset: bit set of interface IDs
2790 * When an image is unloaded, the interface IDs associated with
2791 * the image are put back in the global pool of IDs so the numbers
2795 mono_unload_interface_ids (MonoBitSet *bitset)
2798 mono_bitset_sub (global_interface_bitset, bitset);
2803 mono_unload_interface_id (MonoClass *klass)
2805 if (global_interface_bitset && klass->interface_id) {
2807 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2813 * mono_get_unique_iid:
2816 * Assign a unique integer ID to the interface represented by @class.
2817 * The ID will positive and as small as possible.
2818 * LOCKING: Acquires the classes lock.
2819 * Returns: The new ID.
2822 mono_get_unique_iid (MonoClass *klass)
2826 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2830 if (!global_interface_bitset) {
2831 global_interface_bitset = mono_bitset_new (128, 0);
2834 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2836 int old_size = mono_bitset_size (global_interface_bitset);
2837 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2838 mono_bitset_free (global_interface_bitset);
2839 global_interface_bitset = new_set;
2842 mono_bitset_set (global_interface_bitset, iid);
2843 /* set the bit also in the per-image set */
2844 if (!mono_class_is_ginst (klass)) {
2845 if (klass->image->interface_bitset) {
2846 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2847 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2848 mono_bitset_free (klass->image->interface_bitset);
2849 klass->image->interface_bitset = new_set;
2852 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2854 mono_bitset_set (klass->image->interface_bitset, iid);
2859 #ifndef MONO_SMALL_CONFIG
2860 if (mono_print_vtable) {
2862 char *type_name = mono_type_full_name (&klass->byval_arg);
2863 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2864 if (gklass && !gklass->context.class_inst->is_open) {
2865 generic_id = gklass->context.class_inst->id;
2866 g_assert (generic_id != 0);
2870 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2875 g_assert (iid <= 65535);
2880 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2885 mono_class_setup_interfaces (klass, error);
2886 return_if_nok (error);
2888 for (i = 0; i < klass->interface_count; i++) {
2889 ic = klass->interfaces [i];
2892 *res = g_ptr_array_new ();
2893 g_ptr_array_add (*res, ic);
2894 mono_class_init (ic);
2895 if (mono_class_has_failure (ic)) {
2896 mono_error_set_type_load_class (error, ic, "Error Loading class");
2900 collect_implemented_interfaces_aux (ic, res, error);
2901 return_if_nok (error);
2906 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2908 GPtrArray *res = NULL;
2910 collect_implemented_interfaces_aux (klass, &res, error);
2911 if (!mono_error_ok (error)) {
2913 g_ptr_array_free (res, TRUE);
2920 compare_interface_ids (const void *p_key, const void *p_element) {
2921 const MonoClass *key = (const MonoClass *)p_key;
2922 const MonoClass *element = *(const MonoClass **)p_element;
2924 return (key->interface_id - element->interface_id);
2927 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2929 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2930 MonoClass **result = (MonoClass **)mono_binary_search (
2932 klass->interfaces_packed,
2933 klass->interface_offsets_count,
2934 sizeof (MonoClass *),
2935 compare_interface_ids);
2937 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2944 * mono_class_interface_offset_with_variance:
2946 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2947 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2949 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2951 * FIXME figure out MS disambiguation rules and fix this function.
2954 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2955 int i = mono_class_interface_offset (klass, itf);
2956 *non_exact_match = FALSE;
2960 if (!mono_class_has_variant_generic_params (itf))
2963 for (i = 0; i < klass->interface_offsets_count; i++) {
2964 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2965 *non_exact_match = TRUE;
2966 return klass->interface_offsets_packed [i];
2974 print_implemented_interfaces (MonoClass *klass) {
2977 GPtrArray *ifaces = NULL;
2979 int ancestor_level = 0;
2981 name = mono_type_get_full_name (klass);
2982 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2985 for (i = 0; i < klass->interface_offsets_count; i++)
2986 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2987 klass->interfaces_packed [i]->interface_id,
2988 klass->interface_offsets_packed [i],
2989 klass->interfaces_packed [i]->method.count,
2990 klass->interfaces_packed [i]->name_space,
2991 klass->interfaces_packed [i]->name );
2992 printf ("Interface flags: ");
2993 for (i = 0; i <= klass->max_interface_id; i++)
2994 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2995 printf ("(%d,T)", i);
2997 printf ("(%d,F)", i);
2999 printf ("Dump interface flags:");
3000 #ifdef COMPRESSED_INTERFACE_BITMAP
3002 const uint8_t* p = klass->interface_bitmap;
3003 i = klass->max_interface_id;
3005 printf (" %d x 00 %02X", p [0], p [1]);
3011 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3012 printf (" %02X", klass->interface_bitmap [i]);
3015 while (klass != NULL) {
3016 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3017 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3018 if (!mono_error_ok (&error)) {
3019 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3020 mono_error_cleanup (&error);
3021 } else if (ifaces) {
3022 for (i = 0; i < ifaces->len; i++) {
3023 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3024 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3025 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3027 mono_class_interface_offset (klass, ic),
3032 g_ptr_array_free (ifaces, TRUE);
3035 klass = klass->parent;
3040 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3043 args [0] = &arg0->byval_arg;
3045 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3049 array_class_get_if_rank (MonoClass *klass, guint rank)
3051 return rank ? mono_array_class_get (klass, rank) : klass;
3055 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3057 valuetype_types [0] = eclass;
3058 if (eclass == mono_defaults.int16_class)
3059 valuetype_types [1] = mono_defaults.uint16_class;
3060 else if (eclass == mono_defaults.uint16_class)
3061 valuetype_types [1] = mono_defaults.int16_class;
3062 else if (eclass == mono_defaults.int32_class)
3063 valuetype_types [1] = mono_defaults.uint32_class;
3064 else if (eclass == mono_defaults.uint32_class)
3065 valuetype_types [1] = mono_defaults.int32_class;
3066 else if (eclass == mono_defaults.int64_class)
3067 valuetype_types [1] = mono_defaults.uint64_class;
3068 else if (eclass == mono_defaults.uint64_class)
3069 valuetype_types [1] = mono_defaults.int64_class;
3070 else if (eclass == mono_defaults.byte_class)
3071 valuetype_types [1] = mono_defaults.sbyte_class;
3072 else if (eclass == mono_defaults.sbyte_class)
3073 valuetype_types [1] = mono_defaults.byte_class;
3074 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3075 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3078 static GENERATE_GET_CLASS_WITH_CACHE (generic_icollection, System.Collections.Generic, ICollection`1)
3079 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerable, System.Collections.Generic, IEnumerable`1)
3080 static GENERATE_GET_CLASS_WITH_CACHE (generic_ienumerator, System.Collections.Generic, IEnumerator`1)
3081 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlylist, System.Collections.Generic, IReadOnlyList`1)
3082 static GENERATE_GET_CLASS_WITH_CACHE (generic_ireadonlycollection, System.Collections.Generic, IReadOnlyCollection`1)
3084 /* this won't be needed once bug #325495 is completely fixed
3085 * though we'll need something similar to know which interfaces to allow
3086 * in arrays when they'll be lazyly created
3088 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3089 * MS returns diferrent types based on which instance is called. For example:
3090 * object obj = new byte[10][];
3091 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3092 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3095 * Fixing this should kill quite some code, save some bits and improve compatibility.
3098 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3100 MonoClass *eclass = klass->element_class;
3101 MonoClass* generic_icollection_class;
3102 MonoClass* generic_ienumerable_class;
3103 MonoClass* generic_ienumerator_class;
3104 MonoClass* generic_ireadonlylist_class;
3105 MonoClass* generic_ireadonlycollection_class;
3106 MonoClass *valuetype_types[2] = { NULL, NULL };
3107 MonoClass **interfaces = NULL;
3108 int i, nifaces, interface_count, real_count, original_rank;
3110 gboolean internal_enumerator;
3111 gboolean eclass_is_valuetype;
3113 if (!mono_defaults.generic_ilist_class) {
3117 internal_enumerator = FALSE;
3118 eclass_is_valuetype = FALSE;
3119 original_rank = eclass->rank;
3120 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3121 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
3122 if (gklass && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3124 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3126 eclass = mono_class_from_mono_type (gklass->context.class_inst->type_argv [0]);
3127 original_rank = eclass->rank;
3129 eclass = eclass->element_class;
3130 internal_enumerator = TRUE;
3131 *is_enumerator = TRUE;
3139 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3140 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3142 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3144 generic_icollection_class = mono_class_get_generic_icollection_class ();
3145 generic_ienumerable_class = mono_class_get_generic_ienumerable_class ();
3146 generic_ienumerator_class = mono_class_get_generic_ienumerator_class ();
3147 generic_ireadonlylist_class = mono_class_get_generic_ireadonlylist_class ();
3148 generic_ireadonlycollection_class = mono_class_get_generic_ireadonlycollection_class ();
3150 mono_class_init (eclass);
3153 * Arrays in 2.0 need to implement a number of generic interfaces
3154 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3155 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3156 * We collect the types needed to build the
3157 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3158 * the generic interfaces needed to implement.
3160 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3161 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3163 if (eclass->valuetype) {
3164 nifaces = generic_ireadonlylist_class ? 5 : 3;
3165 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3167 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3168 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3169 if (internal_enumerator) {
3171 if (valuetype_types [1])
3175 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3176 interfaces [0] = valuetype_types [0];
3177 if (valuetype_types [1])
3178 interfaces [nifaces] = valuetype_types [1];
3180 eclass_is_valuetype = TRUE;
3183 int idepth = eclass->idepth;
3184 if (!internal_enumerator)
3186 nifaces = generic_ireadonlylist_class ? 2 : 3;
3188 // FIXME: This doesn't seem to work/required for generic params
3189 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3190 mono_class_setup_interface_offsets (eclass);
3192 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3193 /* we add object for interfaces and the supertypes for the other
3194 * types. The last of the supertypes is the element class itself which we
3195 * already created the explicit interfaces for (so we include it for IEnumerator
3196 * and exclude it for arrays).
3198 if (MONO_CLASS_IS_INTERFACE (eclass))
3201 interface_count += idepth;
3202 if (eclass->rank && eclass->element_class->valuetype) {
3203 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3204 if (valuetype_types [1])
3207 /* IList, ICollection, IEnumerable, IReadOnlyList */
3208 interface_count *= nifaces;
3209 real_count = interface_count;
3210 if (internal_enumerator) {
3211 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3212 if (valuetype_types [1])
3215 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3216 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3217 interfaces [0] = mono_defaults.object_class;
3221 for (i = 0; i < idepth; i++) {
3222 mono_class_init (eclass->supertypes [i]);
3223 interfaces [j] = eclass->supertypes [i];
3227 if (all_interfaces) {
3228 for (i = 0; i < eclass->interface_offsets_count; i++) {
3229 interfaces [j] = eclass->interfaces_packed [i];
3233 for (i = 0; i < eclass->interface_count; i++) {
3234 interfaces [j] = eclass->interfaces [i];
3238 if (valuetype_types [1]) {
3239 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3244 /* instantiate the generic interfaces */
3245 for (i = 0; i < interface_count; i += nifaces) {
3246 MonoClass *iface = interfaces [i];
3248 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3249 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3251 if (eclass->valuetype) {
3252 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3253 if (generic_ireadonlylist_class) {
3254 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3255 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3258 if (!generic_ireadonlylist_class)
3259 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3262 if (internal_enumerator) {
3264 /* instantiate IEnumerator<iface> */
3265 for (i = 0; i < interface_count; i++) {
3266 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3268 j = interface_count;
3269 if (!eclass_is_valuetype) {
3270 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3271 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3274 for (i = 0; i < eclass->idepth; i++) {
3275 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3279 for (i = 0; i < eclass->interface_offsets_count; i++) {
3280 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3284 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3286 if (valuetype_types [1])
3287 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3291 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3292 for (i = 0; i < real_count; ++i) {
3293 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3294 g_print ("%s implements %s\n", type_name, name);
3305 find_array_interface (MonoClass *klass, const char *name)
3308 for (i = 0; i < klass->interface_count; ++i) {
3309 if (strcmp (klass->interfaces [i]->name, name) == 0)
3316 * Return the number of virtual methods.
3317 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3318 * Return -1 on failure.
3319 * FIXME It would be nice if this information could be cached somewhere.
3322 count_virtual_methods (MonoClass *klass)
3326 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3328 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3329 mono_class_setup_methods (klass);
3330 if (mono_class_has_failure (klass))
3333 for (i = 0; i < klass->method.count; ++i) {
3334 flags = klass->methods [i]->flags;
3335 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3339 for (i = 0; i < klass->method.count; ++i) {
3340 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3342 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3350 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3358 m = (l + num_ifaces) / 2;
3359 if (interfaces_full [m] == ic)
3361 if (l == num_ifaces)
3363 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3372 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3374 int i = find_interface (num_ifaces, interfaces_full, ic);
3376 return interface_offsets_full [i];
3381 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3383 int i = find_interface (num_ifaces, interfaces_full, ic);
3387 interface_offsets_full [i] = offset;
3390 for (i = 0; i < num_ifaces; ++i) {
3391 if (interfaces_full [i]) {
3393 if (interfaces_full [i]->interface_id < ic->interface_id)
3396 while (end < num_ifaces && interfaces_full [end]) end++;
3397 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3398 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3400 interfaces_full [i] = ic;
3401 interface_offsets_full [i] = offset;
3407 #ifdef COMPRESSED_INTERFACE_BITMAP
3410 * Compressed interface bitmap design.
3412 * Interface bitmaps take a large amount of memory, because their size is
3413 * linear with the maximum interface id assigned in the process (each interface
3414 * is assigned a unique id as it is loaded). The number of interface classes
3415 * is high because of the many implicit interfaces implemented by arrays (we'll
3416 * need to lazy-load them in the future).
3417 * Most classes implement a very small number of interfaces, so the bitmap is
3418 * sparse. This bitmap needs to be checked by interface casts, so access to the
3419 * needed bit must be fast and doable with few jit instructions.
3421 * The current compression format is as follows:
3422 * *) it is a sequence of one or more two-byte elements
3423 * *) the first byte in the element is the count of empty bitmap bytes
3424 * at the current bitmap position
3425 * *) the second byte in the element is an actual bitmap byte at the current
3428 * As an example, the following compressed bitmap bytes:
3429 * 0x07 0x01 0x00 0x7
3430 * correspond to the following bitmap:
3431 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3433 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3434 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3435 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3439 * mono_compress_bitmap:
3440 * @dest: destination buffer
3441 * @bitmap: bitmap buffer
3442 * @size: size of @bitmap in bytes
3444 * This is a mono internal function.
3445 * The @bitmap data is compressed into a format that is small but
3446 * still searchable in few instructions by the JIT and runtime.
3447 * The compressed data is stored in the buffer pointed to by the
3448 * @dest array. Passing a #NULL value for @dest allows to just compute
3449 * the size of the buffer.
3450 * This compression algorithm assumes the bits set in the bitmap are
3451 * few and far between, like in interface bitmaps.
3452 * Returns: The size of the compressed bitmap in bytes.
3455 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3459 const uint8_t *end = bitmap + size;
3460 while (bitmap < end) {
3461 if (*bitmap || numz == 255) {
3485 * mono_class_interface_match:
3486 * @bitmap: a compressed bitmap buffer
3487 * @id: the index to check in the bitmap
3489 * This is a mono internal function.
3490 * Checks if a bit is set in a compressed interface bitmap. @id must
3491 * be already checked for being smaller than the maximum id encoded in the
3494 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3498 mono_class_interface_match (const uint8_t *bitmap, int id)
3501 id -= bitmap [0] * 8;
3505 return bitmap [1] & (1 << id);
3514 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3515 * LOCKING: Acquires the loader lock.
3518 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3522 int i, j, max_iid, num_ifaces;
3523 MonoClass **interfaces_full = NULL;
3524 int *interface_offsets_full = NULL;
3526 GPtrArray **ifaces_array = NULL;
3527 int interface_offsets_count;
3528 MonoClass **array_interfaces = NULL;
3529 int num_array_interfaces;
3530 int is_enumerator = FALSE;
3532 mono_class_setup_supertypes (klass);
3534 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3535 * implicit interfaces have the property that they are assigned the same slot in the
3536 * vtables for compatible interfaces
3538 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3540 /* compute maximum number of slots and maximum interface id */
3542 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3543 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3544 for (j = 0; j < klass->idepth; j++) {
3545 k = klass->supertypes [j];
3546 num_ifaces += k->interface_count;
3547 for (i = 0; i < k->interface_count; i++) {
3548 ic = k->interfaces [i];
3550 mono_class_init (ic);
3552 if (max_iid < ic->interface_id)
3553 max_iid = ic->interface_id;
3555 ifaces = mono_class_get_implemented_interfaces (k, &error);
3556 if (!mono_error_ok (&error)) {
3557 char *name = mono_type_get_full_name (k);
3558 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3560 mono_error_cleanup (&error);
3565 num_ifaces += ifaces->len;
3566 for (i = 0; i < ifaces->len; ++i) {
3567 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3568 if (max_iid < ic->interface_id)
3569 max_iid = ic->interface_id;
3571 ifaces_array [j] = ifaces;
3575 for (i = 0; i < num_array_interfaces; ++i) {
3576 ic = array_interfaces [i];
3577 mono_class_init (ic);
3578 if (max_iid < ic->interface_id)
3579 max_iid = ic->interface_id;
3582 if (MONO_CLASS_IS_INTERFACE (klass)) {
3584 if (max_iid < klass->interface_id)
3585 max_iid = klass->interface_id;
3588 /* compute vtable offset for interfaces */
3589 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3590 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3592 for (i = 0; i < num_ifaces; i++)
3593 interface_offsets_full [i] = -1;
3595 /* skip the current class */
3596 for (j = 0; j < klass->idepth - 1; j++) {
3597 k = klass->supertypes [j];
3598 ifaces = ifaces_array [j];
3601 for (i = 0; i < ifaces->len; ++i) {
3603 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3605 /*Force the sharing of interface offsets between parent and subtypes.*/
3606 io = mono_class_interface_offset (k, ic);
3608 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3613 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3614 ifaces = ifaces_array [klass->idepth - 1];
3616 for (i = 0; i < ifaces->len; ++i) {
3618 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3619 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3621 count = count_virtual_methods (ic);
3623 char *name = mono_type_get_full_name (ic);
3624 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3633 if (MONO_CLASS_IS_INTERFACE (klass))
3634 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3636 if (num_array_interfaces) {
3637 if (is_enumerator) {
3638 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3639 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3640 g_assert (ienumerator_offset >= 0);
3641 for (i = 0; i < num_array_interfaces; ++i) {
3642 ic = array_interfaces [i];
3643 if (strcmp (ic->name, "IEnumerator`1") == 0)
3644 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3646 g_assert_not_reached ();
3647 /*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);*/
3650 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3651 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3652 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3653 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3654 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3655 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3656 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3657 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3658 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3659 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3660 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3661 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3662 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3663 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3664 for (i = 0; i < num_array_interfaces; ++i) {
3666 ic = array_interfaces [i];
3667 if (mono_class_get_generic_class (ic)->container_class == mono_defaults.generic_ilist_class)
3668 offset = ilist_offset;
3669 else if (strcmp (ic->name, "ICollection`1") == 0)
3670 offset = icollection_offset;
3671 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3672 offset = ienumerable_offset;
3673 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3674 offset = ireadonlylist_offset;
3675 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3676 offset = ireadonlycollection_offset;
3678 g_assert_not_reached ();
3679 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3680 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3685 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3686 if (interface_offsets_full [i] != -1)
3687 interface_offsets_count ++;
3690 /* Publish the data */
3691 mono_loader_lock ();
3693 klass->max_interface_id = max_iid;
3695 * We might get called multiple times:
3696 * - mono_class_init ()
3697 * - mono_class_setup_vtable ().
3698 * - mono_class_setup_interface_offsets ().
3699 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3700 * means we have to overwrite those when called from other places (#4440).
3702 if (klass->interfaces_packed) {
3704 g_assert (klass->interface_offsets_count == interface_offsets_count);
3708 klass->interface_offsets_count = interface_offsets_count;
3709 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3710 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3711 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3712 #ifdef COMPRESSED_INTERFACE_BITMAP
3713 bitmap = g_malloc0 (bsize);
3715 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3717 for (i = 0; i < interface_offsets_count; i++) {
3718 int id = interfaces_full [i]->interface_id;
3719 bitmap [id >> 3] |= (1 << (id & 7));
3720 klass->interfaces_packed [i] = interfaces_full [i];
3721 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3722 /*if (num_array_interfaces)
3723 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]);*/
3725 #ifdef COMPRESSED_INTERFACE_BITMAP
3726 i = mono_compress_bitmap (NULL, bitmap, bsize);
3727 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3728 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3731 klass->interface_bitmap = bitmap;
3734 mono_loader_unlock ();
3737 g_free (interfaces_full);
3738 g_free (interface_offsets_full);
3739 g_free (array_interfaces);
3740 for (i = 0; i < klass->idepth; i++) {
3741 ifaces = ifaces_array [i];
3743 g_ptr_array_free (ifaces, TRUE);
3745 g_free (ifaces_array);
3747 //printf ("JUST DONE: ");
3748 //print_implemented_interfaces (klass);
3754 * Setup interface offsets for interfaces.
3756 * - klass->max_interface_id
3757 * - klass->interface_offsets_count
3758 * - klass->interfaces_packed
3759 * - klass->interface_offsets_packed
3760 * - klass->interface_bitmap
3762 * This function can fail @class.
3765 mono_class_setup_interface_offsets (MonoClass *klass)
3767 setup_interface_offsets (klass, 0, FALSE);
3770 /*Checks if @klass has @parent as one of it's parents type gtd
3774 * Bar<T> : Foo<Bar<Bar<T>>>
3778 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3780 klass = mono_class_get_generic_type_definition (klass);
3781 parent = mono_class_get_generic_type_definition (parent);
3782 mono_class_setup_supertypes (klass);
3783 mono_class_setup_supertypes (parent);
3785 return klass->idepth >= parent->idepth &&
3786 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3790 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3792 MonoGenericInst *ginst;
3795 if (!mono_class_is_ginst (klass)) {
3796 mono_class_setup_vtable_full (klass, in_setup);
3797 return !mono_class_has_failure (klass);
3800 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3801 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3804 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3805 for (i = 0; i < ginst->type_argc; ++i) {
3807 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3809 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3810 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3811 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3813 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3814 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3822 * mono_class_setup_vtable:
3824 * Creates the generic vtable of CLASS.
3825 * Initializes the following fields in MonoClass:
3828 * Plus all the fields initialized by setup_interface_offsets ().
3829 * If there is an error during vtable construction, klass->has_failure
3830 * is set and details are stored in a MonoErrorBoxed.
3832 * LOCKING: Acquires the loader lock.
3835 mono_class_setup_vtable (MonoClass *klass)
3837 mono_class_setup_vtable_full (klass, NULL);
3841 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3844 MonoMethod **overrides;
3845 MonoGenericContext *context;
3853 if (MONO_CLASS_IS_INTERFACE (klass)) {
3854 /* This sets method->slot for all methods if this is an interface */
3855 mono_class_setup_methods (klass);
3859 if (mono_class_has_failure (klass))
3862 if (g_list_find (in_setup, klass))
3865 mono_loader_lock ();
3867 if (klass->vtable) {
3868 mono_loader_unlock ();
3872 mono_stats.generic_vtable_count ++;
3873 in_setup = g_list_prepend (in_setup, klass);
3875 if (mono_class_is_ginst (klass)) {
3876 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3877 mono_loader_unlock ();
3878 g_list_remove (in_setup, klass);
3882 context = mono_class_get_context (klass);
3883 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3885 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3886 type_token = klass->type_token;
3889 if (image_is_dynamic (klass->image)) {
3890 /* Generic instances can have zero method overrides without causing any harm.
3891 * This is true since we don't do layout all over again for them, we simply inflate
3892 * the layout of the parent.
3894 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3895 if (!is_ok (&error)) {
3896 mono_loader_unlock ();
3897 g_list_remove (in_setup, klass);
3898 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3899 mono_error_cleanup (&error);
3903 /* The following call fails if there are missing methods in the type */
3904 /* FIXME it's probably a good idea to avoid this for generic instances. */
3905 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3909 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3911 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3915 mono_loader_unlock ();
3916 g_list_remove (in_setup, klass);
3921 #define DEBUG_INTERFACE_VTABLE_CODE 0
3922 #define TRACE_INTERFACE_VTABLE_CODE 0
3923 #define VERIFY_INTERFACE_VTABLE_CODE 0
3924 #define VTABLE_SELECTOR (1)
3926 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3927 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3928 if (!(VTABLE_SELECTOR)) break; \
3932 #define DEBUG_INTERFACE_VTABLE(stmt)
3935 #if TRACE_INTERFACE_VTABLE_CODE
3936 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3937 if (!(VTABLE_SELECTOR)) break; \
3941 #define TRACE_INTERFACE_VTABLE(stmt)
3944 #if VERIFY_INTERFACE_VTABLE_CODE
3945 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3946 if (!(VTABLE_SELECTOR)) break; \
3950 #define VERIFY_INTERFACE_VTABLE(stmt)
3954 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3956 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3960 GString *res = g_string_new ("");
3962 g_string_append_c (res, '(');
3963 for (i = 0; i < sig->param_count; ++i) {
3965 g_string_append_c (res, ',');
3966 mono_type_get_desc (res, sig->params [i], include_namespace);
3968 g_string_append (res, ")=>");
3969 if (sig->ret != NULL) {
3970 mono_type_get_desc (res, sig->ret, include_namespace);
3972 g_string_append (res, "NULL");
3975 g_string_free (res, FALSE);
3979 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3980 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3981 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3982 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3990 is_wcf_hack_disabled (void)
3992 static gboolean disabled;
3993 static gboolean inited = FALSE;
3995 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
4002 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
4004 MonoMethodSignature *cmsig, *imsig;
4005 if (strcmp (im->name, cm->name) == 0) {
4006 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
4007 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
4010 if (! slot_is_empty) {
4011 if (require_newslot) {
4012 if (! interface_is_explicitly_implemented_by_class) {
4013 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
4016 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4017 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
4021 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
4024 cmsig = mono_method_signature (cm);
4025 imsig = mono_method_signature (im);
4026 if (!cmsig || !imsig) {
4027 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4031 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4032 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
4033 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4034 TRACE_INTERFACE_VTABLE (printf ("]"));
4037 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4038 if (mono_security_core_clr_enabled ())
4039 mono_security_core_clr_check_override (klass, cm, im);
4041 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4042 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4043 char *body_name = mono_method_full_name (cm, TRUE);
4044 char *decl_name = mono_method_full_name (im, TRUE);
4045 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4053 MonoClass *ic = im->klass;
4054 const char *ic_name_space = ic->name_space;
4055 const char *ic_name = ic->name;
4058 if (! require_newslot) {
4059 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4062 if (cm->klass->rank == 0) {
4063 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4066 cmsig = mono_method_signature (cm);
4067 imsig = mono_method_signature (im);
4068 if (!cmsig || !imsig) {
4069 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
4073 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4074 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4075 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4076 TRACE_INTERFACE_VTABLE (printf ("]"));
4079 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4080 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4083 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4084 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4087 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))) {
4088 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4092 subname = strstr (cm->name, ic_name_space);
4093 if (subname != cm->name) {
4094 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4097 subname += strlen (ic_name_space);
4098 if (subname [0] != '.') {
4099 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4103 if (strstr (subname, ic_name) != subname) {
4104 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4107 subname += strlen (ic_name);
4108 if (subname [0] != '.') {
4109 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4113 if (strcmp (subname, im->name) != 0) {
4114 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4118 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4119 if (mono_security_core_clr_enabled ())
4120 mono_security_core_clr_check_override (klass, cm, im);
4122 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4123 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4124 char *body_name = mono_method_full_name (cm, TRUE);
4125 char *decl_name = mono_method_full_name (im, TRUE);
4126 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4136 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4138 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4139 MonoMethod *method = key;
4140 MonoMethod *override = value;
4141 MonoClass *method_class = mono_method_get_class (method);
4142 MonoClass *override_class = mono_method_get_class (override);
4144 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4145 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4146 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4149 print_overrides (GHashTable *override_map, const char *message) {
4151 printf ("Override map \"%s\" START:\n", message);
4152 g_hash_table_foreach (override_map, foreach_override, NULL);
4153 printf ("Override map \"%s\" END.\n", message);
4155 printf ("Override map \"%s\" EMPTY.\n", message);
4159 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4160 char *full_name = mono_type_full_name (&klass->byval_arg);
4164 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4166 if (print_interfaces) {
4167 print_implemented_interfaces (klass);
4168 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4171 if (klass->parent) {
4172 parent_size = klass->parent->vtable_size;
4176 for (i = 0; i < size; ++i) {
4177 MonoMethod *cm = vtable [i];
4178 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4179 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4181 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4189 #if VERIFY_INTERFACE_VTABLE_CODE
4191 mono_method_try_get_vtable_index (MonoMethod *method)
4193 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4194 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4195 if (imethod->declaring->is_generic)
4196 return imethod->declaring->slot;
4198 return method->slot;
4202 mono_class_verify_vtable (MonoClass *klass)
4205 char *full_name = mono_type_full_name (&klass->byval_arg);
4207 printf ("*** Verifying VTable of class '%s' \n", full_name);
4211 if (!klass->methods)
4214 for (i = 0; i < klass->method.count; ++i) {
4215 MonoMethod *cm = klass->methods [i];
4218 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4222 full_name = mono_method_full_name (cm, TRUE);
4224 slot = mono_method_try_get_vtable_index (cm);
4226 if (slot >= klass->vtable_size) {
4227 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4231 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4232 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4233 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4234 g_free (other_name);
4237 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4244 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4246 char *method_signature;
4249 for (index = 0; index < onum; ++index) {
4250 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4251 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4253 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4254 type_name = mono_type_full_name (&klass->byval_arg);
4255 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4256 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4257 g_free (method_signature);
4259 mono_class_setup_methods (klass);
4260 if (mono_class_has_failure (klass)) {
4261 char *name = mono_type_get_full_name (klass);
4262 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4266 for (index = 0; index < klass->method.count; ++index) {
4267 MonoMethod *cm = klass->methods [index];
4268 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4270 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4271 g_free (method_signature);
4276 mono_method_get_method_definition (MonoMethod *method)
4278 while (method->is_inflated)
4279 method = ((MonoMethodInflated*)method)->declaring;
4284 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4288 for (i = 0; i < onum; ++i) {
4289 MonoMethod *decl = overrides [i * 2];
4290 MonoMethod *body = overrides [i * 2 + 1];
4292 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4293 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4297 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4298 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4299 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4301 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4305 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4306 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4307 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4309 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4313 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4314 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4318 body = mono_method_get_method_definition (body);
4319 decl = mono_method_get_method_definition (decl);
4321 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4322 char *body_name = mono_method_full_name (body, TRUE);
4323 char *decl_name = mono_method_full_name (decl, TRUE);
4324 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4334 mono_class_need_stelemref_method (MonoClass *klass)
4336 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4340 * LOCKING: this is supposed to be called with the loader lock held.
4343 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4347 MonoMethod **vtable;
4348 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4349 GPtrArray *ifaces = NULL;
4350 GHashTable *override_map = NULL;
4352 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4353 int first_non_interface_slot;
4355 GSList *virt_methods = NULL, *l;
4356 int stelemref_slot = 0;
4361 if (overrides && !verify_class_overrides (klass, overrides, onum))
4364 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4365 if (!mono_error_ok (&error)) {
4366 char *name = mono_type_get_full_name (klass);
4367 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4369 mono_error_cleanup (&error);
4371 } else if (ifaces) {
4372 for (i = 0; i < ifaces->len; i++) {
4373 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4374 max_vtsize += ic->method.count;
4376 g_ptr_array_free (ifaces, TRUE);
4380 if (klass->parent) {
4381 mono_class_init (klass->parent);
4382 mono_class_setup_vtable_full (klass->parent, in_setup);
4384 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4387 max_vtsize += klass->parent->vtable_size;
4388 cur_slot = klass->parent->vtable_size;
4391 max_vtsize += klass->method.count;
4393 /*Array have a slot for stelemref*/
4394 if (mono_class_need_stelemref_method (klass)) {
4395 stelemref_slot = cur_slot;
4400 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4401 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4403 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4405 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4406 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4409 max_iid = klass->max_interface_id;
4410 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4412 /* Optimized version for generic instances */
4413 if (mono_class_is_ginst (klass)) {
4415 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4418 mono_class_setup_vtable_full (gklass, in_setup);
4419 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4422 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4423 klass->vtable_size = gklass->vtable_size;
4424 for (i = 0; i < gklass->vtable_size; ++i)
4425 if (gklass->vtable [i]) {
4426 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4427 if (!mono_error_ok (&error)) {
4428 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4429 mono_error_cleanup (&error);
4433 tmp [i]->slot = gklass->vtable [i]->slot;
4435 mono_memory_barrier ();
4436 klass->vtable = tmp;
4438 /* Have to set method->slot for abstract virtual methods */
4439 if (klass->methods && gklass->methods) {
4440 for (i = 0; i < klass->method.count; ++i)
4441 if (klass->methods [i]->slot == -1)
4442 klass->methods [i]->slot = gklass->methods [i]->slot;
4448 if (klass->parent && klass->parent->vtable_size) {
4449 MonoClass *parent = klass->parent;
4452 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4454 // Also inherit parent interface vtables, just as a starting point.
4455 // This is needed otherwise bug-77127.exe fails when the property methods
4456 // have different names in the iterface and the class, because for child
4457 // classes the ".override" information is not used anymore.
4458 for (i = 0; i < parent->interface_offsets_count; i++) {
4459 MonoClass *parent_interface = parent->interfaces_packed [i];
4460 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4461 /*FIXME this is now dead code as this condition will never hold true.
4462 Since interface offsets are inherited then the offset of an interface implemented
4463 by a parent will never be the out of it's vtable boundary.
4465 if (interface_offset >= parent->vtable_size) {
4466 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4469 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4470 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4471 for (j = 0; j < parent_interface->method.count && !mono_class_has_failure (klass); j++) {
4472 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4473 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4474 parent_interface_offset + j, parent_interface_offset, j,
4475 interface_offset + j, interface_offset, j));
4482 /*Array have a slot for stelemref*/
4483 if (mono_class_need_stelemref_method (klass)) {
4484 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4486 method->slot = stelemref_slot;
4488 g_assert (method->slot == stelemref_slot);
4490 vtable [stelemref_slot] = method;
4493 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4494 /* override interface methods */
4495 for (i = 0; i < onum; i++) {
4496 MonoMethod *decl = overrides [i*2];
4497 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4499 dslot = mono_method_get_vtable_slot (decl);
4501 mono_class_set_type_load_failure (klass, "");
4505 dslot += mono_class_interface_offset (klass, decl->klass);
4506 vtable [dslot] = overrides [i*2 + 1];
4507 vtable [dslot]->slot = dslot;
4509 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4511 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4513 if (mono_security_core_clr_enabled ())
4514 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4517 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4518 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4521 * Create a list of virtual methods to avoid calling
4522 * mono_class_get_virtual_methods () which is slow because of the metadata
4526 gpointer iter = NULL;
4529 virt_methods = NULL;
4530 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4531 virt_methods = g_slist_prepend (virt_methods, cm);
4533 if (mono_class_has_failure (klass))
4537 // Loop on all implemented interfaces...
4538 for (i = 0; i < klass->interface_offsets_count; i++) {
4539 MonoClass *parent = klass->parent;
4541 gboolean interface_is_explicitly_implemented_by_class;
4544 ic = klass->interfaces_packed [i];
4545 ic_offset = mono_class_interface_offset (klass, ic);
4547 mono_class_setup_methods (ic);
4548 if (mono_class_has_failure (ic))
4551 // Check if this interface is explicitly implemented (instead of just inherited)
4552 if (parent != NULL) {
4553 int implemented_interfaces_index;
4554 interface_is_explicitly_implemented_by_class = FALSE;
4555 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4556 if (ic == klass->interfaces [implemented_interfaces_index]) {
4557 interface_is_explicitly_implemented_by_class = TRUE;
4562 interface_is_explicitly_implemented_by_class = TRUE;
4565 // Loop on all interface methods...
4566 for (im_index = 0; im_index < ic->method.count; im_index++) {
4567 MonoMethod *im = ic->methods [im_index];
4568 int im_slot = ic_offset + im->slot;
4569 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4571 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4574 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4576 // If there is an explicit implementation, just use it right away,
4577 // otherwise look for a matching method
4578 if (override_im == NULL) {
4582 // First look for a suitable method among the class methods
4583 for (l = virt_methods; l; l = l->next) {
4584 cm = (MonoMethod *)l->data;
4585 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)));
4586 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4587 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4588 vtable [im_slot] = cm;
4589 /* Why do we need this? */
4594 TRACE_INTERFACE_VTABLE (printf ("\n"));
4595 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4599 // If the slot is still empty, look in all the inherited virtual methods...
4600 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4601 MonoClass *parent = klass->parent;
4602 // Reverse order, so that last added methods are preferred
4603 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4604 MonoMethod *cm = parent->vtable [cm_index];
4606 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));
4607 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4608 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4609 vtable [im_slot] = cm;
4610 /* Why do we need this? */
4616 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4618 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4622 g_assert (vtable [im_slot] == override_im);
4627 // If the class is not abstract, check that all its interface slots are full.
4628 // The check is done here and not directly at the end of the loop above because
4629 // it can happen (for injected generic array interfaces) that the same slot is
4630 // processed multiple times (those interfaces have overlapping slots), and it
4631 // will not always be the first pass the one that fills the slot.
4632 if (! (mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT)) {
4633 for (i = 0; i < klass->interface_offsets_count; i++) {
4637 ic = klass->interfaces_packed [i];
4638 ic_offset = mono_class_interface_offset (klass, ic);
4640 for (im_index = 0; im_index < ic->method.count; im_index++) {
4641 MonoMethod *im = ic->methods [im_index];
4642 int im_slot = ic_offset + im->slot;
4644 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4647 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4648 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4649 if (vtable [im_slot] == NULL) {
4650 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4657 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4658 for (l = virt_methods; l; l = l->next) {
4659 cm = (MonoMethod *)l->data;
4661 * If the method is REUSE_SLOT, we must check in the
4662 * base class for a method to override.
4664 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4666 for (k = klass->parent; k ; k = k->parent) {
4671 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4672 MonoMethodSignature *cmsig, *m1sig;
4674 cmsig = mono_method_signature (cm);
4675 m1sig = mono_method_signature (m1);
4677 if (!cmsig || !m1sig) {
4678 /* FIXME proper error message */
4679 mono_class_set_type_load_failure (klass, "");
4683 if (!strcmp(cm->name, m1->name) &&
4684 mono_metadata_signature_equal (cmsig, m1sig)) {
4686 if (mono_security_core_clr_enabled ())
4687 mono_security_core_clr_check_override (klass, cm, m1);
4689 slot = mono_method_get_vtable_slot (m1);
4693 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4694 char *body_name = mono_method_full_name (cm, TRUE);
4695 char *decl_name = mono_method_full_name (m1, TRUE);
4696 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4702 g_assert (cm->slot < max_vtsize);
4704 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4705 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4706 mono_method_full_name (m1, 1), m1,
4707 mono_method_full_name (cm, 1), cm));
4708 g_hash_table_insert (override_map, m1, cm);
4712 if (mono_class_has_failure (k))
4722 /*Non final newslot methods must be given a non-interface vtable slot*/
4723 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4727 cm->slot = cur_slot++;
4729 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4730 vtable [cm->slot] = cm;
4733 /* override non interface methods */
4734 for (i = 0; i < onum; i++) {
4735 MonoMethod *decl = overrides [i*2];
4736 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4737 g_assert (decl->slot != -1);
4738 vtable [decl->slot] = overrides [i*2 + 1];
4739 overrides [i * 2 + 1]->slot = decl->slot;
4741 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4742 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4743 mono_method_full_name (decl, 1), decl,
4744 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4745 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4747 if (mono_security_core_clr_enabled ())
4748 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4753 * If a method occupies more than one place in the vtable, and it is
4754 * overriden, then change the other occurances too.
4759 for (i = 0; i < max_vtsize; ++i)
4761 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4763 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4768 g_hash_table_destroy (override_map);
4769 override_map = NULL;
4772 g_slist_free (virt_methods);
4773 virt_methods = NULL;
4775 /* Ensure that all vtable slots are filled with concrete instance methods */
4776 if (!(mono_class_get_flags (klass) & TYPE_ATTRIBUTE_ABSTRACT)) {
4777 for (i = 0; i < cur_slot; ++i) {
4778 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4779 char *type_name = mono_type_get_full_name (klass);
4780 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4781 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4783 g_free (method_name);
4789 if (mono_class_is_ginst (klass)) {
4790 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4792 mono_class_init (gklass);
4794 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4796 /* Check that the vtable_size value computed in mono_class_init () is correct */
4797 if (klass->vtable_size)
4798 g_assert (cur_slot == klass->vtable_size);
4799 klass->vtable_size = cur_slot;
4802 /* Try to share the vtable with our parent. */
4803 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4804 mono_memory_barrier ();
4805 klass->vtable = klass->parent->vtable;
4807 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4808 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4809 mono_memory_barrier ();
4810 klass->vtable = tmp;
4813 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4814 if (mono_print_vtable) {
4817 print_implemented_interfaces (klass);
4819 for (i = 0; i <= max_iid; i++)
4820 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4823 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4824 klass->vtable_size, icount);
4826 for (i = 0; i < cur_slot; ++i) {
4831 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4832 mono_method_full_name (cm, TRUE));
4838 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4839 klass->name, max_iid);
4841 for (i = 0; i < klass->interface_count; i++) {
4842 ic = klass->interfaces [i];
4843 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4844 mono_class_interface_offset (klass, ic),
4845 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4848 for (k = klass->parent; k ; k = k->parent) {
4849 for (i = 0; i < k->interface_count; i++) {
4850 ic = k->interfaces [i];
4851 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4852 mono_class_interface_offset (klass, ic),
4853 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4859 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4864 char *name = mono_type_get_full_name (klass);
4865 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4868 g_hash_table_destroy (override_map);
4870 g_slist_free (virt_methods);
4875 * mono_method_get_vtable_slot:
4877 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4878 * LOCKING: Acquires the loader lock.
4880 * FIXME Use proper MonoError machinery here.
4883 mono_method_get_vtable_slot (MonoMethod *method)
4885 if (method->slot == -1) {
4886 mono_class_setup_vtable (method->klass);
4887 if (mono_class_has_failure (method->klass))
4889 if (method->slot == -1) {
4893 if (!mono_class_is_ginst (method->klass)) {
4894 g_assert (method->is_inflated);
4895 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4898 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4899 g_assert (mono_class_is_ginst (method->klass));
4900 gklass = mono_class_get_generic_class (method->klass)->container_class;
4901 mono_class_setup_methods (method->klass);
4902 g_assert (method->klass->methods);
4903 for (i = 0; i < method->klass->method.count; ++i) {
4904 if (method->klass->methods [i] == method)
4907 g_assert (i < method->klass->method.count);
4908 g_assert (gklass->methods);
4909 method->slot = gklass->methods [i]->slot;
4911 g_assert (method->slot != -1);
4913 return method->slot;
4917 * mono_method_get_vtable_index:
4920 * Returns the index into the runtime vtable to access the method or,
4921 * in the case of a virtual generic method, the virtual generic method
4922 * thunk. Returns -1 on failure.
4924 * FIXME Use proper MonoError machinery here.
4927 mono_method_get_vtable_index (MonoMethod *method)
4929 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4930 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4931 if (imethod->declaring->is_generic)
4932 return mono_method_get_vtable_slot (imethod->declaring);
4934 return mono_method_get_vtable_slot (method);
4937 static MonoMethod *default_ghc = NULL;
4938 static MonoMethod *default_finalize = NULL;
4939 static int finalize_slot = -1;
4940 static int ghc_slot = -1;
4943 initialize_object_slots (MonoClass *klass)
4948 if (klass == mono_defaults.object_class) {
4949 mono_class_setup_vtable (klass);
4950 for (i = 0; i < klass->vtable_size; ++i) {
4951 MonoMethod *cm = klass->vtable [i];
4953 if (!strcmp (cm->name, "GetHashCode"))
4955 else if (!strcmp (cm->name, "Finalize"))
4959 g_assert (ghc_slot > 0);
4960 default_ghc = klass->vtable [ghc_slot];
4962 g_assert (finalize_slot > 0);
4963 default_finalize = klass->vtable [finalize_slot];
4968 MonoMethod *array_method;
4970 } GenericArrayMethodInfo;
4972 static int generic_array_method_num = 0;
4973 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4976 generic_array_methods (MonoClass *klass)
4978 int i, count_generic = 0;
4979 GList *list = NULL, *tmp;
4980 if (generic_array_method_num)
4981 return generic_array_method_num;
4982 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4983 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4984 for (i = 0; i < klass->parent->method.count; i++) {
4985 MonoMethod *m = klass->parent->methods [i];
4986 if (!strncmp (m->name, "InternalArray__", 15)) {
4988 list = g_list_prepend (list, m);
4991 list = g_list_reverse (list);
4992 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4994 for (tmp = list; tmp; tmp = tmp->next) {
4995 const char *mname, *iname;
4997 MonoMethod *m = (MonoMethod *)tmp->data;
4998 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4999 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
5001 generic_array_method_info [i].array_method = m;
5002 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
5003 iname = "System.Collections.Generic.ICollection`1.";
5004 mname = m->name + 27;
5005 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
5006 iname = "System.Collections.Generic.IEnumerable`1.";
5007 mname = m->name + 27;
5008 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
5009 iname = "System.Collections.Generic.IReadOnlyList`1.";
5010 mname = m->name + strlen (ireadonlylist_prefix);
5011 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
5012 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
5013 mname = m->name + strlen (ireadonlycollection_prefix);
5014 } else if (!strncmp (m->name, "InternalArray__", 15)) {
5015 iname = "System.Collections.Generic.IList`1.";
5016 mname = m->name + 15;
5018 g_assert_not_reached ();
5021 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
5022 strcpy (name, iname);
5023 strcpy (name + strlen (iname), mname);
5024 generic_array_method_info [i].name = name;
5027 /*g_print ("array generic methods: %d\n", count_generic);*/
5029 generic_array_method_num = count_generic;
5031 return generic_array_method_num;
5035 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5037 MonoGenericContext tmp_context;
5040 tmp_context.class_inst = NULL;
5041 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
5042 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5044 for (i = 0; i < generic_array_method_num; i++) {
5046 MonoMethod *m = generic_array_method_info [i].array_method;
5047 MonoMethod *inflated;
5049 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5050 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5051 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5056 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5058 int null_length = strlen ("(null)");
5059 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5060 char *s = (char *)mono_image_alloc (image, len);
5063 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5064 g_assert (result == len - 1);
5071 * @klass: the class to initialize
5073 * Compute the instance_size, class_size and other infos that cannot be
5074 * computed at mono_class_get() time. Also compute vtable_size if possible.
5075 * Returns TRUE on success or FALSE if there was a problem in loading
5076 * the type (incorrect assemblies, missing assemblies, methods, etc).
5077 * Initializes the following fields in @klass:
5078 * - all the fields initialized by mono_class_init_sizes ()
5083 * LOCKING: Acquires the loader lock.
5086 mono_class_init (MonoClass *klass)
5088 int i, vtable_size = 0, array_method_count = 0;
5089 MonoCachedClassInfo cached_info;
5090 gboolean has_cached_info;
5091 gboolean locked = FALSE;
5092 gboolean ghcimpl = FALSE;
5093 gboolean has_cctor = FALSE;
5094 int first_iface_slot = 0;
5098 /* Double-checking locking pattern */
5099 if (klass->inited || mono_class_has_failure (klass))
5100 return !mono_class_has_failure (klass);
5102 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5105 * This function can recursively call itself.
5107 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
5108 if (g_slist_find (init_list, klass)) {
5109 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
5112 init_list = g_slist_prepend (init_list, klass);
5113 mono_native_tls_set_value (init_pending_tls_id, init_list);
5116 * We want to avoid doing complicated work inside locks, so we compute all the required
5117 * information and write it to @klass inside a lock.
5120 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5121 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5125 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5126 MonoClass *element_class = klass->element_class;
5127 if (!element_class->inited)
5128 mono_class_init (element_class);
5129 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
5133 mono_stats.initialized_class_count++;
5135 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
5136 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5138 mono_class_init (gklass);
5139 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
5142 mono_class_setup_interface_id (klass);
5145 if (klass->parent && !klass->parent->inited)
5146 mono_class_init (klass->parent);
5148 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5150 /* Compute instance size etc. */
5151 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
5152 if (mono_class_has_failure (klass))
5155 mono_class_setup_supertypes (klass);
5158 initialize_object_slots (klass);
5161 * Initialize the rest of the data without creating a generic vtable if possible.
5162 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5163 * also avoid computing a generic vtable.
5165 if (has_cached_info) {
5167 vtable_size = cached_info.vtable_size;
5168 ghcimpl = cached_info.ghcimpl;
5169 has_cctor = cached_info.has_cctor;
5170 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5171 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5172 * The first slot if for array with.
5174 static int szarray_vtable_size[2] = { 0 };
5176 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5179 if (!szarray_vtable_size [slot]) {
5180 mono_class_setup_vtable (klass);
5181 szarray_vtable_size [slot] = klass->vtable_size;
5182 vtable_size = klass->vtable_size;
5184 vtable_size = szarray_vtable_size[slot];
5186 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
5187 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5189 /* Generic instance case */
5190 ghcimpl = gklass->ghcimpl;
5191 has_cctor = gklass->has_cctor;
5193 mono_class_setup_vtable (gklass);
5194 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
5197 vtable_size = gklass->vtable_size;
5201 /* ghcimpl is not currently used
5203 if (klass->parent) {
5204 MonoMethod *cmethod = klass->vtable [ghc_slot];
5205 if (cmethod->is_inflated)
5206 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5207 if (cmethod == default_ghc) {
5213 /* C# doesn't allow interfaces to have cctors */
5214 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5215 MonoMethod *cmethod = NULL;
5217 if (klass->type_token && !image_is_dynamic(klass->image)) {
5218 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5219 /* The find_method function ignores the 'flags' argument */
5220 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5223 mono_class_setup_methods (klass);
5224 if (mono_class_has_failure (klass))
5227 for (i = 0; i < klass->method.count; ++i) {
5228 MonoMethod *method = klass->methods [i];
5229 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5230 (strcmp (".cctor", method->name) == 0)) {
5240 array_method_count = 3 + (klass->rank > 1? 2: 1);
5242 if (klass->interface_count) {
5243 int count_generic = generic_array_methods (klass);
5244 array_method_count += klass->interface_count * count_generic;
5248 if (klass->parent) {
5249 if (!klass->parent->vtable_size)
5250 mono_class_setup_vtable (klass->parent);
5251 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5253 g_assert (klass->parent->vtable_size);
5254 first_iface_slot = klass->parent->vtable_size;
5255 if (mono_class_need_stelemref_method (klass))
5260 * Do the actual changes to @klass inside the loader lock
5262 mono_loader_lock ();
5265 if (klass->inited || mono_class_has_failure (klass)) {
5266 mono_loader_unlock ();
5267 /* Somebody might have gotten in before us */
5268 return !mono_class_has_failure (klass);
5271 mono_stats.initialized_class_count++;
5273 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5274 MonoClass *gklass = klass->generic_class->container_class;
5276 mono_stats.generic_class_count++;
5278 klass->method = gklass->method;
5279 klass->field = gklass->field;
5282 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5283 klass->nested_classes_inited = TRUE;
5284 klass->ghcimpl = ghcimpl;
5285 klass->has_cctor = has_cctor;
5287 klass->vtable_size = vtable_size;
5288 if (has_cached_info) {
5289 klass->has_finalize = cached_info.has_finalize;
5290 klass->has_finalize_inited = TRUE;
5293 klass->method.count = array_method_count;
5295 mono_loader_unlock ();
5298 setup_interface_offsets (klass, first_iface_slot, TRUE);
5300 if (mono_security_core_clr_enabled ())
5301 mono_security_core_clr_check_inheritance (klass);
5303 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5304 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5309 init_list = g_slist_remove (init_list, klass);
5310 mono_native_tls_set_value (init_pending_tls_id, init_list);
5312 /* Because of the double-checking locking pattern */
5313 mono_memory_barrier ();
5317 mono_loader_unlock ();
5319 return !mono_class_has_failure (klass);
5323 * mono_class_has_finalizer:
5325 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5329 mono_class_has_finalizer (MonoClass *klass)
5331 gboolean has_finalize = FALSE;
5333 if (klass->has_finalize_inited)
5334 return klass->has_finalize;
5336 /* Interfaces and valuetypes are not supposed to have finalizers */
5337 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5338 MonoMethod *cmethod = NULL;
5340 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5341 } else if (mono_class_is_ginst (klass)) {
5342 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5344 has_finalize = mono_class_has_finalizer (gklass);
5345 } else if (klass->parent && klass->parent->has_finalize) {
5346 has_finalize = TRUE;
5348 if (klass->parent) {
5350 * Can't search in metadata for a method named Finalize, because that
5351 * ignores overrides.
5353 mono_class_setup_vtable (klass);
5354 if (mono_class_has_failure (klass))
5357 cmethod = klass->vtable [finalize_slot];
5361 g_assert (klass->vtable_size > finalize_slot);
5363 if (klass->parent) {
5364 if (cmethod->is_inflated)
5365 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5366 if (cmethod != default_finalize)
5367 has_finalize = TRUE;
5373 mono_image_lock (klass->image);
5375 if (!klass->has_finalize_inited) {
5376 klass->has_finalize = has_finalize ? 1 : 0;
5378 mono_memory_barrier ();
5379 klass->has_finalize_inited = TRUE;
5382 mono_image_unlock (klass->image);
5384 return klass->has_finalize;
5388 mono_is_corlib_image (MonoImage *image)
5390 return image == mono_defaults.corlib;
5394 * LOCKING: this assumes the loader lock is held
5397 mono_class_setup_mono_type (MonoClass *klass)
5399 const char *name = klass->name;
5400 const char *nspace = klass->name_space;
5401 gboolean is_corlib = mono_is_corlib_image (klass->image);
5403 klass->this_arg.byref = 1;
5404 klass->this_arg.data.klass = klass;
5405 klass->this_arg.type = MONO_TYPE_CLASS;
5406 klass->byval_arg.data.klass = klass;
5407 klass->byval_arg.type = MONO_TYPE_CLASS;
5409 if (is_corlib && !strcmp (nspace, "System")) {
5410 if (!strcmp (name, "ValueType")) {
5412 * do not set the valuetype bit for System.ValueType.
5413 * klass->valuetype = 1;
5415 klass->blittable = TRUE;
5416 } else if (!strcmp (name, "Enum")) {
5418 * do not set the valuetype bit for System.Enum.
5419 * klass->valuetype = 1;
5421 klass->valuetype = 0;
5422 klass->enumtype = 0;
5423 } else if (!strcmp (name, "Object")) {
5424 klass->byval_arg.type = MONO_TYPE_OBJECT;
5425 klass->this_arg.type = MONO_TYPE_OBJECT;
5426 } else if (!strcmp (name, "String")) {
5427 klass->byval_arg.type = MONO_TYPE_STRING;
5428 klass->this_arg.type = MONO_TYPE_STRING;
5429 } else if (!strcmp (name, "TypedReference")) {
5430 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5431 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5435 if (klass->valuetype) {
5436 int t = MONO_TYPE_VALUETYPE;
5438 if (is_corlib && !strcmp (nspace, "System")) {
5441 if (!strcmp (name, "Boolean")) {
5442 t = MONO_TYPE_BOOLEAN;
5443 } else if (!strcmp(name, "Byte")) {
5445 klass->blittable = TRUE;
5449 if (!strcmp (name, "Char")) {
5454 if (!strcmp (name, "Double")) {
5456 klass->blittable = TRUE;
5460 if (!strcmp (name, "Int32")) {
5462 klass->blittable = TRUE;
5463 } else if (!strcmp(name, "Int16")) {
5465 klass->blittable = TRUE;
5466 } else if (!strcmp(name, "Int64")) {
5468 klass->blittable = TRUE;
5469 } else if (!strcmp(name, "IntPtr")) {
5471 klass->blittable = TRUE;
5475 if (!strcmp (name, "Single")) {
5477 klass->blittable = TRUE;
5478 } else if (!strcmp(name, "SByte")) {
5480 klass->blittable = TRUE;
5484 if (!strcmp (name, "UInt32")) {
5486 klass->blittable = TRUE;
5487 } else if (!strcmp(name, "UInt16")) {
5489 klass->blittable = TRUE;
5490 } else if (!strcmp(name, "UInt64")) {
5492 klass->blittable = TRUE;
5493 } else if (!strcmp(name, "UIntPtr")) {
5495 klass->blittable = TRUE;
5499 if (!strcmp (name, "TypedReference")) {
5500 t = MONO_TYPE_TYPEDBYREF;
5501 klass->blittable = TRUE;
5505 if (!strcmp (name, "Void")) {
5513 klass->byval_arg.type = (MonoTypeEnum)t;
5514 klass->this_arg.type = (MonoTypeEnum)t;
5517 if (MONO_CLASS_IS_INTERFACE (klass))
5518 klass->interface_id = mono_get_unique_iid (klass);
5523 * COM initialization is delayed until needed.
5524 * However when a [ComImport] attribute is present on a type it will trigger
5525 * the initialization. This is not a problem unless the BCL being executed
5526 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5529 init_com_from_comimport (MonoClass *klass)
5531 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5532 if (mono_security_core_clr_enabled ()) {
5533 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5534 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5535 /* but it can not be made available for application (i.e. user code) since all COM calls
5536 * are considered native calls. In this case we fail with a TypeLoadException (just like
5537 * Silverlight 2 does */
5538 mono_class_set_type_load_failure (klass, "");
5543 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5545 #endif /*DISABLE_COM*/
5548 * LOCKING: this assumes the loader lock is held
5551 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5553 gboolean system_namespace;
5554 gboolean is_corlib = mono_is_corlib_image (klass->image);
5556 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5558 /* if root of the hierarchy */
5559 if (system_namespace && !strcmp (klass->name, "Object")) {
5560 klass->parent = NULL;
5561 klass->instance_size = sizeof (MonoObject);
5564 if (!strcmp (klass->name, "<Module>")) {
5565 klass->parent = NULL;
5566 klass->instance_size = 0;
5570 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5571 /* Imported COM Objects always derive from __ComObject. */
5573 if (MONO_CLASS_IS_IMPORT (klass)) {
5574 init_com_from_comimport (klass);
5575 if (parent == mono_defaults.object_class)
5576 parent = mono_class_get_com_object_class ();
5580 /* set the parent to something useful and safe, but mark the type as broken */
5581 parent = mono_defaults.object_class;
5582 mono_class_set_type_load_failure (klass, "");
5586 klass->parent = parent;
5588 if (mono_class_is_ginst (parent) && !parent->name) {
5590 * If the parent is a generic instance, we may get
5591 * called before it is fully initialized, especially
5592 * before it has its name.
5597 #ifndef DISABLE_REMOTING
5598 klass->marshalbyref = parent->marshalbyref;
5599 klass->contextbound = parent->contextbound;
5602 klass->delegate = parent->delegate;
5604 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5605 mono_class_set_is_com_object (klass);
5607 if (system_namespace) {
5608 #ifndef DISABLE_REMOTING
5609 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5610 klass->marshalbyref = 1;
5612 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5613 klass->contextbound = 1;
5615 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5616 klass->delegate = 1;
5619 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5620 (strcmp (klass->parent->name_space, "System") == 0)))
5621 klass->valuetype = 1;
5622 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5623 klass->valuetype = klass->enumtype = 1;
5625 /*klass->enumtype = klass->parent->enumtype; */
5627 /* initialize com types if COM interfaces are present */
5629 if (MONO_CLASS_IS_IMPORT (klass))
5630 init_com_from_comimport (klass);
5632 klass->parent = NULL;
5638 * mono_class_setup_supertypes:
5641 * Build the data structure needed to make fast type checks work.
5642 * This currently sets two fields in @class:
5643 * - idepth: distance between @class and System.Object in the type
5645 * - supertypes: array of classes: each element has a class in the hierarchy
5646 * starting from @class up to System.Object
5648 * LOCKING: This function is atomic, in case of contention we waste memory.
5651 mono_class_setup_supertypes (MonoClass *klass)
5654 MonoClass **supertypes;
5656 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5660 if (klass->parent && !klass->parent->supertypes)
5661 mono_class_setup_supertypes (klass->parent);
5663 klass->idepth = klass->parent->idepth + 1;
5667 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5668 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5670 if (klass->parent) {
5671 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5674 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5675 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5677 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5680 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5684 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5686 MonoClass *gtd = (MonoClass*)user_data;
5687 /* Only try to fix generic instances of @gtd */
5688 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5691 /* Check if the generic instance has no parent. */
5692 if (gtd->parent && !gclass->parent)
5693 mono_generic_class_setup_parent (gclass, gtd);
5699 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5701 mono_class_set_type_load_failure (klass, "%s", msg);
5702 mono_error_set_type_load_class (error, klass, "%s", msg);
5706 * mono_class_create_from_typedef:
5707 * @image: image where the token is valid
5708 * @type_token: typedef token
5709 * @error: used to return any error found while creating the type
5711 * Create the MonoClass* representing the specified type token.
5712 * @type_token must be a TypeDef token.
5714 * FIXME: don't return NULL on failure, just the the caller figure it out.
5717 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5719 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5720 MonoClass *klass, *parent = NULL;
5721 guint32 cols [MONO_TYPEDEF_SIZE];
5722 guint32 cols_next [MONO_TYPEDEF_SIZE];
5723 guint tidx = mono_metadata_token_index (type_token);
5724 MonoGenericContext *context = NULL;
5725 const char *name, *nspace;
5727 MonoClass **interfaces;
5728 guint32 field_last, method_last;
5729 guint32 nesting_tokeen;
5731 mono_error_init (error);
5733 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5734 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5738 mono_loader_lock ();
5740 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5741 mono_loader_unlock ();
5745 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5747 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5748 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5750 if (mono_metadata_has_generic_params (image, type_token)) {
5751 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5752 klass->class_kind = MONO_CLASS_GTD;
5753 classes_size += sizeof (MonoClassGtd);
5755 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5756 klass->class_kind = MONO_CLASS_DEF;
5757 classes_size += sizeof (MonoClassDef);
5761 klass->name_space = nspace;
5763 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5765 klass->image = image;
5766 klass->type_token = type_token;
5767 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5769 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5772 * Check whether we're a generic type definition.
5774 if (mono_class_is_gtd (klass)) {
5775 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5776 generic_container->owner.klass = klass;
5777 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5778 context = &generic_container->context;
5779 mono_class_set_generic_container (klass, generic_container);
5780 enable_gclass_recording ();
5783 if (cols [MONO_TYPEDEF_EXTENDS]) {
5785 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5787 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5788 /*WARNING: this must satisfy mono_metadata_type_hash*/
5789 klass->this_arg.byref = 1;
5790 klass->this_arg.data.klass = klass;
5791 klass->this_arg.type = MONO_TYPE_CLASS;
5792 klass->byval_arg.data.klass = klass;
5793 klass->byval_arg.type = MONO_TYPE_CLASS;
5795 parent = mono_class_get_checked (image, parent_token, error);
5796 if (parent && context) /* Always inflate */
5797 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5799 if (parent == NULL) {
5800 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5801 goto parent_failure;
5804 for (tmp = parent; tmp; tmp = tmp->parent) {
5806 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5807 goto parent_failure;
5809 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5810 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5811 goto parent_failure;
5816 mono_class_setup_parent (klass, parent);
5818 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5819 mono_class_setup_mono_type (klass);
5821 if (mono_class_is_gtd (klass))
5822 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5825 * This might access klass->byval_arg for recursion generated by generic constraints,
5826 * so it has to come after setup_mono_type ().
5828 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5829 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5830 if (!mono_error_ok (error)) {
5831 /*FIXME implement a mono_class_set_failure_from_mono_error */
5832 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5833 mono_loader_unlock ();
5834 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5839 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5843 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5847 klass->cast_class = klass->element_class = klass;
5849 if (!klass->enumtype) {
5850 if (!mono_metadata_interfaces_from_typedef_full (
5851 image, type_token, &interfaces, &icount, FALSE, context, error)){
5853 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5854 mono_loader_unlock ();
5855 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5859 klass->interfaces = interfaces;
5860 klass->interface_count = icount;
5861 klass->interfaces_inited = 1;
5864 /*g_print ("Load class %s\n", name);*/
5867 * Compute the field and method lists
5869 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5870 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5872 if (tt->rows > tidx){
5873 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5874 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5875 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5877 field_last = image->tables [MONO_TABLE_FIELD].rows;
5878 method_last = image->tables [MONO_TABLE_METHOD].rows;
5881 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5882 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5883 klass->field.count = field_last - klass->field.first;
5885 klass->field.count = 0;
5887 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5888 klass->method.count = method_last - klass->method.first;
5890 klass->method.count = 0;
5892 /* reserve space to store vector pointer in arrays */
5893 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5894 klass->instance_size += 2 * sizeof (gpointer);
5895 g_assert (klass->field.count == 0);
5898 if (klass->enumtype) {
5899 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5900 if (!enum_basetype) {
5901 /*set it to a default value as the whole runtime can't handle this to be null*/
5902 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5903 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5904 mono_loader_unlock ();
5905 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5908 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5912 * If we're a generic type definition, load the constraints.
5913 * We must do this after the class has been constructed to make certain recursive scenarios
5916 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5917 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5918 mono_loader_unlock ();
5919 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5923 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5924 if (!strncmp (name, "Vector", 6))
5925 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");
5928 mono_loader_unlock ();
5930 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5935 mono_class_setup_mono_type (klass);
5936 mono_loader_unlock ();
5937 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5941 /** Is klass a Nullable<T> ginst? */
5943 mono_class_is_nullable (MonoClass *klass)
5945 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5946 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5950 /** if klass is T? return T */
5952 mono_class_get_nullable_param (MonoClass *klass)
5954 g_assert (mono_class_is_nullable (klass));
5955 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5959 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5963 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5965 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5966 if (!mono_error_ok (&error)) {
5967 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5968 klass->parent = mono_defaults.object_class;
5969 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5970 mono_error_cleanup (&error);
5974 mono_class_setup_parent (klass, klass->parent);
5976 if (klass->enumtype) {
5977 klass->cast_class = gtd->cast_class;
5978 klass->element_class = gtd->element_class;
5984 * Create the `MonoClass' for an instantiation of a generic type.
5985 * We only do this if we actually need it.
5988 mono_generic_class_get_class (MonoGenericClass *gclass)
5990 MonoClass *klass, *gklass;
5992 if (gclass->cached_class)
5993 return gclass->cached_class;
5995 mono_loader_lock ();
5996 if (gclass->cached_class) {
5997 mono_loader_unlock ();
5998 return gclass->cached_class;
6001 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
6003 gklass = gclass->container_class;
6005 if (record_gclass_instantiation > 0)
6006 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6008 if (gklass->nested_in) {
6009 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6010 klass->nested_in = gklass->nested_in;
6013 klass->name = gklass->name;
6014 klass->name_space = gklass->name_space;
6016 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6018 klass->image = gklass->image;
6019 klass->type_token = gklass->type_token;
6020 klass->field.count = gklass->field.count;
6022 klass->class_kind = MONO_CLASS_GINST;
6024 ((MonoClassGenericInst*)klass)->generic_class = gclass;
6026 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6027 klass->this_arg.type = klass->byval_arg.type;
6028 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6029 klass->this_arg.byref = TRUE;
6030 klass->enumtype = gklass->enumtype;
6031 klass->valuetype = gklass->valuetype;
6033 klass->cast_class = klass->element_class = klass;
6035 if (mono_class_is_nullable (klass))
6036 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6039 * We're not interested in the nested classes of a generic instance.
6040 * We use the generic type definition to look for nested classes.
6043 mono_generic_class_setup_parent (klass, gklass);
6045 if (gclass->is_dynamic) {
6047 * 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.
6048 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6049 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6051 if (!gklass->wastypebuilder)
6054 mono_class_setup_supertypes (klass);
6056 if (klass->enumtype) {
6058 * For enums, gklass->fields might not been set, but instance_size etc. is
6059 * already set in mono_reflection_create_internal_class (). For non-enums,
6060 * these will be computed normally in mono_class_layout_fields ().
6062 klass->instance_size = gklass->instance_size;
6063 klass->sizes.class_size = gklass->sizes.class_size;
6064 mono_memory_barrier ();
6065 klass->size_inited = 1;
6069 mono_memory_barrier ();
6070 gclass->cached_class = klass;
6072 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6074 inflated_classes ++;
6075 inflated_classes_size += sizeof (MonoClassGenericInst);
6077 mono_loader_unlock ();
6083 get_image_for_container (MonoGenericContainer *container)
6086 if (container->is_anonymous) {
6087 result = container->owner.image;
6090 if (container->is_method) {
6091 MonoMethod *method = container->owner.method;
6092 g_assert_checked (method);
6093 klass = method->klass;
6095 klass = container->owner.klass;
6097 g_assert_checked (klass);
6098 result = klass->image;
6105 get_image_for_generic_param (MonoGenericParam *param)
6107 MonoGenericContainer *container = mono_generic_param_owner (param);
6108 g_assert_checked (container);
6109 return get_image_for_container (container);
6112 // Make a string in the designated image consisting of a single integer.
6113 #define INT_STRING_SIZE 16
6115 make_generic_name_string (MonoImage *image, int num)
6117 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6118 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6122 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6123 // pinfo is derived from param by the caller for us.
6125 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6127 MonoClass *klass, **ptr;
6129 MonoGenericContainer *container = mono_generic_param_owner (param);
6130 g_assert_checked (container);
6132 MonoImage *image = get_image_for_container (container);
6133 gboolean is_mvar = container->is_method;
6134 gboolean is_anonymous = container->is_anonymous;
6136 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6137 klass->class_kind = MONO_CLASS_GPARAM;
6138 classes_size += sizeof (MonoClassGenericParam);
6141 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6143 int n = mono_generic_param_num (param);
6144 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6148 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6149 } else if (is_mvar) {
6150 MonoMethod *omethod = container->owner.method;
6151 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6153 MonoClass *oklass = container->owner.klass;
6154 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6157 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6159 // Count non-NULL items in pinfo->constraints
6162 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6166 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6167 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6169 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6170 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6172 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6175 if (count - pos > 0) {
6176 klass->interface_count = count - pos;
6177 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6178 klass->interfaces_inited = TRUE;
6179 for (i = pos; i < count; i++)
6180 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6183 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6185 klass->inited = TRUE;
6186 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6187 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6189 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6190 klass->this_arg.type = klass->byval_arg.type;
6191 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6192 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6193 klass->this_arg.byref = TRUE;
6195 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6196 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6198 /*Init these fields to sane values*/
6199 klass->min_align = 1;
6201 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6202 * constrained to, the JIT depends on this.
6204 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6205 mono_memory_barrier ();
6206 klass->size_inited = 1;
6208 mono_class_setup_supertypes (klass);
6210 if (count - pos > 0) {
6211 mono_class_setup_vtable (klass->parent);
6212 if (mono_class_has_failure (klass->parent))
6213 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6215 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6221 #define FAST_CACHE_SIZE 16
6224 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6225 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6226 * we cache the MonoClasses.
6227 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6228 * LOCKING: Takes the image lock depending on @take_lock.
6231 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6233 int n = mono_generic_param_num (param);
6234 MonoImage *image = get_image_for_generic_param (param);
6235 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6236 MonoClass *klass = NULL;
6241 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6242 // For high numbers or constraints we have to use pointer hashes.
6243 if (param->gshared_constraint) {
6244 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6247 mono_image_lock (image);
6248 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6250 mono_image_unlock (image);
6255 if (n < FAST_CACHE_SIZE) {
6257 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6259 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6261 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6264 mono_image_lock (image);
6265 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6267 mono_image_unlock (image);
6274 * LOCKING: Image lock (param->image) must be held
6277 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6279 int n = mono_generic_param_num (param);
6280 MonoImage *image = get_image_for_generic_param (param);
6281 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6285 if (param->gshared_constraint) {
6286 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6288 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6289 mono_memory_barrier ();
6291 image->mvar_cache_constrained = ht;
6293 image->var_cache_constrained = ht;
6295 g_hash_table_insert (ht, param, klass);
6296 } else if (n < FAST_CACHE_SIZE) {
6298 /* Requires locking to avoid droping an already published class */
6299 if (!image->mvar_cache_fast)
6300 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6301 image->mvar_cache_fast [n] = klass;
6303 if (!image->var_cache_fast)
6304 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6305 image->var_cache_fast [n] = klass;
6308 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6310 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6312 ht = g_hash_table_new (NULL, NULL);
6313 mono_memory_barrier ();
6315 image->mvar_cache_slow = ht;
6317 image->var_cache_slow = ht;
6320 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6325 * LOCKING: Acquires the image lock (@image).
6328 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6330 MonoImage *image = get_image_for_generic_param (param);
6331 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6332 MonoClass *klass, *klass2;
6334 // If a klass already exists for this object and is cached, return it.
6335 if (pinfo) // Non-anonymous
6336 klass = pinfo->pklass;
6338 klass = get_anon_gparam_class (param, TRUE);
6343 // Create a new klass
6344 klass = make_generic_param_class (param, pinfo);
6346 // Now we need to cache the klass we created.
6347 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6348 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6349 // and allow our newly-created klass object to just leak.
6350 mono_memory_barrier ();
6352 mono_image_lock (image);
6354 // Here "klass2" refers to the klass potentially created by the other thread.
6355 if (pinfo) // Repeat check from above
6356 klass2 = pinfo->pklass;
6358 klass2 = get_anon_gparam_class (param, FALSE);
6365 pinfo->pklass = klass;
6367 set_anon_gparam_class (param, klass);
6369 mono_image_unlock (image);
6371 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6373 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6375 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6381 * mono_class_from_generic_parameter:
6382 * @param: Parameter to find/construct a class for.
6383 * @arg2: Is ignored.
6384 * @arg3: Is ignored.
6387 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6389 return mono_class_from_generic_parameter_internal (param);
6394 mono_ptr_class_get (MonoType *type)
6397 MonoClass *el_class;
6401 el_class = mono_class_from_mono_type (type);
6402 image = el_class->image;
6404 mono_image_lock (image);
6405 if (image->ptr_cache) {
6406 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6407 mono_image_unlock (image);
6411 mono_image_unlock (image);
6413 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6415 classes_size += sizeof (MonoClassPointer);
6417 result->parent = NULL; /* no parent for PTR types */
6418 result->name_space = el_class->name_space;
6419 name = g_strdup_printf ("%s*", el_class->name);
6420 result->name = mono_image_strdup (image, name);
6421 result->class_kind = MONO_CLASS_POINTER;
6424 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6426 result->image = el_class->image;
6427 result->inited = TRUE;
6428 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6429 result->cast_class = result->element_class = el_class;
6430 result->blittable = TRUE;
6432 result->byval_arg.type = MONO_TYPE_PTR;
6433 result->this_arg.type = result->byval_arg.type;
6434 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6435 result->this_arg.byref = TRUE;
6437 mono_class_setup_supertypes (result);
6439 mono_image_lock (image);
6440 if (image->ptr_cache) {
6442 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6443 mono_image_unlock (image);
6444 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6448 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6450 g_hash_table_insert (image->ptr_cache, el_class, result);
6451 mono_image_unlock (image);
6453 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6459 mono_fnptr_class_get (MonoMethodSignature *sig)
6462 static GHashTable *ptr_hash = NULL;
6464 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6466 mono_loader_lock ();
6469 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6471 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6472 mono_loader_unlock ();
6475 result = g_new0 (MonoClass, 1);
6477 result->parent = NULL; /* no parent for PTR types */
6478 result->name_space = "System";
6479 result->name = "MonoFNPtrFakeClass";
6480 result->class_kind = MONO_CLASS_POINTER;
6482 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6484 result->image = mono_defaults.corlib; /* need to fix... */
6485 result->inited = TRUE;
6486 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6487 result->cast_class = result->element_class = result;
6488 result->blittable = TRUE;
6490 result->byval_arg.type = MONO_TYPE_FNPTR;
6491 result->this_arg.type = result->byval_arg.type;
6492 result->this_arg.data.method = result->byval_arg.data.method = sig;
6493 result->this_arg.byref = TRUE;
6494 result->blittable = TRUE;
6496 mono_class_setup_supertypes (result);
6498 g_hash_table_insert (ptr_hash, sig, result);
6500 mono_loader_unlock ();
6502 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6508 * mono_class_from_mono_type:
6509 * @type: describes the type to return
6511 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6514 mono_class_from_mono_type (MonoType *type)
6516 switch (type->type) {
6517 case MONO_TYPE_OBJECT:
6518 return type->data.klass? type->data.klass: mono_defaults.object_class;
6519 case MONO_TYPE_VOID:
6520 return type->data.klass? type->data.klass: mono_defaults.void_class;
6521 case MONO_TYPE_BOOLEAN:
6522 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6523 case MONO_TYPE_CHAR:
6524 return type->data.klass? type->data.klass: mono_defaults.char_class;
6526 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6528 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6530 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6532 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6534 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6536 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6538 return type->data.klass? type->data.klass: mono_defaults.int_class;
6540 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6542 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6544 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6546 return type->data.klass? type->data.klass: mono_defaults.single_class;
6548 return type->data.klass? type->data.klass: mono_defaults.double_class;
6549 case MONO_TYPE_STRING:
6550 return type->data.klass? type->data.klass: mono_defaults.string_class;
6551 case MONO_TYPE_TYPEDBYREF:
6552 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6553 case MONO_TYPE_ARRAY:
6554 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6556 return mono_ptr_class_get (type->data.type);
6557 case MONO_TYPE_FNPTR:
6558 return mono_fnptr_class_get (type->data.method);
6559 case MONO_TYPE_SZARRAY:
6560 return mono_array_class_get (type->data.klass, 1);
6561 case MONO_TYPE_CLASS:
6562 case MONO_TYPE_VALUETYPE:
6563 return type->data.klass;
6564 case MONO_TYPE_GENERICINST:
6565 return mono_generic_class_get_class (type->data.generic_class);
6566 case MONO_TYPE_MVAR:
6568 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6570 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6571 g_assert_not_reached ();
6574 // Yes, this returns NULL, even if it is documented as not doing so, but there
6575 // is no way for the code to make it this far, due to the assert above.
6580 * mono_type_retrieve_from_typespec
6581 * @image: context where the image is created
6582 * @type_spec: typespec token
6583 * @context: the generic context used to evaluate generic instantiations in
6586 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6588 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6590 *did_inflate = FALSE;
6595 if (context && (context->class_inst || context->method_inst)) {
6596 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6598 if (!mono_error_ok (error)) {
6604 *did_inflate = TRUE;
6611 * mono_class_create_from_typespec
6612 * @image: context where the image is created
6613 * @type_spec: typespec token
6614 * @context: the generic context used to evaluate generic instantiations in
6617 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6620 gboolean inflated = FALSE;
6621 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6622 return_val_if_nok (error, NULL);
6623 ret = mono_class_from_mono_type (t);
6625 mono_metadata_free_type (t);
6630 * mono_bounded_array_class_get:
6631 * @element_class: element class
6632 * @rank: the dimension of the array class
6633 * @bounded: whenever the array has non-zero bounds
6635 * Returns: A class object describing the array with element type @element_type and
6639 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6643 MonoClass *parent = NULL;
6644 GSList *list, *rootlist = NULL;
6648 g_assert (rank <= 255);
6651 /* bounded only matters for one-dimensional arrays */
6654 image = eclass->image;
6656 if (rank == 1 && !bounded) {
6658 * This case is very frequent not just during compilation because of calls
6659 * from mono_class_from_mono_type (), mono_array_new (),
6660 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6662 mono_os_mutex_lock (&image->szarray_cache_lock);
6663 if (!image->szarray_cache)
6664 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6665 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6666 mono_os_mutex_unlock (&image->szarray_cache_lock);
6670 mono_loader_lock ();
6672 mono_loader_lock ();
6674 if (!image->array_cache)
6675 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6677 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6678 for (; list; list = list->next) {
6679 klass = (MonoClass *)list->data;
6680 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6681 mono_loader_unlock ();
6688 parent = mono_defaults.array_class;
6689 if (!parent->inited)
6690 mono_class_init (parent);
6692 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6694 klass->image = image;
6695 klass->name_space = eclass->name_space;
6696 klass->class_kind = MONO_CLASS_ARRAY;
6698 nsize = strlen (eclass->name);
6699 name = (char *)g_malloc (nsize + 2 + rank + 1);
6700 memcpy (name, eclass->name, nsize);
6703 memset (name + nsize + 1, ',', rank - 1);
6705 name [nsize + rank] = '*';
6706 name [nsize + rank + bounded] = ']';
6707 name [nsize + rank + bounded + 1] = 0;
6708 klass->name = mono_image_strdup (image, name);
6711 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6713 classes_size += sizeof (MonoClassArray);
6715 klass->type_token = 0;
6716 klass->parent = parent;
6717 klass->instance_size = mono_class_instance_size (klass->parent);
6719 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6720 /*Arrays of those two types are invalid.*/
6721 MonoError prepared_error;
6722 mono_error_init (&prepared_error);
6723 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6724 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6725 mono_error_cleanup (&prepared_error);
6726 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6727 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6728 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6729 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6731 /* element_size -1 is ok as this is not an instantitable type*/
6732 klass->sizes.element_size = -1;
6734 klass->sizes.element_size = mono_class_array_element_size (eclass);
6736 mono_class_setup_supertypes (klass);
6738 if (mono_class_is_ginst (eclass))
6739 mono_class_init (eclass);
6740 mono_class_init_sizes (eclass);
6741 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6742 /*FIXME we fail the array type, but we have to let other fields be set.*/
6744 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6748 if (eclass->enumtype)
6749 klass->cast_class = eclass->element_class;
6751 klass->cast_class = eclass;
6753 switch (klass->cast_class->byval_arg.type) {
6755 klass->cast_class = mono_defaults.byte_class;
6758 klass->cast_class = mono_defaults.int16_class;
6761 #if SIZEOF_VOID_P == 4
6765 klass->cast_class = mono_defaults.int32_class;
6768 #if SIZEOF_VOID_P == 8
6772 klass->cast_class = mono_defaults.int64_class;
6778 klass->element_class = eclass;
6780 if ((rank > 1) || bounded) {
6781 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6782 klass->byval_arg.type = MONO_TYPE_ARRAY;
6783 klass->byval_arg.data.array = at;
6784 at->eklass = eclass;
6786 /* FIXME: complete.... */
6788 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6789 klass->byval_arg.data.klass = eclass;
6791 klass->this_arg = klass->byval_arg;
6792 klass->this_arg.byref = 1;
6794 //WTF was this? it's wrong
6795 // klass->generic_container = eclass->generic_container;
6797 if (rank == 1 && !bounded) {
6798 MonoClass *prev_class;
6800 mono_os_mutex_lock (&image->szarray_cache_lock);
6801 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6803 /* Someone got in before us */
6806 g_hash_table_insert (image->szarray_cache, eclass, klass);
6807 mono_os_mutex_unlock (&image->szarray_cache_lock);
6809 list = g_slist_append (rootlist, klass);
6810 g_hash_table_insert (image->array_cache, eclass, list);
6813 mono_loader_unlock ();
6815 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6821 * mono_array_class_get:
6822 * @element_class: element class
6823 * @rank: the dimension of the array class
6825 * Returns: A class object describing the array with element type @element_type and
6829 mono_array_class_get (MonoClass *eclass, guint32 rank)
6831 return mono_bounded_array_class_get (eclass, rank, FALSE);
6835 * mono_class_instance_size:
6838 * Use to get the size of a class in bytes.
6840 * Returns: The size of an object instance
6843 mono_class_instance_size (MonoClass *klass)
6845 if (!klass->size_inited)
6846 mono_class_init_sizes (klass);
6848 return klass->instance_size;
6852 * mono_class_min_align:
6855 * Use to get the computed minimum alignment requirements for the specified class.
6857 * Returns: minimum alignment requirements
6860 mono_class_min_align (MonoClass *klass)
6862 if (!klass->size_inited)
6863 mono_class_init_sizes (klass);
6865 return klass->min_align;
6869 * mono_class_value_size:
6872 * This function is used for value types, and return the
6873 * space and the alignment to store that kind of value object.
6875 * Returns: the size of a value of kind @klass
6878 mono_class_value_size (MonoClass *klass, guint32 *align)
6882 /* fixme: check disable, because we still have external revereces to
6883 * mscorlib and Dummy Objects
6885 /*g_assert (klass->valuetype);*/
6887 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6890 *align = klass->min_align;
6896 * mono_class_data_size:
6899 * Returns: The size of the static class data
6902 mono_class_data_size (MonoClass *klass)
6905 mono_class_init (klass);
6906 /* This can happen with dynamically created types */
6907 if (!klass->size_inited)
6908 mono_class_init_sizes (klass);
6910 /* in arrays, sizes.class_size is unioned with element_size
6911 * and arrays have no static fields
6915 return klass->sizes.class_size;
6919 * Auxiliary routine to mono_class_get_field
6921 * Takes a field index instead of a field token.
6923 static MonoClassField *
6924 mono_class_get_field_idx (MonoClass *klass, int idx)
6926 mono_class_setup_fields (klass);
6927 if (mono_class_has_failure (klass))
6931 if (klass->image->uncompressed_metadata) {
6933 * klass->field.first points to the FieldPtr table, while idx points into the
6934 * Field table, so we have to do a search.
6936 /*FIXME this is broken for types with multiple fields with the same name.*/
6937 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6940 for (i = 0; i < klass->field.count; ++i)
6941 if (mono_field_get_name (&klass->fields [i]) == name)
6942 return &klass->fields [i];
6943 g_assert_not_reached ();
6945 if (klass->field.count) {
6946 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6947 return &klass->fields [idx - klass->field.first];
6951 klass = klass->parent;
6957 * mono_class_get_field:
6958 * @class: the class to lookup the field.
6959 * @field_token: the field token
6961 * Returns: A MonoClassField representing the type and offset of
6962 * the field, or a NULL value if the field does not belong to this
6966 mono_class_get_field (MonoClass *klass, guint32 field_token)
6968 int idx = mono_metadata_token_index (field_token);
6970 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6972 return mono_class_get_field_idx (klass, idx - 1);
6976 * mono_class_get_field_from_name:
6977 * @klass: the class to lookup the field.
6978 * @name: the field name
6980 * Search the class @klass and it's parents for a field with the name @name.
6982 * Returns: The MonoClassField pointer of the named field or NULL
6985 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6987 return mono_class_get_field_from_name_full (klass, name, NULL);
6991 * mono_class_get_field_from_name_full:
6992 * @klass: the class to lookup the field.
6993 * @name: the field name
6994 * @type: the type of the fields. This optional.
6996 * Search the class @klass and it's parents for a field with the name @name and type @type.
6998 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6999 * of its generic type definition.
7001 * Returns: The MonoClassField pointer of the named field or NULL
7004 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7008 mono_class_setup_fields (klass);
7009 if (mono_class_has_failure (klass))
7013 for (i = 0; i < klass->field.count; ++i) {
7014 MonoClassField *field = &klass->fields [i];
7016 if (strcmp (name, mono_field_get_name (field)) != 0)
7020 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7021 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7026 klass = klass->parent;
7032 * mono_class_get_field_token:
7033 * @field: the field we need the token of
7035 * Get the token of a field. Note that the tokesn is only valid for the image
7036 * the field was loaded from. Don't use this function for fields in dynamic types.
7038 * Returns: The token representing the field in the image it was loaded from.
7041 mono_class_get_field_token (MonoClassField *field)
7043 MonoClass *klass = field->parent;
7046 mono_class_setup_fields (klass);
7051 for (i = 0; i < klass->field.count; ++i) {
7052 if (&klass->fields [i] == field) {
7053 int idx = klass->field.first + i + 1;
7055 if (klass->image->uncompressed_metadata)
7056 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7057 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7060 klass = klass->parent;
7063 g_assert_not_reached ();
7068 mono_field_get_index (MonoClassField *field)
7070 int index = field - field->parent->fields;
7072 g_assert (index >= 0 && index < field->parent->field.count);
7078 * mono_class_get_field_default_value:
7080 * Return the default value of the field as a pointer into the metadata blob.
7083 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7086 guint32 constant_cols [MONO_CONSTANT_SIZE];
7088 MonoClass *klass = field->parent;
7090 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7092 if (!klass->ext || !klass->ext->field_def_values) {
7093 MonoFieldDefaultValue *def_values;
7095 mono_class_alloc_ext (klass);
7097 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7099 mono_image_lock (klass->image);
7100 mono_memory_barrier ();
7101 if (!klass->ext->field_def_values)
7102 klass->ext->field_def_values = def_values;
7103 mono_image_unlock (klass->image);
7106 field_index = mono_field_get_index (field);
7108 if (!klass->ext->field_def_values [field_index].data) {
7109 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7113 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7115 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7116 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7117 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7120 *def_type = klass->ext->field_def_values [field_index].def_type;
7121 return klass->ext->field_def_values [field_index].data;
7125 mono_property_get_index (MonoProperty *prop)
7127 int index = prop - prop->parent->ext->properties;
7129 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7135 * mono_class_get_property_default_value:
7137 * Return the default value of the field as a pointer into the metadata blob.
7140 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7143 guint32 constant_cols [MONO_CONSTANT_SIZE];
7144 MonoClass *klass = property->parent;
7146 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7148 * We don't cache here because it is not used by C# so it's quite rare, but
7149 * we still do the lookup in klass->ext because that is where the data
7150 * is stored for dynamic assemblies.
7153 if (image_is_dynamic (klass->image)) {
7154 int prop_index = mono_property_get_index (property);
7155 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7156 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7157 return klass->ext->prop_def_values [prop_index].data;
7161 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7165 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7166 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7167 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7171 mono_class_get_event_token (MonoEvent *event)
7173 MonoClass *klass = event->parent;
7178 for (i = 0; i < klass->ext->event.count; ++i) {
7179 if (&klass->ext->events [i] == event)
7180 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7183 klass = klass->parent;
7186 g_assert_not_reached ();
7191 * mono_class_get_property_from_name:
7193 * @name: name of the property to lookup in the specified class
7195 * Use this method to lookup a property in a class
7196 * Returns: the MonoProperty with the given name, or NULL if the property
7197 * does not exist on the @klass.
7200 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7204 gpointer iter = NULL;
7205 while ((p = mono_class_get_properties (klass, &iter))) {
7206 if (! strcmp (name, p->name))
7209 klass = klass->parent;
7215 * mono_class_get_property_token:
7216 * @prop: MonoProperty to query
7218 * Returns: The ECMA token for the specified property.
7221 mono_class_get_property_token (MonoProperty *prop)
7223 MonoClass *klass = prop->parent;
7227 gpointer iter = NULL;
7228 while ((p = mono_class_get_properties (klass, &iter))) {
7229 if (&klass->ext->properties [i] == prop)
7230 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7234 klass = klass->parent;
7237 g_assert_not_reached ();
7242 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7244 const char *name, *nspace;
7245 if (image_is_dynamic (image))
7246 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7248 switch (type_token & 0xff000000){
7249 case MONO_TOKEN_TYPE_DEF: {
7250 guint32 cols [MONO_TYPEDEF_SIZE];
7251 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7252 guint tidx = mono_metadata_token_index (type_token);
7254 if (tidx > tt->rows)
7255 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7257 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7258 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7259 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7260 if (strlen (nspace) == 0)
7261 return g_strdup_printf ("%s", name);
7263 return g_strdup_printf ("%s.%s", nspace, name);
7266 case MONO_TOKEN_TYPE_REF: {
7268 guint32 cols [MONO_TYPEREF_SIZE];
7269 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7270 guint tidx = mono_metadata_token_index (type_token);
7273 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7275 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7276 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7277 mono_error_cleanup (&error);
7281 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7282 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7283 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7284 if (strlen (nspace) == 0)
7285 return g_strdup_printf ("%s", name);
7287 return g_strdup_printf ("%s.%s", nspace, name);
7290 case MONO_TOKEN_TYPE_SPEC:
7291 return g_strdup_printf ("Typespec 0x%08x", type_token);
7293 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7298 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7300 if (image_is_dynamic (image))
7301 return g_strdup_printf ("DynamicAssembly %s", image->name);
7303 switch (type_token & 0xff000000){
7304 case MONO_TOKEN_TYPE_DEF:
7305 if (image->assembly)
7306 return mono_stringify_assembly_name (&image->assembly->aname);
7307 else if (image->assembly_name)
7308 return g_strdup (image->assembly_name);
7309 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7310 case MONO_TOKEN_TYPE_REF: {
7312 MonoAssemblyName aname;
7313 guint32 cols [MONO_TYPEREF_SIZE];
7314 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7315 guint32 idx = mono_metadata_token_index (type_token);
7318 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7320 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7321 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7322 mono_error_cleanup (&error);
7325 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7327 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7328 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7329 case MONO_RESOLUTION_SCOPE_MODULE:
7331 return g_strdup ("");
7332 case MONO_RESOLUTION_SCOPE_MODULEREF:
7334 return g_strdup ("");
7335 case MONO_RESOLUTION_SCOPE_TYPEREF:
7337 return g_strdup ("");
7338 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7339 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7340 return mono_stringify_assembly_name (&aname);
7342 g_assert_not_reached ();
7346 case MONO_TOKEN_TYPE_SPEC:
7348 return g_strdup ("");
7350 g_assert_not_reached ();
7357 * mono_class_get_full:
7358 * @image: the image where the class resides
7359 * @type_token: the token for the class
7360 * @context: the generic context used to evaluate generic instantiations in
7361 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7363 * Returns: The MonoClass that represents @type_token in @image
7366 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7370 klass = mono_class_get_checked (image, type_token, &error);
7372 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7373 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7375 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7381 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7385 mono_error_init (error);
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);
7394 * mono_class_get_checked:
7395 * @image: the image where the class resides
7396 * @type_token: the token for the class
7397 * @error: error object to return any error
7399 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7402 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7404 MonoClass *klass = NULL;
7406 mono_error_init (error);
7408 if (image_is_dynamic (image)) {
7409 int table = mono_metadata_token_table (type_token);
7411 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7412 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7415 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7419 switch (type_token & 0xff000000){
7420 case MONO_TOKEN_TYPE_DEF:
7421 klass = mono_class_create_from_typedef (image, type_token, error);
7423 case MONO_TOKEN_TYPE_REF:
7424 klass = mono_class_from_typeref_checked (image, type_token, error);
7426 case MONO_TOKEN_TYPE_SPEC:
7427 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7430 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7434 /* Generic case, should be avoided for when a better error is possible. */
7435 if (!klass && mono_error_ok (error)) {
7436 char *name = mono_class_name_from_token (image, type_token);
7437 char *assembly = mono_assembly_name_from_token (image, type_token);
7438 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7446 * mono_type_get_checked:
7447 * @image: the image where the type resides
7448 * @type_token: the token for the type
7449 * @context: the generic context used to evaluate generic instantiations in
7450 * @error: Error handling context
7452 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7454 * Returns: The MonoType that represents @type_token in @image
7457 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7459 MonoType *type = NULL;
7460 gboolean inflated = FALSE;
7462 mono_error_init (error);
7464 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7465 if (image_is_dynamic (image)) {
7466 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7467 return_val_if_nok (error, NULL);
7468 return mono_class_get_type (klass);
7471 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7472 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7479 return mono_class_get_type (klass);
7482 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7489 MonoType *tmp = type;
7490 type = mono_class_get_type (mono_class_from_mono_type (type));
7491 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7492 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7493 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7495 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7497 if (type->type != tmp->type)
7500 mono_metadata_free_type (tmp);
7507 * @image: image where the class token will be looked up.
7508 * @type_token: a type token from the image
7510 * Returns the MonoClass with the given @type_token on the @image
7513 mono_class_get (MonoImage *image, guint32 type_token)
7515 return mono_class_get_full (image, type_token, NULL);
7519 * mono_image_init_name_cache:
7521 * Initializes the class name cache stored in image->name_cache.
7523 * LOCKING: Acquires the corresponding image lock.
7526 mono_image_init_name_cache (MonoImage *image)
7528 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7529 guint32 cols [MONO_TYPEDEF_SIZE];
7532 guint32 i, visib, nspace_index;
7533 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7535 if (image->name_cache)
7538 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7540 if (image_is_dynamic (image)) {
7541 mono_image_lock (image);
7542 if (image->name_cache) {
7543 /* Somebody initialized it before us */
7544 g_hash_table_destroy (the_name_cache);
7546 mono_atomic_store_release (&image->name_cache, the_name_cache);
7548 mono_image_unlock (image);
7552 /* Temporary hash table to avoid lookups in the nspace_table */
7553 name_cache2 = g_hash_table_new (NULL, NULL);
7555 for (i = 1; i <= t->rows; ++i) {
7556 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7557 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7559 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7560 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7562 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7564 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7565 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7567 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7568 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7569 if (!nspace_table) {
7570 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7571 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7572 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7575 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7578 /* Load type names from EXPORTEDTYPES table */
7580 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7581 guint32 cols [MONO_EXP_TYPE_SIZE];
7584 for (i = 0; i < t->rows; ++i) {
7585 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7587 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7588 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7592 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7593 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7595 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7596 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7597 if (!nspace_table) {
7598 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7599 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7600 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7603 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7607 g_hash_table_destroy (name_cache2);
7609 mono_image_lock (image);
7610 if (image->name_cache) {
7611 /* Somebody initialized it before us */
7612 g_hash_table_destroy (the_name_cache);
7614 mono_atomic_store_release (&image->name_cache, the_name_cache);
7616 mono_image_unlock (image);
7619 /*FIXME Only dynamic assemblies should allow this operation.*/
7621 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7622 const char *name, guint32 index)
7624 GHashTable *nspace_table;
7625 GHashTable *name_cache;
7628 mono_image_init_name_cache (image);
7629 mono_image_lock (image);
7631 name_cache = image->name_cache;
7632 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7633 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7634 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7637 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7638 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7640 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7642 mono_image_unlock (image);
7651 find_nocase (gpointer key, gpointer value, gpointer user_data)
7653 char *name = (char*)key;
7654 FindUserData *data = (FindUserData*)user_data;
7656 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7657 data->value = value;
7661 * mono_class_from_name_case:
7662 * @image: The MonoImage where the type is looked up in
7663 * @name_space: the type namespace
7664 * @name: the type short name.
7665 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7667 * Obtains a MonoClass with a given namespace and a given name which
7668 * is located in the given MonoImage. The namespace and name
7669 * lookups are case insensitive.
7672 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7675 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7676 mono_error_cleanup (&error);
7682 * mono_class_from_name_case:
7683 * @image: The MonoImage where the type is looked up in
7684 * @name_space: the type namespace
7685 * @name: the type short name.
7688 * Obtains a MonoClass with a given namespace and a given name which
7689 * is located in the given MonoImage. The namespace and name
7690 * lookups are case insensitive.
7692 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7693 * was not found. The @error object will contain information about the problem
7697 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7699 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7700 guint32 cols [MONO_TYPEDEF_SIZE];
7705 mono_error_init (error);
7707 if (image_is_dynamic (image)) {
7709 FindUserData user_data;
7711 mono_image_init_name_cache (image);
7712 mono_image_lock (image);
7714 user_data.key = name_space;
7715 user_data.value = NULL;
7716 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7718 if (user_data.value) {
7719 GHashTable *nspace_table = (GHashTable*)user_data.value;
7721 user_data.key = name;
7722 user_data.value = NULL;
7724 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7726 if (user_data.value)
7727 token = GPOINTER_TO_UINT (user_data.value);
7730 mono_image_unlock (image);
7733 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7739 /* add a cache if needed */
7740 for (i = 1; i <= t->rows; ++i) {
7741 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7742 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7744 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7745 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7747 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7749 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7750 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7751 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7752 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7758 return_nested_in (MonoClass *klass, char *nested)
7761 char *s = strchr (nested, '/');
7762 gpointer iter = NULL;
7769 while ((found = mono_class_get_nested_types (klass, &iter))) {
7770 if (strcmp (found->name, nested) == 0) {
7772 return return_nested_in (found, s);
7780 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7782 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7783 MonoImage *file_image;
7787 mono_error_init (error);
7790 * The EXPORTEDTYPES table only contains public types, so have to search the
7792 * Note: image->modules contains the contents of the MODULEREF table, while
7793 * the real module list is in the FILE table.
7795 for (i = 0; i < file_table->rows; i++) {
7796 guint32 cols [MONO_FILE_SIZE];
7797 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7798 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7801 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7803 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7804 if (klass || !is_ok (error))
7813 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7815 GHashTable *nspace_table;
7816 MonoImage *loaded_image;
7823 mono_error_init (error);
7825 // Checking visited images avoids stack overflows when cyclic references exist.
7826 if (g_hash_table_lookup (visited_images, image))
7829 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7831 if ((nested = strchr (name, '/'))) {
7832 int pos = nested - name;
7833 int len = strlen (name);
7836 memcpy (buf, name, len + 1);
7838 nested = buf + pos + 1;
7842 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7843 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7844 gboolean res = get_class_from_name (image, name_space, name, &klass);
7847 klass = search_modules (image, name_space, name, error);
7852 return klass ? return_nested_in (klass, nested) : NULL;
7858 mono_image_init_name_cache (image);
7859 mono_image_lock (image);
7861 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7864 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7866 mono_image_unlock (image);
7868 if (!token && image_is_dynamic (image) && image->modules) {
7869 /* Search modules as well */
7870 for (i = 0; i < image->module_count; ++i) {
7871 MonoImage *module = image->modules [i];
7873 klass = mono_class_from_name_checked (module, name_space, name, error);
7874 if (klass || !is_ok (error))
7880 klass = search_modules (image, name_space, name, error);
7881 if (klass || !is_ok (error))
7886 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7887 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7888 guint32 cols [MONO_EXP_TYPE_SIZE];
7891 idx = mono_metadata_token_index (token);
7893 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7895 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7896 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7897 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7900 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7902 return klass ? return_nested_in (klass, nested) : NULL;
7904 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7905 guint32 assembly_idx;
7907 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7909 mono_assembly_load_reference (image, assembly_idx - 1);
7910 g_assert (image->references [assembly_idx - 1]);
7911 if (image->references [assembly_idx - 1] == (gpointer)-1)
7913 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7915 return klass ? return_nested_in (klass, nested) : NULL;
7918 g_assert_not_reached ();
7922 token = MONO_TOKEN_TYPE_DEF | token;
7924 klass = mono_class_get_checked (image, token, error);
7926 return return_nested_in (klass, nested);
7931 * mono_class_from_name_checked:
7932 * @image: The MonoImage where the type is looked up in
7933 * @name_space: the type namespace
7934 * @name: the type short name.
7936 * Obtains a MonoClass with a given namespace and a given name which
7937 * is located in the given MonoImage.
7939 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7940 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7943 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7946 GHashTable *visited_images;
7948 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7950 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7952 g_hash_table_destroy (visited_images);
7958 * mono_class_from_name:
7959 * @image: The MonoImage where the type is looked up in
7960 * @name_space: the type namespace
7961 * @name: the type short name.
7963 * Obtains a MonoClass with a given namespace and a given name which
7964 * is located in the given MonoImage.
7966 * To reference nested classes, use the "/" character as a separator.
7967 * For example use "Foo/Bar" to reference the class Bar that is nested
7968 * inside Foo, like this: "class Foo { class Bar {} }".
7971 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7976 klass = mono_class_from_name_checked (image, name_space, name, &error);
7977 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7983 * mono_class_load_from_name:
7984 * @image: The MonoImage where the type is looked up in
7985 * @name_space: the type namespace
7986 * @name: the type short name.
7988 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7989 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7990 * If they are missing. Thing of System.Object or System.String.
7993 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7998 klass = mono_class_from_name_checked (image, name_space, name, &error);
8000 g_error ("Runtime critical type %s.%s not found", name_space, name);
8001 if (!mono_error_ok (&error))
8002 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8007 * mono_class_try_load_from_name:
8008 * @image: The MonoImage where the type is looked up in
8009 * @name_space: the type namespace
8010 * @name: the type short name.
8012 * This function tries to load a type, returning the class was found or NULL otherwise.
8013 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8015 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8016 * a type that we would otherwise assume to be available but was not due some error.
8020 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8025 klass = mono_class_from_name_checked (image, name_space, name, &error);
8026 if (!mono_error_ok (&error))
8027 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8033 * mono_class_is_subclass_of:
8034 * @klass: class to probe if it is a subclass of another one
8035 * @klassc: the class we suspect is the base class
8036 * @check_interfaces: whether we should perform interface checks
8038 * This method determines whether @klass is a subclass of @klassc.
8040 * If the @check_interfaces flag is set, then if @klassc is an interface
8041 * this method return TRUE if the @klass implements the interface or
8042 * if @klass is an interface, if one of its base classes is @klass.
8044 * If @check_interfaces is false then, then if @klass is not an interface
8045 * then it returns TRUE if the @klass is a subclass of @klassc.
8047 * if @klass is an interface and @klassc is System.Object, then this function
8052 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8053 gboolean check_interfaces)
8055 /* FIXME test for interfaces with variant generic arguments */
8056 mono_class_init (klass);
8057 mono_class_init (klassc);
8059 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8060 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8062 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8065 for (i = 0; i < klass->interface_count; i ++) {
8066 MonoClass *ic = klass->interfaces [i];
8071 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8076 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8079 if (klassc == mono_defaults.object_class)
8086 mono_type_is_generic_argument (MonoType *type)
8088 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8092 mono_class_has_variant_generic_params (MonoClass *klass)
8095 MonoGenericContainer *container;
8097 if (!mono_class_is_ginst (klass))
8100 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8102 for (i = 0; i < container->type_argc; ++i)
8103 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8110 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8112 if (target == candidate)
8115 if (check_for_reference_conv &&
8116 mono_type_is_generic_argument (&target->byval_arg) &&
8117 mono_type_is_generic_argument (&candidate->byval_arg)) {
8118 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8119 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8121 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8124 if (!mono_class_is_assignable_from (target, candidate))
8130 * @container the generic container from the GTD
8131 * @klass: the class to be assigned to
8132 * @oklass: the source class
8134 * Both @klass and @oklass must be instances of the same generic interface.
8136 * Returns: TRUE if @klass can be assigned to a @klass variable
8139 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8142 MonoType **klass_argv, **oklass_argv;
8143 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8144 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8146 if (klass == oklass)
8149 /*Viable candidates are instances of the same generic interface*/
8150 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8153 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8154 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8156 for (j = 0; j < container->type_argc; ++j) {
8157 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8158 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8160 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8164 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8165 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8167 if (param1_class != param2_class) {
8168 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8169 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8171 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8172 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8182 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8184 MonoGenericParam *gparam, *ogparam;
8185 MonoGenericParamInfo *tinfo, *cinfo;
8186 MonoClass **candidate_class;
8187 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8190 if (target == candidate)
8192 if (target->byval_arg.type != candidate->byval_arg.type)
8195 gparam = target->byval_arg.data.generic_param;
8196 ogparam = candidate->byval_arg.data.generic_param;
8197 tinfo = mono_generic_param_info (gparam);
8198 cinfo = mono_generic_param_info (ogparam);
8200 class_constraint_satisfied = FALSE;
8201 valuetype_constraint_satisfied = FALSE;
8203 /*candidate must have a super set of target's special constraints*/
8204 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8205 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8207 if (cinfo->constraints) {
8208 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8209 MonoClass *cc = *candidate_class;
8211 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8212 class_constraint_satisfied = TRUE;
8213 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8214 valuetype_constraint_satisfied = TRUE;
8217 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8218 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8220 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8222 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8224 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8225 valuetype_constraint_satisfied)) {
8230 /*candidate type constraints must be a superset of target's*/
8231 if (tinfo->constraints) {
8232 MonoClass **target_class;
8233 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8234 MonoClass *tc = *target_class;
8237 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8238 * check it's constraints since it satisfy the constraint by itself.
8240 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8243 if (!cinfo->constraints)
8246 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8247 MonoClass *cc = *candidate_class;
8249 if (mono_class_is_assignable_from (tc, cc))
8253 * This happens when we have the following:
8255 * Bar<K> where K : IFace
8256 * Foo<T, U> where T : U where U : IFace
8258 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8261 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8262 if (mono_gparam_is_assignable_from (target, cc))
8266 if (!*candidate_class)
8271 /*candidate itself must have a constraint that satisfy target*/
8272 if (cinfo->constraints) {
8273 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8274 MonoClass *cc = *candidate_class;
8275 if (mono_class_is_assignable_from (target, cc))
8283 * mono_class_is_assignable_from:
8284 * @klass: the class to be assigned to
8285 * @oklass: the source class
8287 * Returns: TRUE if an instance of object oklass can be assigned to an
8288 * instance of object @klass
8291 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8294 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8296 mono_class_init (klass);
8298 if (!oklass->inited)
8299 mono_class_init (oklass);
8301 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8304 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8305 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8307 return mono_gparam_is_assignable_from (klass, oklass);
8310 if (MONO_CLASS_IS_INTERFACE (klass)) {
8311 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8312 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8313 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8317 for (i = 0; constraints [i]; ++i) {
8318 if (mono_class_is_assignable_from (klass, constraints [i]))
8326 /* interface_offsets might not be set for dynamic classes */
8327 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8329 * oklass might be a generic type parameter but they have
8330 * interface_offsets set.
8332 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8333 if (!is_ok (&error)) {
8334 mono_error_cleanup (&error);
8339 if (!oklass->interface_bitmap)
8340 /* Happens with generic instances of not-yet created dynamic types */
8342 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8345 if (mono_class_has_variant_generic_params (klass)) {
8347 mono_class_setup_interfaces (oklass, &error);
8348 if (!mono_error_ok (&error)) {
8349 mono_error_cleanup (&error);
8353 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8354 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8355 MonoClass *iface = oklass->interfaces_packed [i];
8357 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8362 } else if (klass->delegate) {
8363 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8365 }else if (klass->rank) {
8366 MonoClass *eclass, *eoclass;
8368 if (oklass->rank != klass->rank)
8371 /* vectors vs. one dimensional arrays */
8372 if (oklass->byval_arg.type != klass->byval_arg.type)
8375 eclass = klass->cast_class;
8376 eoclass = oklass->cast_class;
8379 * a is b does not imply a[] is b[] when a is a valuetype, and
8380 * b is a reference type.
8383 if (eoclass->valuetype) {
8384 if ((eclass == mono_defaults.enum_class) ||
8385 (eclass == mono_defaults.enum_class->parent) ||
8386 (eclass == mono_defaults.object_class))
8390 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8391 } else if (mono_class_is_nullable (klass)) {
8392 if (mono_class_is_nullable (oklass))
8393 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8395 return mono_class_is_assignable_from (klass->cast_class, oklass);
8396 } else if (klass == mono_defaults.object_class)
8399 return mono_class_has_parent (oklass, klass);
8402 /*Check if @oklass is variant compatible with @klass.*/
8404 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8407 MonoType **klass_argv, **oklass_argv;
8408 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8409 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8411 /*Viable candidates are instances of the same generic interface*/
8412 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8415 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8416 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8418 for (j = 0; j < container->type_argc; ++j) {
8419 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8420 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8422 if (param1_class->valuetype != param2_class->valuetype)
8426 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8427 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8429 if (param1_class != param2_class) {
8430 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8431 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8433 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8434 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8442 /*Check if @candidate implements the interface @target*/
8444 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8448 gboolean is_variant = mono_class_has_variant_generic_params (target);
8450 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8451 if (mono_class_is_variant_compatible_slow (target, candidate))
8456 if (candidate == target)
8459 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8460 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8461 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8463 if (tb && tb->interfaces) {
8464 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8465 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8466 MonoClass *iface_class;
8468 /* we can't realize the type here since it can do pretty much anything. */
8471 iface_class = mono_class_from_mono_type (iface->type);
8472 if (iface_class == target)
8474 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8476 if (mono_class_implement_interface_slow (target, iface_class))
8481 /*setup_interfaces don't mono_class_init anything*/
8482 /*FIXME this doesn't handle primitive type arrays.
8483 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8484 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8486 mono_class_setup_interfaces (candidate, &error);
8487 if (!mono_error_ok (&error)) {
8488 mono_error_cleanup (&error);
8492 for (i = 0; i < candidate->interface_count; ++i) {
8493 if (candidate->interfaces [i] == target)
8496 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8499 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8503 candidate = candidate->parent;
8504 } while (candidate);
8510 * Check if @oklass can be assigned to @klass.
8511 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8514 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8516 if (candidate == target)
8518 if (target == mono_defaults.object_class)
8521 if (mono_class_has_parent (candidate, target))
8524 /*If target is not an interface there is no need to check them.*/
8525 if (MONO_CLASS_IS_INTERFACE (target))
8526 return mono_class_implement_interface_slow (target, candidate);
8528 if (target->delegate && mono_class_has_variant_generic_params (target))
8529 return mono_class_is_variant_compatible (target, candidate, FALSE);
8532 MonoClass *eclass, *eoclass;
8534 if (target->rank != candidate->rank)
8537 /* vectors vs. one dimensional arrays */
8538 if (target->byval_arg.type != candidate->byval_arg.type)
8541 eclass = target->cast_class;
8542 eoclass = candidate->cast_class;
8545 * a is b does not imply a[] is b[] when a is a valuetype, and
8546 * b is a reference type.
8549 if (eoclass->valuetype) {
8550 if ((eclass == mono_defaults.enum_class) ||
8551 (eclass == mono_defaults.enum_class->parent) ||
8552 (eclass == mono_defaults.object_class))
8556 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8558 /*FIXME properly handle nullables */
8559 /*FIXME properly handle (M)VAR */
8564 * mono_class_get_cctor:
8565 * @klass: A MonoClass pointer
8567 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8570 mono_class_get_cctor (MonoClass *klass)
8572 MonoCachedClassInfo cached_info;
8574 if (image_is_dynamic (klass->image)) {
8576 * has_cctor is not set for these classes because mono_class_init () is
8579 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8582 if (!klass->has_cctor)
8585 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8587 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8588 if (!mono_error_ok (&error))
8589 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8593 if (mono_class_is_ginst (klass) && !klass->methods)
8594 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8596 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8600 * mono_class_get_finalizer:
8601 * @klass: The MonoClass pointer
8603 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8606 mono_class_get_finalizer (MonoClass *klass)
8608 MonoCachedClassInfo cached_info;
8611 mono_class_init (klass);
8612 if (!mono_class_has_finalizer (klass))
8615 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8617 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8618 if (!mono_error_ok (&error))
8619 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8622 mono_class_setup_vtable (klass);
8623 return klass->vtable [finalize_slot];
8628 * mono_class_needs_cctor_run:
8629 * @klass: the MonoClass pointer
8630 * @caller: a MonoMethod describing the caller
8632 * Determines whenever the class has a static constructor and whenever it
8633 * needs to be called when executing CALLER.
8636 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8640 method = mono_class_get_cctor (klass);
8642 return (method == caller) ? FALSE : TRUE;
8648 * mono_class_array_element_size:
8651 * Returns: The number of bytes an element of type @klass
8652 * uses when stored into an array.
8655 mono_class_array_element_size (MonoClass *klass)
8657 MonoType *type = &klass->byval_arg;
8660 switch (type->type) {
8663 case MONO_TYPE_BOOLEAN:
8667 case MONO_TYPE_CHAR:
8676 case MONO_TYPE_CLASS:
8677 case MONO_TYPE_STRING:
8678 case MONO_TYPE_OBJECT:
8679 case MONO_TYPE_SZARRAY:
8680 case MONO_TYPE_ARRAY:
8681 return sizeof (gpointer);
8686 case MONO_TYPE_VALUETYPE:
8687 if (type->data.klass->enumtype) {
8688 type = mono_class_enum_basetype (type->data.klass);
8689 klass = klass->element_class;
8692 return mono_class_instance_size (klass) - sizeof (MonoObject);
8693 case MONO_TYPE_GENERICINST:
8694 type = &type->data.generic_class->container_class->byval_arg;
8697 case MONO_TYPE_MVAR: {
8700 return mono_type_size (type, &align);
8702 case MONO_TYPE_VOID:
8706 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8712 * mono_array_element_size:
8713 * @ac: pointer to a #MonoArrayClass
8715 * Returns: The size of single array element.
8718 mono_array_element_size (MonoClass *ac)
8720 g_assert (ac->rank);
8721 return ac->sizes.element_size;
8725 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8726 MonoGenericContext *context)
8729 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8730 g_assert (mono_error_ok (&error));
8735 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8736 MonoGenericContext *context, MonoError *error)
8738 mono_error_init (error);
8740 if (image_is_dynamic (image)) {
8741 MonoClass *tmp_handle_class;
8742 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8744 mono_error_assert_ok (error);
8745 g_assert (tmp_handle_class);
8747 *handle_class = tmp_handle_class;
8749 if (tmp_handle_class == mono_defaults.typehandle_class)
8750 return &((MonoClass*)obj)->byval_arg;
8755 switch (token & 0xff000000) {
8756 case MONO_TOKEN_TYPE_DEF:
8757 case MONO_TOKEN_TYPE_REF:
8758 case MONO_TOKEN_TYPE_SPEC: {
8761 *handle_class = mono_defaults.typehandle_class;
8762 type = mono_type_get_checked (image, token, context, error);
8766 mono_class_init (mono_class_from_mono_type (type));
8767 /* We return a MonoType* as handle */
8770 case MONO_TOKEN_FIELD_DEF: {
8772 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8774 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8778 *handle_class = mono_defaults.fieldhandle_class;
8779 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8783 mono_class_init (klass);
8784 return mono_class_get_field (klass, token);
8786 case MONO_TOKEN_METHOD_DEF:
8787 case MONO_TOKEN_METHOD_SPEC: {
8789 meth = mono_get_method_checked (image, token, NULL, context, error);
8791 *handle_class = mono_defaults.methodhandle_class;
8797 case MONO_TOKEN_MEMBER_REF: {
8798 guint32 cols [MONO_MEMBERREF_SIZE];
8800 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8801 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8802 mono_metadata_decode_blob_size (sig, &sig);
8803 if (*sig == 0x6) { /* it's a field */
8805 MonoClassField *field;
8806 field = mono_field_from_token_checked (image, token, &klass, context, error);
8808 *handle_class = mono_defaults.fieldhandle_class;
8812 meth = mono_get_method_checked (image, token, NULL, context, error);
8814 *handle_class = mono_defaults.methodhandle_class;
8819 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8825 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8827 MonoClass *handle_class;
8828 mono_error_init (error);
8829 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8833 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8835 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8838 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8841 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8843 get_cached_class_info = func;
8847 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8849 if (!get_cached_class_info)
8852 return get_cached_class_info (klass, res);
8856 mono_install_get_class_from_name (MonoGetClassFromName func)
8858 get_class_from_name = func;
8862 * mono_class_get_image:
8864 * Use this method to get the `MonoImage*` where this class came from.
8866 * Returns: The image where this class is defined.
8869 mono_class_get_image (MonoClass *klass)
8871 return klass->image;
8875 * mono_class_get_element_class:
8876 * @klass: the MonoClass to act on
8878 * Use this function to get the element class of an array.
8880 * Returns: The element class of an array.
8883 mono_class_get_element_class (MonoClass *klass)
8885 return klass->element_class;
8889 * mono_class_is_valuetype:
8890 * @klass: the MonoClass to act on
8892 * Use this method to determine if the provided `MonoClass*` represents a value type,
8893 * or a reference type.
8895 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8898 mono_class_is_valuetype (MonoClass *klass)
8900 return klass->valuetype;
8904 * mono_class_is_enum:
8905 * @klass: the MonoClass to act on
8907 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8909 * Returns: TRUE if the MonoClass represents an enumeration.
8912 mono_class_is_enum (MonoClass *klass)
8914 return klass->enumtype;
8918 * mono_class_enum_basetype:
8919 * @klass: the MonoClass to act on
8921 * Use this function to get the underlying type for an enumeration value.
8923 * Returns: The underlying type representation for an enumeration.
8926 mono_class_enum_basetype (MonoClass *klass)
8928 if (klass->element_class == klass)
8929 /* SRE or broken types */
8932 return &klass->element_class->byval_arg;
8936 * mono_class_get_parent
8937 * @klass: the MonoClass to act on
8939 * Returns: The parent class for this class.
8942 mono_class_get_parent (MonoClass *klass)
8944 return klass->parent;
8948 * mono_class_get_nesting_type:
8949 * @klass: the MonoClass to act on
8951 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8953 * If the return is NULL, this indicates that this class is not nested.
8955 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8958 mono_class_get_nesting_type (MonoClass *klass)
8960 return klass->nested_in;
8964 * mono_class_get_rank:
8965 * @klass: the MonoClass to act on
8967 * Returns: The rank for the array (the number of dimensions).
8970 mono_class_get_rank (MonoClass *klass)
8976 * mono_class_get_name
8977 * @klass: the MonoClass to act on
8979 * Returns: The name of the class.
8982 mono_class_get_name (MonoClass *klass)
8988 * mono_class_get_namespace:
8989 * @klass: the MonoClass to act on
8991 * Returns: The namespace of the class.
8994 mono_class_get_namespace (MonoClass *klass)
8996 return klass->name_space;
9000 * mono_class_get_type:
9001 * @klass: the MonoClass to act on
9003 * This method returns the internal Type representation for the class.
9005 * Returns: The MonoType from the class.
9008 mono_class_get_type (MonoClass *klass)
9010 return &klass->byval_arg;
9014 * mono_class_get_type_token:
9015 * @klass: the MonoClass to act on
9017 * This method returns type token for the class.
9019 * Returns: The type token for the class.
9022 mono_class_get_type_token (MonoClass *klass)
9024 return klass->type_token;
9028 * mono_class_get_byref_type:
9029 * @klass: the MonoClass to act on
9034 mono_class_get_byref_type (MonoClass *klass)
9036 return &klass->this_arg;
9040 * mono_class_num_fields:
9041 * @klass: the MonoClass to act on
9043 * Returns: The number of static and instance fields in the class.
9046 mono_class_num_fields (MonoClass *klass)
9048 return klass->field.count;
9052 * mono_class_num_methods:
9053 * @klass: the MonoClass to act on
9055 * Returns: The number of methods in the class.
9058 mono_class_num_methods (MonoClass *klass)
9060 return klass->method.count;
9064 * mono_class_num_properties
9065 * @klass: the MonoClass to act on
9067 * Returns: The number of properties in the class.
9070 mono_class_num_properties (MonoClass *klass)
9072 mono_class_setup_properties (klass);
9074 return klass->ext->property.count;
9078 * mono_class_num_events:
9079 * @klass: the MonoClass to act on
9081 * Returns: The number of events in the class.
9084 mono_class_num_events (MonoClass *klass)
9086 mono_class_setup_events (klass);
9088 return klass->ext->event.count;
9092 * mono_class_get_fields:
9093 * @klass: the MonoClass to act on
9095 * This routine is an iterator routine for retrieving the fields in a class.
9097 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9098 * iterate over all of the elements. When no more values are
9099 * available, the return value is NULL.
9101 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9104 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9106 MonoClassField* field;
9110 mono_class_setup_fields (klass);
9111 if (mono_class_has_failure (klass))
9113 /* start from the first */
9114 if (klass->field.count) {
9115 *iter = &klass->fields [0];
9116 return &klass->fields [0];
9122 field = (MonoClassField *)*iter;
9124 if (field < &klass->fields [klass->field.count]) {
9132 * mono_class_get_methods
9133 * @klass: the MonoClass to act on
9135 * This routine is an iterator routine for retrieving the fields in a class.
9137 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9138 * iterate over all of the elements. When no more values are
9139 * available, the return value is NULL.
9141 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9144 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9146 MonoMethod** method;
9150 mono_class_setup_methods (klass);
9153 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9154 * FIXME we should better report this error to the caller
9156 if (!klass->methods)
9158 /* start from the first */
9159 if (klass->method.count) {
9160 *iter = &klass->methods [0];
9161 return klass->methods [0];
9167 method = (MonoMethod **)*iter;
9169 if (method < &klass->methods [klass->method.count]) {
9177 * mono_class_get_virtual_methods:
9179 * Iterate over the virtual methods of KLASS.
9181 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9184 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9186 MonoMethod** method;
9189 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9191 mono_class_setup_methods (klass);
9193 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9194 * FIXME we should better report this error to the caller
9196 if (!klass->methods)
9198 /* start from the first */
9199 method = &klass->methods [0];
9201 method = (MonoMethod **)*iter;
9204 while (method < &klass->methods [klass->method.count]) {
9205 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9209 if (method < &klass->methods [klass->method.count]) {
9216 /* Search directly in metadata to avoid calling setup_methods () */
9217 MonoMethod *res = NULL;
9223 start_index = GPOINTER_TO_UINT (*iter);
9226 for (i = start_index; i < klass->method.count; ++i) {
9229 /* klass->method.first points into the methodptr table */
9230 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9232 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9236 if (i < klass->method.count) {
9238 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9239 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9241 /* Add 1 here so the if (*iter) check fails */
9242 *iter = GUINT_TO_POINTER (i + 1);
9251 * mono_class_get_properties:
9252 * @klass: the MonoClass to act on
9254 * This routine is an iterator routine for retrieving the properties in a class.
9256 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9257 * iterate over all of the elements. When no more values are
9258 * available, the return value is NULL.
9260 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9263 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9265 MonoProperty* property;
9269 mono_class_setup_properties (klass);
9270 /* start from the first */
9271 if (klass->ext->property.count) {
9272 *iter = &klass->ext->properties [0];
9273 return (MonoProperty *)*iter;
9279 property = (MonoProperty *)*iter;
9281 if (property < &klass->ext->properties [klass->ext->property.count]) {
9283 return (MonoProperty *)*iter;
9289 * mono_class_get_events:
9290 * @klass: the MonoClass to act on
9292 * This routine is an iterator routine for retrieving the properties in a class.
9294 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9295 * iterate over all of the elements. When no more values are
9296 * available, the return value is NULL.
9298 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9301 mono_class_get_events (MonoClass* klass, gpointer *iter)
9307 mono_class_setup_events (klass);
9308 /* start from the first */
9309 if (klass->ext->event.count) {
9310 *iter = &klass->ext->events [0];
9311 return (MonoEvent *)*iter;
9317 event = (MonoEvent *)*iter;
9319 if (event < &klass->ext->events [klass->ext->event.count]) {
9321 return (MonoEvent *)*iter;
9327 * mono_class_get_interfaces
9328 * @klass: the MonoClass to act on
9330 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9332 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9333 * iterate over all of the elements. When no more values are
9334 * available, the return value is NULL.
9336 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9339 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9347 mono_class_init (klass);
9348 if (!klass->interfaces_inited) {
9349 mono_class_setup_interfaces (klass, &error);
9350 if (!mono_error_ok (&error)) {
9351 mono_error_cleanup (&error);
9355 /* start from the first */
9356 if (klass->interface_count) {
9357 *iter = &klass->interfaces [0];
9358 return klass->interfaces [0];
9364 iface = (MonoClass **)*iter;
9366 if (iface < &klass->interfaces [klass->interface_count]) {
9374 setup_nested_types (MonoClass *klass)
9377 GList *classes, *nested_classes, *l;
9380 if (klass->nested_classes_inited)
9383 if (!klass->type_token)
9384 klass->nested_classes_inited = TRUE;
9386 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9390 guint32 cols [MONO_NESTED_CLASS_SIZE];
9391 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9392 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9393 if (!mono_error_ok (&error)) {
9394 /*FIXME don't swallow the error message*/
9395 mono_error_cleanup (&error);
9397 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9401 classes = g_list_prepend (classes, nclass);
9403 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9406 mono_class_alloc_ext (klass);
9408 nested_classes = NULL;
9409 for (l = classes; l; l = l->next)
9410 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9411 g_list_free (classes);
9413 mono_image_lock (klass->image);
9415 mono_memory_barrier ();
9416 if (!klass->nested_classes_inited) {
9417 klass->ext->nested_classes = nested_classes;
9418 mono_memory_barrier ();
9419 klass->nested_classes_inited = TRUE;
9422 mono_image_unlock (klass->image);
9426 * mono_class_get_nested_types
9427 * @klass: the MonoClass to act on
9429 * This routine is an iterator routine for retrieving the nested types of a class.
9430 * This works only if @klass is non-generic, or a generic type definition.
9432 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9433 * iterate over all of the elements. When no more values are
9434 * available, the return value is NULL.
9436 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9439 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9445 if (!klass->nested_classes_inited)
9446 setup_nested_types (klass);
9449 /* start from the first */
9450 if (klass->ext && klass->ext->nested_classes) {
9451 *iter = klass->ext->nested_classes;
9452 return (MonoClass *)klass->ext->nested_classes->data;
9454 /* no nested types */
9458 item = (GList *)*iter;
9462 return (MonoClass *)item->data;
9469 * mono_class_is_delegate
9470 * @klass: the MonoClass to act on
9472 * Returns: TRUE if the MonoClass represents a System.Delegate.
9475 mono_class_is_delegate (MonoClass *klass)
9477 return klass->delegate;
9481 * mono_class_implements_interface
9482 * @klass: The MonoClass to act on
9483 * @interface: The interface to check if @klass implements.
9485 * Returns: TRUE if @klass implements @interface.
9488 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9490 return mono_class_is_assignable_from (iface, klass);
9494 * mono_field_get_name:
9495 * @field: the MonoClassField to act on
9497 * Returns: The name of the field.
9500 mono_field_get_name (MonoClassField *field)
9506 * mono_field_get_type:
9507 * @field: the MonoClassField to act on
9509 * Returns: MonoType of the field.
9512 mono_field_get_type (MonoClassField *field)
9515 MonoType *type = mono_field_get_type_checked (field, &error);
9516 if (!mono_error_ok (&error)) {
9517 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9518 mono_error_cleanup (&error);
9525 * mono_field_get_type_checked:
9526 * @field: the MonoClassField to act on
9527 * @error: used to return any erro found while retrieving @field type
9529 * Returns: MonoType of the field.
9532 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9534 mono_error_init (error);
9536 mono_field_resolve_type (field, error);
9541 * mono_field_get_parent:
9542 * @field: the MonoClassField to act on
9544 * Returns: MonoClass where the field was defined.
9547 mono_field_get_parent (MonoClassField *field)
9549 return field->parent;
9553 * mono_field_get_flags;
9554 * @field: the MonoClassField to act on
9556 * The metadata flags for a field are encoded using the
9557 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9559 * Returns: The flags for the field.
9562 mono_field_get_flags (MonoClassField *field)
9565 return mono_field_resolve_flags (field);
9566 return field->type->attrs;
9570 * mono_field_get_offset:
9571 * @field: the MonoClassField to act on
9573 * Returns: The field offset.
9576 mono_field_get_offset (MonoClassField *field)
9578 return field->offset;
9582 mono_field_get_rva (MonoClassField *field)
9586 MonoClass *klass = field->parent;
9587 MonoFieldDefaultValue *field_def_values;
9589 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9591 if (!klass->ext || !klass->ext->field_def_values) {
9592 mono_class_alloc_ext (klass);
9594 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9596 mono_image_lock (klass->image);
9597 if (!klass->ext->field_def_values)
9598 klass->ext->field_def_values = field_def_values;
9599 mono_image_unlock (klass->image);
9602 field_index = mono_field_get_index (field);
9604 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9605 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9607 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9608 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9611 return klass->ext->field_def_values [field_index].data;
9615 * mono_field_get_data:
9616 * @field: the MonoClassField to act on
9618 * Returns: A pointer to the metadata constant value or to the field
9619 * data if it has an RVA flag.
9622 mono_field_get_data (MonoClassField *field)
9624 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9625 MonoTypeEnum def_type;
9627 return mono_class_get_field_default_value (field, &def_type);
9628 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9629 return mono_field_get_rva (field);
9636 * mono_property_get_name:
9637 * @prop: the MonoProperty to act on
9639 * Returns: The name of the property
9642 mono_property_get_name (MonoProperty *prop)
9648 * mono_property_get_set_method
9649 * @prop: the MonoProperty to act on.
9651 * Returns: The setter method of the property (A MonoMethod)
9654 mono_property_get_set_method (MonoProperty *prop)
9660 * mono_property_get_get_method
9661 * @prop: the MonoProperty to act on.
9663 * Returns: The setter method of the property (A MonoMethod)
9666 mono_property_get_get_method (MonoProperty *prop)
9672 * mono_property_get_parent:
9673 * @prop: the MonoProperty to act on.
9675 * Returns: The MonoClass where the property was defined.
9678 mono_property_get_parent (MonoProperty *prop)
9680 return prop->parent;
9684 * mono_property_get_flags:
9685 * @prop: the MonoProperty to act on.
9687 * The metadata flags for a property are encoded using the
9688 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9690 * Returns: The flags for the property.
9693 mono_property_get_flags (MonoProperty *prop)
9699 * mono_event_get_name:
9700 * @event: the MonoEvent to act on
9702 * Returns: The name of the event.
9705 mono_event_get_name (MonoEvent *event)
9711 * mono_event_get_add_method:
9712 * @event: The MonoEvent to act on.
9714 * Returns: The @add' method for the event (a MonoMethod).
9717 mono_event_get_add_method (MonoEvent *event)
9723 * mono_event_get_remove_method:
9724 * @event: The MonoEvent to act on.
9726 * Returns: The @remove method for the event (a MonoMethod).
9729 mono_event_get_remove_method (MonoEvent *event)
9731 return event->remove;
9735 * mono_event_get_raise_method:
9736 * @event: The MonoEvent to act on.
9738 * Returns: The @raise method for the event (a MonoMethod).
9741 mono_event_get_raise_method (MonoEvent *event)
9743 return event->raise;
9747 * mono_event_get_parent:
9748 * @event: the MonoEvent to act on.
9750 * Returns: The MonoClass where the event is defined.
9753 mono_event_get_parent (MonoEvent *event)
9755 return event->parent;
9759 * mono_event_get_flags
9760 * @event: the MonoEvent to act on.
9762 * The metadata flags for an event are encoded using the
9763 * EVENT_* constants. See the tabledefs.h file for details.
9765 * Returns: The flags for the event.
9768 mono_event_get_flags (MonoEvent *event)
9770 return event->attrs;
9774 * mono_class_get_method_from_name:
9775 * @klass: where to look for the method
9776 * @name: name of the method
9777 * @param_count: number of parameters. -1 for any number.
9779 * Obtains a MonoMethod with a given name and number of parameters.
9780 * It only works if there are no multiple signatures for any given method name.
9783 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9785 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9789 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9791 MonoMethod *res = NULL;
9794 /* Search directly in the metadata to avoid calling setup_methods () */
9795 for (i = 0; i < klass->method.count; ++i) {
9797 guint32 cols [MONO_METHOD_SIZE];
9799 MonoMethodSignature *sig;
9801 /* klass->method.first points into the methodptr table */
9802 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9804 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9805 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9807 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9810 if (param_count == -1) {
9814 sig = mono_method_signature_checked (method, &error);
9816 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9819 if (sig->param_count == param_count) {
9830 * mono_class_get_method_from_name_flags:
9831 * @klass: where to look for the method
9832 * @name_space: name of the method
9833 * @param_count: number of parameters. -1 for any number.
9834 * @flags: flags which must be set in the method
9836 * Obtains a MonoMethod with a given name and number of parameters.
9837 * It only works if there are no multiple signatures for any given method name.
9840 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9842 MonoMethod *res = NULL;
9845 mono_class_init (klass);
9847 if (mono_class_is_ginst (klass) && !klass->methods) {
9848 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9851 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9852 if (!mono_error_ok (&error))
9853 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9858 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9859 mono_class_setup_methods (klass);
9861 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9862 See mono/tests/array_load_exception.il
9863 FIXME we should better report this error to the caller
9865 if (!klass->methods)
9867 for (i = 0; i < klass->method.count; ++i) {
9868 MonoMethod *method = klass->methods [i];
9870 if (method->name[0] == name [0] &&
9871 !strcmp (name, method->name) &&
9872 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9873 ((method->flags & flags) == flags)) {
9880 res = find_method_in_metadata (klass, name, param_count, flags);
9887 * mono_class_set_failure:
9888 * @klass: class in which the failure was detected
9889 * @ex_type: the kind of exception/error to be thrown (later)
9890 * @ex_data: exception data (specific to each type of exception/error)
9892 * Keep a detected failure informations in the class for later processing.
9893 * Note that only the first failure is kept.
9895 * LOCKING: Acquires the loader lock.
9898 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9900 g_assert (boxed_error != NULL);
9902 if (mono_class_has_failure (klass))
9905 mono_loader_lock ();
9906 klass->has_failure = 1;
9907 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, boxed_error);
9908 mono_loader_unlock ();
9914 mono_class_has_failure (const MonoClass *klass)
9916 g_assert (klass != NULL);
9917 return klass->has_failure != 0;
9922 * mono_class_set_type_load_failure:
9923 * @klass: class in which the failure was detected
9924 * @fmt: Printf-style error message string.
9926 * Collect detected failure informaion in the class for later processing.
9927 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9928 * Note that only the first failure is kept.
9930 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9932 * LOCKING: Acquires the loader lock.
9935 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9937 MonoError prepare_error;
9940 if (mono_class_has_failure (klass))
9943 mono_error_init (&prepare_error);
9945 va_start (args, fmt);
9946 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9949 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9950 mono_error_cleanup (&prepare_error);
9951 return mono_class_set_failure (klass, box);
9955 * mono_class_get_exception_data:
9957 * Return the exception_data property of KLASS.
9959 * LOCKING: Acquires the loader lock.
9962 mono_class_get_exception_data (const MonoClass *klass)
9964 return mono_image_property_lookup (klass->image, (MonoClass*)klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9968 * mono_classes_init:
9970 * Initialize the resources used by this module.
9973 mono_classes_init (void)
9975 mono_os_mutex_init (&classes_mutex);
9977 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9978 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9980 mono_counters_register ("Inflated methods size",
9981 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9982 mono_counters_register ("Inflated classes",
9983 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9984 mono_counters_register ("Inflated classes size",
9985 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9986 mono_counters_register ("MonoClass size",
9987 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9988 mono_counters_register ("MonoClassExt size",
9989 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9993 * mono_classes_cleanup:
9995 * Free the resources used by this module.
9998 mono_classes_cleanup (void)
10000 mono_native_tls_free (setup_fields_tls_id);
10001 mono_native_tls_free (init_pending_tls_id);
10003 if (global_interface_bitset)
10004 mono_bitset_free (global_interface_bitset);
10005 global_interface_bitset = NULL;
10006 mono_os_mutex_destroy (&classes_mutex);
10010 * mono_class_get_exception_for_failure:
10011 * @klass: class in which the failure was detected
10013 * Return a constructed MonoException than the caller can then throw
10014 * using mono_raise_exception - or NULL if no failure is present (or
10015 * doesn't result in an exception).
10018 mono_class_get_exception_for_failure (MonoClass *klass)
10020 if (!mono_class_has_failure (klass))
10022 MonoError unboxed_error;
10023 mono_error_init (&unboxed_error);
10024 mono_error_set_for_class_failure (&unboxed_error, klass);
10025 return mono_error_convert_to_exception (&unboxed_error);
10029 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10031 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10032 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10034 if (outer_klass == inner_klass)
10036 inner_klass = inner_klass->nested_in;
10037 } while (inner_klass);
10042 mono_class_get_generic_type_definition (MonoClass *klass)
10044 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10045 return gklass ? gklass->container_class : klass;
10049 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10051 * Generic instantiations are ignored for all super types of @klass.
10053 * Visibility checks ignoring generic instantiations.
10056 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10059 klass = mono_class_get_generic_type_definition (klass);
10060 parent = mono_class_get_generic_type_definition (parent);
10061 mono_class_setup_supertypes (klass);
10063 for (i = 0; i < klass->idepth; ++i) {
10064 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10070 * Subtype can only access parent members with family protection if the site object
10071 * is subclass of Subtype. For example:
10072 * class A { protected int x; }
10074 * void valid_access () {
10078 * void invalid_access () {
10085 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10087 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10090 if (context_klass == NULL)
10092 /*if access_klass is not member_klass context_klass must be type compat*/
10093 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10099 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10102 if (accessing == accessed)
10104 if (!accessed || !accessing)
10107 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10108 * anywhere so untrusted friends are not safe to access platform's code internals */
10109 if (mono_security_core_clr_enabled ()) {
10110 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10114 mono_assembly_load_friends (accessed);
10115 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10116 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10117 /* Be conservative with checks */
10118 if (!friend_->name)
10120 if (strcmp (accessing->aname.name, friend_->name))
10122 if (friend_->public_key_token [0]) {
10123 if (!accessing->aname.public_key_token [0])
10125 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10134 * If klass is a generic type or if it is derived from a generic type, return the
10135 * MonoClass of the generic definition
10136 * Returns NULL if not found
10139 get_generic_definition_class (MonoClass *klass)
10142 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10143 if (gklass && gklass->container_class)
10144 return gklass->container_class;
10145 klass = klass->parent;
10151 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10154 for (i = 0; i < ginst->type_argc; ++i) {
10155 MonoType *type = ginst->type_argv[i];
10156 switch (type->type) {
10157 case MONO_TYPE_SZARRAY:
10158 if (!can_access_type (access_klass, type->data.klass))
10161 case MONO_TYPE_ARRAY:
10162 if (!can_access_type (access_klass, type->data.array->eklass))
10165 case MONO_TYPE_PTR:
10166 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10169 case MONO_TYPE_CLASS:
10170 case MONO_TYPE_VALUETYPE:
10171 case MONO_TYPE_GENERICINST:
10172 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10182 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10186 if (access_klass == member_klass)
10189 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10192 if (access_klass->element_class && !access_klass->enumtype)
10193 access_klass = access_klass->element_class;
10195 if (member_klass->element_class && !member_klass->enumtype)
10196 member_klass = member_klass->element_class;
10198 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10200 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10203 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10206 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10209 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10212 /*Non nested type with nested visibility. We just fail it.*/
10213 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10216 switch (access_level) {
10217 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10218 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10220 case TYPE_ATTRIBUTE_PUBLIC:
10223 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10226 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10227 return is_nesting_type (member_klass, access_klass);
10229 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10230 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10232 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10233 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10235 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10236 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10237 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10239 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10240 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10241 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10246 /* FIXME: check visibility of type, too */
10248 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10250 MonoClass *member_generic_def;
10251 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10254 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10255 if (((access_gklass && access_gklass->container_class) ||
10256 mono_class_is_gtd (access_klass)) &&
10257 (member_generic_def = get_generic_definition_class (member_klass))) {
10258 MonoClass *access_container;
10260 if (mono_class_is_gtd (access_klass))
10261 access_container = access_klass;
10263 access_container = access_gklass->container_class;
10265 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10269 /* Partition I 8.5.3.2 */
10270 /* the access level values are the same for fields and methods */
10271 switch (access_level) {
10272 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10273 /* same compilation unit */
10274 return access_klass->image == member_klass->image;
10275 case FIELD_ATTRIBUTE_PRIVATE:
10276 return access_klass == member_klass;
10277 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10278 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10279 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10282 case FIELD_ATTRIBUTE_ASSEMBLY:
10283 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10284 case FIELD_ATTRIBUTE_FAMILY:
10285 if (is_valid_family_access (access_klass, member_klass, context_klass))
10288 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10289 if (is_valid_family_access (access_klass, member_klass, context_klass))
10291 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10292 case FIELD_ATTRIBUTE_PUBLIC:
10299 * mono_method_can_access_field:
10300 * @method: Method that will attempt to access the field
10301 * @field: the field to access
10303 * Used to determine if a method is allowed to access the specified field.
10305 * Returns: TRUE if the given @method is allowed to access the @field while following
10306 * the accessibility rules of the CLI.
10309 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10311 /* FIXME: check all overlapping fields */
10312 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10314 MonoClass *nested = method->klass->nested_in;
10316 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10319 nested = nested->nested_in;
10326 * mono_method_can_access_method:
10327 * @method: Method that will attempt to access the other method
10328 * @called: the method that we want to probe for accessibility.
10330 * Used to determine if the @method is allowed to access the specified @called method.
10332 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10333 * the accessibility rules of the CLI.
10336 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10338 method = mono_method_get_method_definition (method);
10339 called = mono_method_get_method_definition (called);
10340 return mono_method_can_access_method_full (method, called, NULL);
10344 * mono_method_can_access_method_full:
10345 * @method: The caller method
10346 * @called: The called method
10347 * @context_klass: The static type on stack of the owner @called object used
10349 * This function must be used with instance calls, as they have more strict family accessibility.
10350 * It can be used with static methods, but context_klass should be NULL.
10352 * Returns: TRUE if caller have proper visibility and acessibility to @called
10355 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10357 /* Wrappers are except from access checks */
10358 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10361 MonoClass *access_class = method->klass;
10362 MonoClass *member_class = called->klass;
10363 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10365 MonoClass *nested = access_class->nested_in;
10367 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10370 nested = nested->nested_in;
10377 can = can_access_type (access_class, member_class);
10379 MonoClass *nested = access_class->nested_in;
10381 can = can_access_type (nested, member_class);
10384 nested = nested->nested_in;
10391 if (called->is_inflated) {
10392 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10393 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10402 * mono_method_can_access_field_full:
10403 * @method: The caller method
10404 * @field: The accessed field
10405 * @context_klass: The static type on stack of the owner @field object used
10407 * This function must be used with instance fields, as they have more strict family accessibility.
10408 * It can be used with static fields, but context_klass should be NULL.
10410 * Returns: TRUE if caller have proper visibility and acessibility to @field
10413 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10415 MonoClass *access_class = method->klass;
10416 MonoClass *member_class = field->parent;
10417 /* FIXME: check all overlapping fields */
10418 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10420 MonoClass *nested = access_class->nested_in;
10422 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10425 nested = nested->nested_in;
10432 can = can_access_type (access_class, member_class);
10434 MonoClass *nested = access_class->nested_in;
10436 can = can_access_type (nested, member_class);
10439 nested = nested->nested_in;
10449 * mono_class_can_access_class:
10450 * @source_class: The source class
10451 * @target_class: The accessed class
10453 * This function returns is @target_class is visible to @source_class
10455 * Returns: TRUE if source have proper visibility and acessibility to target
10458 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10460 return can_access_type (source_class, target_class);
10464 * mono_type_is_valid_enum_basetype:
10465 * @type: The MonoType to check
10467 * Returns: TRUE if the type can be used as the basetype of an enum
10469 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10470 switch (type->type) {
10473 case MONO_TYPE_BOOLEAN:
10476 case MONO_TYPE_CHAR:
10490 * mono_class_is_valid_enum:
10491 * @klass: An enum class to be validated
10493 * This method verify the required properties an enum should have.
10495 * Returns: TRUE if the informed enum class is valid
10497 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10498 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10499 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10501 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10502 MonoClassField * field;
10503 gpointer iter = NULL;
10504 gboolean found_base_field = FALSE;
10506 g_assert (klass->enumtype);
10507 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10508 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10512 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10515 while ((field = mono_class_get_fields (klass, &iter))) {
10516 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10517 if (found_base_field)
10519 found_base_field = TRUE;
10520 if (!mono_type_is_valid_enum_basetype (field->type))
10525 if (!found_base_field)
10528 if (klass->method.count > 0)
10535 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10537 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10541 * mono_class_setup_interface_id:
10543 * Initializes MonoClass::interface_id if required.
10545 * LOCKING: Acquires the loader lock.
10548 mono_class_setup_interface_id (MonoClass *klass)
10550 mono_loader_lock ();
10551 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10552 klass->interface_id = mono_get_unique_iid (klass);
10553 mono_loader_unlock ();
10557 * mono_class_alloc_ext:
10559 * Allocate klass->ext if not already done.
10562 mono_class_alloc_ext (MonoClass *klass)
10569 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10570 mono_image_lock (klass->image);
10571 mono_memory_barrier ();
10574 class_ext_size += sizeof (MonoClassExt);
10575 mono_image_unlock (klass->image);
10579 * mono_class_setup_interfaces:
10581 * Initialize klass->interfaces/interfaces_count.
10582 * LOCKING: Acquires the loader lock.
10583 * This function can fail the type.
10586 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10588 int i, interface_count;
10589 MonoClass **interfaces;
10591 mono_error_init (error);
10593 if (klass->interfaces_inited)
10596 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10597 MonoType *args [1];
10599 /* generic IList, ICollection, IEnumerable */
10600 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10601 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10603 args [0] = &klass->element_class->byval_arg;
10604 interfaces [0] = mono_class_bind_generic_parameters (
10605 mono_defaults.generic_ilist_class, 1, args, FALSE);
10606 if (interface_count > 1)
10607 interfaces [1] = mono_class_bind_generic_parameters (
10608 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10609 } else if (mono_class_is_ginst (klass)) {
10610 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10612 mono_class_setup_interfaces (gklass, error);
10613 if (!mono_error_ok (error)) {
10614 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10618 interface_count = gklass->interface_count;
10619 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10620 for (i = 0; i < interface_count; i++) {
10621 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10622 if (!mono_error_ok (error)) {
10623 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10628 interface_count = 0;
10632 mono_image_lock (klass->image);
10634 if (!klass->interfaces_inited) {
10635 klass->interface_count = interface_count;
10636 klass->interfaces = interfaces;
10638 mono_memory_barrier ();
10640 klass->interfaces_inited = TRUE;
10643 mono_image_unlock (klass->image);
10647 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10649 MonoClass *klass = field->parent;
10650 MonoImage *image = klass->image;
10651 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10652 int field_idx = field - klass->fields;
10654 mono_error_init (error);
10657 MonoClassField *gfield = >d->fields [field_idx];
10658 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10659 if (!mono_error_ok (error)) {
10660 char *full_name = mono_type_get_full_name (gtd);
10661 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));
10662 g_free (full_name);
10665 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10666 if (!mono_error_ok (error)) {
10667 char *full_name = mono_type_get_full_name (klass);
10668 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));
10669 g_free (full_name);
10673 guint32 cols [MONO_FIELD_SIZE];
10674 MonoGenericContainer *container = NULL;
10675 int idx = klass->field.first + field_idx;
10677 /*FIXME, in theory we do not lazy load SRE fields*/
10678 g_assert (!image_is_dynamic (image));
10680 if (mono_class_is_gtd (klass)) {
10681 container = mono_class_get_generic_container (klass);
10683 container = mono_class_get_generic_container (gtd);
10684 g_assert (container);
10687 /* klass->field.first and idx points into the fieldptr table */
10688 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10690 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10691 char *full_name = mono_type_get_full_name (klass);
10692 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10693 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10694 g_free (full_name);
10698 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10700 mono_metadata_decode_value (sig, &sig);
10701 /* FIELD signature == 0x06 */
10702 g_assert (*sig == 0x06);
10704 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10705 if (!field->type) {
10706 char *full_name = mono_type_get_full_name (klass);
10707 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));
10708 g_free (full_name);
10714 mono_field_resolve_flags (MonoClassField *field)
10716 MonoClass *klass = field->parent;
10717 MonoImage *image = klass->image;
10718 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10719 int field_idx = field - klass->fields;
10723 MonoClassField *gfield = >d->fields [field_idx];
10724 return mono_field_get_flags (gfield);
10726 int idx = klass->field.first + field_idx;
10728 /*FIXME, in theory we do not lazy load SRE fields*/
10729 g_assert (!image_is_dynamic (image));
10731 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10736 * mono_class_get_fields_lazy:
10737 * @klass: the MonoClass to act on
10739 * This routine is an iterator routine for retrieving the fields in a class.
10740 * Only minimal information about fields are loaded. Accessors must be used
10741 * for all MonoClassField returned.
10743 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10744 * iterate over all of the elements. When no more values are
10745 * available, the return value is NULL.
10747 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10750 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10752 MonoClassField* field;
10756 mono_class_setup_basic_field_info (klass);
10757 if (!klass->fields)
10759 /* start from the first */
10760 if (klass->field.count) {
10761 *iter = &klass->fields [0];
10762 return (MonoClassField *)*iter;
10768 field = (MonoClassField *)*iter;
10770 if (field < &klass->fields [klass->field.count]) {
10772 return (MonoClassField *)*iter;
10778 mono_class_full_name (MonoClass *klass)
10780 return mono_type_full_name (&klass->byval_arg);
10783 /* Declare all shared lazy type lookup functions */
10784 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)