3 * Class management for the Mono runtime
6 * Miguel de Icaza (miguel@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/tabledefs.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/class-internals.h>
31 #include <mono/metadata/object.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-endian.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/security-manager.h>
38 #include <mono/metadata/security-core-clr.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/utils/mono-counters.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/mono-logger-internals.h>
47 #include <mono/utils/mono-memory-model.h>
48 #include <mono/utils/atomic.h>
49 #include <mono/utils/bsearch.h>
50 #include <mono/utils/checked-build.h>
54 gboolean mono_print_vtable = FALSE;
55 gboolean mono_align_small_structs = FALSE;
58 guint32 inflated_classes_size, inflated_methods_size;
59 guint32 classes_size, class_ext_size, class_ext_count;
60 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
62 /* Low level lock which protects data structures in this module */
63 static mono_mutex_t classes_mutex;
65 /* Function supplied by the runtime to find classes by name using information from the AOT file */
66 static MonoGetClassFromName get_class_from_name = NULL;
68 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
69 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
70 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
71 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
72 static int generic_array_methods (MonoClass *klass);
73 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
75 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
76 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
77 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
78 static guint32 mono_field_resolve_flags (MonoClassField *field);
79 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
80 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
82 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * \param image a MonoImage
169 * \param type_token a TypeRef token
171 * Creates the \c MonoClass* structure representing the type defined by
172 * the typeref token valid inside \p image.
173 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * \param image a MonoImage
188 * \param type_token a TypeRef token
189 * \param error error return code, if any.
191 * Creates the \c MonoClass* structure representing the type defined by
192 * the typeref token valid inside \p image.
194 * \returns The \c MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the \p error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
249 if (enclosing->nested_classes_inited && nested_classes) {
250 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
251 for (tmp = nested_classes; tmp; tmp = tmp->next) {
252 res = (MonoClass *)tmp->data;
253 if (strcmp (res->name, name) == 0)
257 /* Don't call mono_class_init as we might've been called by it recursively */
258 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
260 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
261 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
262 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
264 if (strcmp (nname, name) == 0)
265 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
267 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
270 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
273 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
277 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
278 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
282 if (!image->references || !image->references [idx - 1])
283 mono_assembly_load_reference (image, idx - 1);
284 g_assert (image->references [idx - 1]);
286 /* If the assembly did not load, register this as a type load exception */
287 if (image->references [idx - 1] == REFERENCE_MISSING){
288 MonoAssemblyName aname;
291 mono_assembly_get_assemblyref (image, idx - 1, &aname);
292 human_name = mono_stringify_assembly_name (&aname);
293 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
297 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
300 /* Generic case, should be avoided for when a better error is possible. */
301 if (!res && mono_error_ok (error)) {
302 char *name = mono_class_name_from_token (image, type_token);
303 char *assembly = mono_assembly_name_from_token (image, type_token);
304 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (from typeref, class/assembly %s, %s)", type_token, name, assembly);
311 mono_image_memdup (MonoImage *image, void *data, guint size)
313 void *res = mono_image_alloc (image, size);
314 memcpy (res, data, size);
318 /* Copy everything mono_metadata_free_array free. */
320 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
323 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
325 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
327 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
329 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
331 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
333 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
338 /* Copy everything mono_metadata_free_method_signature free. */
340 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
344 sig = mono_metadata_signature_dup_full (image, sig);
346 sig->ret = mono_metadata_type_dup (image, sig->ret);
347 for (i = 0; i < sig->param_count; ++i)
348 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
354 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
356 MonoAssembly *ta = klass->image->assembly;
359 name = mono_stringify_assembly_name (&ta->aname);
360 g_string_append_printf (str, ", %s", name);
365 mono_type_name_check_byref (MonoType *type, GString *str)
368 g_string_append_c (str, '&');
372 * mono_identifier_escape_type_name_chars:
373 * \param str a destination string
374 * \param identifier an IDENTIFIER in internal form
378 * The displayed form of the identifier is appended to str.
380 * The displayed form of an identifier has the characters ,+&*[]\
381 * that have special meaning in type names escaped with a preceeding
382 * backslash (\) character.
385 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
391 // reserve space for common case: there will be no escaped characters.
392 g_string_set_size(str, n + strlen(identifier));
393 g_string_set_size(str, n);
395 for (const char* s = identifier; *s != 0 ; s++) {
404 g_string_append_c (str, '\\');
405 g_string_append_c (str, *s);
408 g_string_append_c (str, *s);
416 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
417 MonoTypeNameFormat format)
421 switch (type->type) {
422 case MONO_TYPE_ARRAY: {
423 int i, rank = type->data.array->rank;
424 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429 mono_type_get_name_recurse (
430 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
431 g_string_append_c (str, '[');
433 g_string_append_c (str, '*');
434 for (i = 1; i < rank; i++)
435 g_string_append_c (str, ',');
436 g_string_append_c (str, ']');
438 mono_type_name_check_byref (type, str);
440 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
441 _mono_type_get_assembly_name (type->data.array->eklass, str);
444 case MONO_TYPE_SZARRAY: {
445 MonoTypeNameFormat nested_format;
447 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
448 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
450 mono_type_get_name_recurse (
451 &type->data.klass->byval_arg, str, FALSE, nested_format);
452 g_string_append (str, "[]");
454 mono_type_name_check_byref (type, str);
456 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
457 _mono_type_get_assembly_name (type->data.klass, str);
460 case MONO_TYPE_PTR: {
461 MonoTypeNameFormat nested_format;
463 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
464 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
466 mono_type_get_name_recurse (
467 type->data.type, str, FALSE, nested_format);
468 g_string_append_c (str, '*');
470 mono_type_name_check_byref (type, str);
472 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
473 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
478 if (!mono_generic_param_info (type->data.generic_param))
479 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
481 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
483 mono_type_name_check_byref (type, str);
487 klass = mono_class_from_mono_type (type);
488 if (klass->nested_in) {
489 mono_type_get_name_recurse (
490 &klass->nested_in->byval_arg, str, TRUE, format);
491 if (format == MONO_TYPE_NAME_FORMAT_IL)
492 g_string_append_c (str, '.');
494 g_string_append_c (str, '+');
495 } else if (*klass->name_space) {
496 if (format == MONO_TYPE_NAME_FORMAT_IL)
497 g_string_append (str, klass->name_space);
499 mono_identifier_escape_type_name_chars (str, klass->name_space);
500 g_string_append_c (str, '.');
502 if (format == MONO_TYPE_NAME_FORMAT_IL) {
503 char *s = strchr (klass->name, '`');
504 int len = s ? s - klass->name : strlen (klass->name);
505 g_string_append_len (str, klass->name, len);
507 mono_identifier_escape_type_name_chars (str, klass->name);
511 if (mono_class_is_ginst (klass)) {
512 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
513 MonoGenericInst *inst = gclass->context.class_inst;
514 MonoTypeNameFormat nested_format;
517 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
518 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
520 if (format == MONO_TYPE_NAME_FORMAT_IL)
521 g_string_append_c (str, '<');
523 g_string_append_c (str, '[');
524 for (i = 0; i < inst->type_argc; i++) {
525 MonoType *t = inst->type_argv [i];
528 g_string_append_c (str, ',');
529 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531 g_string_append_c (str, '[');
532 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
533 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535 g_string_append_c (str, ']');
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '>');
540 g_string_append_c (str, ']');
541 } else if (mono_class_is_gtd (klass) &&
542 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
543 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '<');
549 g_string_append_c (str, '[');
550 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
552 g_string_append_c (str, ',');
553 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
555 if (format == MONO_TYPE_NAME_FORMAT_IL)
556 g_string_append_c (str, '>');
558 g_string_append_c (str, ']');
561 mono_type_name_check_byref (type, str);
563 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
564 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
565 _mono_type_get_assembly_name (klass, str);
571 * mono_type_get_name_full:
573 * \param format the format for the return string.
576 * \returns The string representation in a number of formats:
578 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
579 * returned in the format required by \c System.Reflection, this is the
580 * inverse of mono_reflection_parse_type().
582 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
583 * be used by the IL assembler.
585 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
587 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
590 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
594 result = g_string_new ("");
596 mono_type_get_name_recurse (type, result, FALSE, format);
598 return g_string_free (result, FALSE);
602 * mono_type_get_full_name:
603 * \param class a class
605 * \returns The string representation for type as required by System.Reflection.
606 * The inverse of mono_reflection_parse_type().
609 mono_type_get_full_name (MonoClass *klass)
611 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
615 * mono_type_get_name:
617 * \returns The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
628 * \returns The \c MonoType for the underlying integer type if \p 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)
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;
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 * \param context a generics context
875 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
877 * If \p type is a generic type and \p context is not NULL, instantiate it using the
878 * generics context \p context.
880 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
884 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
888 result = mono_class_inflate_generic_type_checked (type, context, &error);
889 mono_error_cleanup (&error);
894 * mono_class_inflate_generic_type:
896 * @context: a generics context
897 * @error: error context to use
899 * If @type is a generic type and @context is not NULL, instantiate it using the
900 * generics context @context.
902 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
903 * on the heap and is owned by the caller.
906 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
908 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
912 * mono_class_inflate_generic_type_no_copy:
914 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
918 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
920 MonoType *inflated = NULL;
924 inflated = inflate_generic_type (image, type, context, error);
925 return_val_if_nok (error, NULL);
931 mono_stats.inflated_type_count++;
936 * mono_class_inflate_generic_class:
938 * Inflate the class @gklass with @context. Set @error on failure.
941 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
946 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
947 return_val_if_nok (error, NULL);
949 res = mono_class_from_mono_type (inflated);
950 mono_metadata_free_type (inflated);
955 static MonoGenericContext
956 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
958 MonoGenericInst *class_inst = NULL;
959 MonoGenericInst *method_inst = NULL;
960 MonoGenericContext res = { NULL, NULL };
964 if (context->class_inst) {
965 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
966 if (!mono_error_ok (error))
970 if (context->method_inst) {
971 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
972 if (!mono_error_ok (error))
976 res.class_inst = class_inst;
977 res.method_inst = method_inst;
983 * mono_class_inflate_generic_method:
984 * \param method a generic method
985 * \param context a generics context
987 * Instantiate the generic method \p method using the generics context \p context.
989 * \returns The new instantiated method
992 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
994 return mono_class_inflate_generic_method_full (method, NULL, context);
998 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1000 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1004 * mono_class_inflate_generic_method_full:
1006 * Instantiate method \p method with the generic context \p context.
1007 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1008 * Use mono_method_signature() and mono_method_get_header() to get the correct values.
1011 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1014 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1015 if (!mono_error_ok (&error))
1016 /*FIXME do proper error handling - on this case, kill this function. */
1017 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1023 * mono_class_inflate_generic_method_full_checked:
1024 * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1027 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1030 MonoMethodInflated *iresult, *cached;
1031 MonoMethodSignature *sig;
1032 MonoGenericContext tmp_context;
1036 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1037 while (method->is_inflated) {
1038 MonoGenericContext *method_context = mono_method_get_context (method);
1039 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1041 tmp_context = inflate_generic_context (method_context, context, error);
1042 return_val_if_nok (error, NULL);
1044 context = &tmp_context;
1046 if (mono_metadata_generic_context_equal (method_context, context))
1049 method = imethod->declaring;
1053 * A method only needs to be inflated if the context has argument for which it is
1056 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1057 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1060 if (!((method->is_generic && context->method_inst) ||
1061 (mono_class_is_gtd (method->klass) && context->class_inst)))
1064 iresult = g_new0 (MonoMethodInflated, 1);
1065 iresult->context = *context;
1066 iresult->declaring = method;
1068 if (!context->method_inst && method->is_generic)
1069 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1071 if (!context->class_inst) {
1072 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1073 if (mono_class_is_gtd (iresult->declaring->klass))
1074 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1076 /* This can happen with some callers like mono_object_get_virtual_method () */
1077 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1078 iresult->context.class_inst = NULL;
1080 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1083 mono_image_set_lock (set);
1084 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1085 mono_image_set_unlock (set);
1089 return (MonoMethod*)cached;
1092 mono_stats.inflated_method_count++;
1094 inflated_methods_size += sizeof (MonoMethodInflated);
1096 sig = mono_method_signature (method);
1098 char *name = mono_type_get_full_name (method->klass);
1099 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1105 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1107 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1110 result = (MonoMethod *) iresult;
1111 result->is_inflated = TRUE;
1112 result->is_generic = FALSE;
1113 result->sre_method = FALSE;
1114 result->signature = NULL;
1116 if (method->wrapper_type) {
1117 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1118 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1119 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1121 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1122 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1125 if (iresult->context.method_inst) {
1126 /* Set the generic_container of the result to the generic_container of method */
1127 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1129 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1130 result->is_generic = 1;
1131 mono_method_set_generic_container (result, generic_container);
1136 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1137 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1141 if (mono_class_is_gtd (method->klass))
1142 result->klass = klass_hint;
1144 if (!result->klass) {
1145 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1146 if (!mono_error_ok (error))
1149 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1151 mono_metadata_free_type (inflated);
1155 * FIXME: This should hold, but it doesn't:
1157 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1158 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1159 * g_assert (result->is_generic);
1162 * Fixing this here causes other things to break, hence a very
1163 * ugly hack in mini-trampolines.c - see
1164 * is_generic_method_definition().
1168 mono_image_set_lock (set);
1169 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1171 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1172 iresult->owner = set;
1175 mono_image_set_unlock (set);
1177 return (MonoMethod*)cached;
1185 * mono_get_inflated_method:
1187 * Obsolete. We keep it around since it's mentioned in the public API.
1190 mono_get_inflated_method (MonoMethod *method)
1196 * mono_method_get_context_general:
1198 * @uninflated: handle uninflated methods?
1200 * Returns the generic context of a method or NULL if it doesn't have
1201 * one. For an inflated method that's the context stored in the
1202 * method. Otherwise it's in the method's generic container or in the
1203 * generic container of the method's class.
1206 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1208 if (method->is_inflated) {
1209 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1210 return &imethod->context;
1214 if (method->is_generic)
1215 return &(mono_method_get_generic_container (method)->context);
1216 if (mono_class_is_gtd (method->klass))
1217 return &mono_class_get_generic_container (method->klass)->context;
1222 * mono_method_get_context:
1225 * Returns the generic context for method if it's inflated, otherwise
1229 mono_method_get_context (MonoMethod *method)
1231 return mono_method_get_context_general (method, FALSE);
1235 * mono_method_get_generic_container:
1237 * Returns the generic container of METHOD, which should be a generic method definition.
1238 * Returns NULL if METHOD is not a generic method definition.
1239 * LOCKING: Acquires the loader lock.
1241 MonoGenericContainer*
1242 mono_method_get_generic_container (MonoMethod *method)
1244 MonoGenericContainer *container;
1246 if (!method->is_generic)
1249 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1250 g_assert (container);
1256 * mono_method_set_generic_container:
1258 * Sets the generic container of METHOD to CONTAINER.
1259 * LOCKING: Acquires the image lock.
1262 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1264 g_assert (method->is_generic);
1266 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1270 * mono_class_find_enum_basetype:
1271 * \param class The enum class
1273 * Determine the basetype of an enum by iterating through its fields. We do this
1274 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1277 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1279 MonoGenericContainer *container = NULL;
1280 MonoImage *m = klass->image;
1281 const int top = mono_class_get_field_count (klass);
1282 int i, first_field_idx;
1284 g_assert (klass->enumtype);
1288 container = mono_class_try_get_generic_container (klass);
1289 if (mono_class_is_ginst (klass)) {
1290 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1292 container = mono_class_get_generic_container (gklass);
1293 g_assert (container);
1297 * Fetch all the field information.
1299 first_field_idx = mono_class_get_first_field_idx (klass);
1300 for (i = 0; i < top; i++){
1302 guint32 cols [MONO_FIELD_SIZE];
1303 int idx = first_field_idx + i;
1306 /* first_field_idx 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 = mono_class_get_exception_data ((MonoClass*)klass);
1370 mono_error_set_from_boxed (oerror, box);
1376 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1380 mono_class_alloc (MonoClass *klass, int size)
1382 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1384 return mono_image_set_alloc (gklass->owner, size);
1386 return mono_image_alloc (klass->image, size);
1390 mono_class_alloc0 (MonoClass *klass, int size)
1394 res = mono_class_alloc (klass, size);
1395 memset (res, 0, size);
1399 #define mono_class_new0(klass,struct_type, n_structs) \
1400 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1403 * mono_class_setup_basic_field_info:
1404 * \param class The class to initialize
1406 * Initializes the following fields in MonoClass:
1407 * * klass->fields (only field->parent and field->name)
1408 * * klass->field.count
1409 * * klass->first_field_idx
1410 * LOCKING: Acquires the loader lock
1413 mono_class_setup_basic_field_info (MonoClass *klass)
1415 MonoGenericClass *gklass;
1416 MonoClassField *field;
1417 MonoClassField *fields;
1425 gklass = mono_class_try_get_generic_class (klass);
1426 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1427 image = klass->image;
1430 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1432 * This happens when a generic instance of an unfinished generic typebuilder
1433 * is used as an element type for creating an array type. We can't initialize
1434 * the fields of this class using the fields of gklass, since gklass is not
1435 * finished yet, fields could be added to it later.
1441 mono_class_setup_basic_field_info (gtd);
1443 mono_loader_lock ();
1444 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1445 mono_loader_unlock ();
1448 top = mono_class_get_field_count (klass);
1450 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1453 * Fetch all the field information.
1455 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1456 for (i = 0; i < top; i++) {
1457 field = &fields [i];
1458 field->parent = klass;
1461 field->name = mono_field_get_name (>d->fields [i]);
1463 int idx = first_field_idx + i;
1464 /* first_field_idx and idx points into the fieldptr table */
1465 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1466 /* The name is needed for fieldrefs */
1467 field->name = mono_metadata_string_heap (image, name_idx);
1471 mono_memory_barrier ();
1473 mono_loader_lock ();
1475 klass->fields = fields;
1476 mono_loader_unlock ();
1480 * mono_class_set_failure_causedby_class:
1481 * \param klass the class that is failing
1482 * \param caused_by the class that caused the failure
1483 * \param msg Why \p klass is failing.
1485 * If \p caused_by has a failure, sets a TypeLoadException failure on
1486 * \p klass with message "\p msg, due to: {\p caused_by message}".
1488 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1491 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1493 if (mono_class_has_failure (caused_by)) {
1494 MonoError cause_error;
1495 error_init (&cause_error);
1496 mono_error_set_for_class_failure (&cause_error, caused_by);
1497 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1498 mono_error_cleanup (&cause_error);
1507 * mono_class_setup_fields:
1508 * \p klass The class to initialize
1510 * Initializes klass->fields, computes class layout and sizes.
1511 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1512 * Sets the following fields in \p klass:
1513 * - all the fields initialized by mono_class_init_sizes ()
1514 * - element_class/cast_class (for enums)
1515 * - field->type/offset for all fields
1518 * LOCKING: Acquires the loader lock.
1521 mono_class_setup_fields (MonoClass *klass)
1524 MonoImage *m = klass->image;
1526 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1528 guint32 real_size = 0;
1529 guint32 packing_size = 0;
1531 gboolean explicit_size;
1532 MonoClassField *field;
1533 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1534 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1536 if (klass->fields_inited)
1539 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1541 * This happens when a generic instance of an unfinished generic typebuilder
1542 * is used as an element type for creating an array type. We can't initialize
1543 * the fields of this class using the fields of gklass, since gklass is not
1544 * finished yet, fields could be added to it later.
1549 mono_class_setup_basic_field_info (klass);
1550 top = mono_class_get_field_count (klass);
1553 mono_class_setup_fields (gtd);
1554 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1559 if (klass->parent) {
1560 /* For generic instances, klass->parent might not have been initialized */
1561 mono_class_init (klass->parent);
1562 mono_class_setup_fields (klass->parent);
1563 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1565 instance_size = klass->parent->instance_size;
1567 instance_size = sizeof (MonoObject);
1570 /* Get the real size */
1571 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1573 instance_size += real_size;
1576 * This function can recursively call itself.
1577 * Prevent infinite recursion by using a list in TLS.
1579 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1580 if (g_slist_find (init_list, klass))
1582 init_list = g_slist_prepend (init_list, klass);
1583 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1586 * Fetch all the field information.
1588 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1589 for (i = 0; i < top; i++) {
1590 int idx = first_field_idx + i;
1591 field = &klass->fields [i];
1594 mono_field_resolve_type (field, &error);
1595 if (!mono_error_ok (&error)) {
1596 /*mono_field_resolve_type already failed class*/
1597 mono_error_cleanup (&error);
1601 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1602 g_assert (field->type);
1605 if (!mono_type_get_underlying_type (field->type)) {
1606 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
1610 if (mono_field_is_deleted (field))
1612 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1614 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1615 int offset = uoffset;
1617 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1618 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1621 if (offset < -1) { /*-1 is used to encode special static fields */
1622 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1625 if (mono_class_is_gtd (klass)) {
1626 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1630 if (mono_type_has_exceptions (field->type)) {
1631 char *class_name = mono_type_get_full_name (klass);
1632 char *type_name = mono_type_full_name (field->type);
1634 mono_class_set_type_load_failure (klass, "");
1635 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1636 g_free (class_name);
1640 /* The def_value of fields is compute lazily during vtable creation */
1643 if (!mono_class_has_failure (klass)) {
1644 mono_loader_lock ();
1645 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1646 mono_loader_unlock ();
1649 init_list = g_slist_remove (init_list, klass);
1650 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1654 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1657 mono_loader_lock ();
1658 klass->instance_size = cached_info->instance_size;
1659 klass->sizes.class_size = cached_info->class_size;
1660 klass->packing_size = cached_info->packing_size;
1661 klass->min_align = cached_info->min_align;
1662 klass->blittable = cached_info->blittable;
1663 klass->has_references = cached_info->has_references;
1664 klass->has_static_refs = cached_info->has_static_refs;
1665 klass->no_special_static_fields = cached_info->no_special_static_fields;
1666 mono_loader_unlock ();
1669 if (!klass->size_inited)
1670 mono_class_setup_fields (klass);
1675 * mono_class_init_sizes:
1677 * Initializes the size related fields of @klass without loading all field data if possible.
1678 * Sets the following fields in @klass:
1680 * - sizes.class_size
1687 * Can fail the class.
1689 * LOCKING: Acquires the loader lock.
1692 mono_class_init_sizes (MonoClass *klass)
1694 MonoCachedClassInfo cached_info;
1695 gboolean has_cached_info;
1697 if (klass->size_inited)
1700 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1702 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1706 * mono_type_get_basic_type_from_generic:
1709 * Returns a closed type corresponding to the possibly open type
1713 mono_type_get_basic_type_from_generic (MonoType *type)
1715 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1716 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1717 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1718 return &mono_defaults.object_class->byval_arg;
1723 class_has_references (MonoClass *klass)
1725 mono_class_init_sizes (klass);
1728 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1729 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1732 return klass->has_references;
1736 type_has_references (MonoClass *klass, MonoType *ftype)
1738 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1740 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1741 MonoGenericParam *gparam = ftype->data.generic_param;
1743 if (gparam->gshared_constraint)
1744 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1750 * mono_class_layout_fields:
1752 * @base_instance_size: base instance size
1755 * This contains the common code for computing the layout of classes and sizes.
1756 * This should only be called from mono_class_setup_fields () and
1757 * typebuilder_setup_fields ().
1759 * LOCKING: Acquires the loader lock
1762 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1765 const int top = mono_class_get_field_count (klass);
1766 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1767 guint32 pass, passes, real_size;
1768 gboolean gc_aware_layout = FALSE;
1769 gboolean has_static_fields = FALSE;
1770 gboolean has_references = FALSE;
1771 gboolean has_static_refs = FALSE;
1772 MonoClassField *field;
1774 int instance_size = base_instance_size;
1775 int class_size, min_align;
1777 gboolean *fields_has_references;
1780 * We want to avoid doing complicated work inside locks, so we compute all the required
1781 * information and write it to @klass inside a lock.
1783 if (klass->fields_inited)
1786 if ((packing_size & 0xffffff00) != 0) {
1787 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1791 if (klass->parent) {
1792 min_align = klass->parent->min_align;
1793 /* we use | since it may have been set already */
1794 has_references = klass->has_references | klass->parent->has_references;
1798 /* We can't really enable 16 bytes alignment until the GC supports it.
1799 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1800 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1801 Bug #506144 is an example of this issue.
1803 if (klass->simd_type)
1808 * When we do generic sharing we need to have layout
1809 * information for open generic classes (either with a generic
1810 * context containing type variables or with a generic
1811 * container), so we don't return in that case anymore.
1814 if (klass->enumtype) {
1815 for (i = 0; i < top; i++) {
1816 field = &klass->fields [i];
1817 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1818 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1823 if (!mono_class_enum_basetype (klass)) {
1824 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1830 * Enable GC aware auto layout: in this mode, reference
1831 * fields are grouped together inside objects, increasing collector
1833 * Requires that all classes whose layout is known to native code be annotated
1834 * with [StructLayout (LayoutKind.Sequential)]
1835 * Value types have gc_aware_layout disabled by default, as per
1836 * what the default is for other runtimes.
1838 /* corlib is missing [StructLayout] directives in many places */
1839 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1840 if (!klass->valuetype)
1841 gc_aware_layout = TRUE;
1844 /* Compute klass->blittable */
1847 blittable = klass->parent->blittable;
1848 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1850 for (i = 0; i < top; i++) {
1851 field = &klass->fields [i];
1853 if (mono_field_is_deleted (field))
1855 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1858 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1861 MonoClass *field_class = mono_class_from_mono_type (field->type);
1863 mono_class_setup_fields (field_class);
1864 if (mono_class_has_failure (field_class)) {
1865 MonoError field_error;
1866 error_init (&field_error);
1867 mono_error_set_for_class_failure (&field_error, field_class);
1868 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1869 mono_error_cleanup (&field_error);
1873 if (!field_class || !field_class->blittable)
1877 if (klass->enumtype)
1878 blittable = klass->element_class->blittable;
1880 if (mono_class_has_failure (klass))
1882 if (klass == mono_defaults.string_class)
1885 /* Compute klass->has_references */
1887 * Process non-static fields first, since static fields might recursively
1888 * refer to the class itself.
1890 for (i = 0; i < top; i++) {
1893 field = &klass->fields [i];
1895 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1896 ftype = mono_type_get_underlying_type (field->type);
1897 ftype = mono_type_get_basic_type_from_generic (ftype);
1898 if (type_has_references (klass, ftype))
1899 has_references = TRUE;
1904 * Compute field layout and total size (not considering static fields)
1906 field_offsets = g_new0 (int, top);
1907 fields_has_references = g_new0 (gboolean, top);
1908 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1910 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1911 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1912 if (gc_aware_layout)
1917 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1920 if (klass->parent) {
1921 mono_class_setup_fields (klass->parent);
1922 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1924 real_size = klass->parent->instance_size;
1926 real_size = sizeof (MonoObject);
1929 for (pass = 0; pass < passes; ++pass) {
1930 for (i = 0; i < top; i++){
1935 field = &klass->fields [i];
1937 if (mono_field_is_deleted (field))
1939 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1942 ftype = mono_type_get_underlying_type (field->type);
1943 ftype = mono_type_get_basic_type_from_generic (ftype);
1944 if (gc_aware_layout) {
1945 fields_has_references [i] = type_has_references (klass, ftype);
1946 if (fields_has_references [i]) {
1955 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1956 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1957 /* This field is a hack inserted by MCS to empty structures */
1961 size = mono_type_size (field->type, &align);
1963 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1964 align = packing_size ? MIN (packing_size, align): align;
1965 /* if the field has managed references, we need to force-align it
1968 if (type_has_references (klass, ftype))
1969 align = MAX (align, sizeof (gpointer));
1971 min_align = MAX (align, min_align);
1972 field_offsets [i] = real_size;
1974 field_offsets [i] += align - 1;
1975 field_offsets [i] &= ~(align - 1);
1977 /*TypeBuilders produce all sort of weird things*/
1978 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1979 real_size = field_offsets [i] + size;
1982 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1983 if (klass->simd_type)
1984 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1985 instance_size = MAX (real_size, instance_size);
1987 if (instance_size & (min_align - 1)) {
1988 instance_size += min_align - 1;
1989 instance_size &= ~(min_align - 1);
1993 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1997 for (i = 0; i < top; i++) {
2002 field = &klass->fields [i];
2005 * There must be info about all the fields in a type if it
2006 * uses explicit layout.
2008 if (mono_field_is_deleted (field))
2010 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2013 size = mono_type_size (field->type, &align);
2014 align = packing_size ? MIN (packing_size, align): align;
2015 min_align = MAX (align, min_align);
2018 /* Already set by typebuilder_setup_fields () */
2019 field_offsets [i] = field->offset + sizeof (MonoObject);
2021 int idx = first_field_idx + i;
2023 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2024 field_offsets [i] = offset + sizeof (MonoObject);
2026 ftype = mono_type_get_underlying_type (field->type);
2027 ftype = mono_type_get_basic_type_from_generic (ftype);
2028 if (type_has_references (klass, ftype)) {
2029 if (field_offsets [i] % sizeof (gpointer)) {
2030 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2037 real_size = MAX (real_size, size + field_offsets [i]);
2040 if (klass->has_references) {
2041 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2043 /* Check for overlapping reference and non-reference fields */
2044 for (i = 0; i < top; i++) {
2047 field = &klass->fields [i];
2049 if (mono_field_is_deleted (field))
2051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2053 ftype = mono_type_get_underlying_type (field->type);
2054 if (MONO_TYPE_IS_REFERENCE (ftype))
2055 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2057 for (i = 0; i < top; i++) {
2058 field = &klass->fields [i];
2060 if (mono_field_is_deleted (field))
2062 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2065 // FIXME: Too much code does this
2067 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2068 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]);
2072 g_free (ref_bitmap);
2075 instance_size = MAX (real_size, instance_size);
2076 if (instance_size & (min_align - 1)) {
2077 instance_size += min_align - 1;
2078 instance_size &= ~(min_align - 1);
2084 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2086 * This leads to all kinds of problems with nested structs, so only
2087 * enable it when a MONO_DEBUG property is set.
2089 * For small structs, set min_align to at least the struct size to improve
2090 * performance, and since the JIT memset/memcpy code assumes this and generates
2091 * unaligned accesses otherwise. See #78990 for a testcase.
2093 if (mono_align_small_structs && top) {
2094 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2095 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2099 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2100 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2101 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2102 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2104 /* Publish the data */
2105 mono_loader_lock ();
2106 if (klass->instance_size && !klass->image->dynamic) {
2107 /* Might be already set using cached info */
2108 if (klass->instance_size != instance_size) {
2109 /* Emit info to help debugging */
2110 g_print ("%s\n", mono_class_full_name (klass));
2111 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2112 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2113 g_print ("%d %d\n", klass->min_align, min_align);
2114 for (i = 0; i < top; ++i) {
2115 field = &klass->fields [i];
2116 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2117 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2120 g_assert (klass->instance_size == instance_size);
2122 klass->instance_size = instance_size;
2124 klass->blittable = blittable;
2125 klass->has_references = has_references;
2126 klass->packing_size = packing_size;
2127 klass->min_align = min_align;
2128 for (i = 0; i < top; ++i) {
2129 field = &klass->fields [i];
2130 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2131 klass->fields [i].offset = field_offsets [i];
2134 mono_memory_barrier ();
2135 klass->size_inited = 1;
2136 mono_loader_unlock ();
2139 * Compute static field layout and size
2140 * Static fields can reference the class itself, so this has to be
2141 * done after instance_size etc. are initialized.
2144 for (i = 0; i < top; i++) {
2148 field = &klass->fields [i];
2150 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2152 if (mono_field_is_deleted (field))
2155 if (mono_type_has_exceptions (field->type)) {
2156 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2160 has_static_fields = TRUE;
2162 size = mono_type_size (field->type, &align);
2163 field_offsets [i] = class_size;
2164 /*align is always non-zero here*/
2165 field_offsets [i] += align - 1;
2166 field_offsets [i] &= ~(align - 1);
2167 class_size = field_offsets [i] + size;
2170 if (has_static_fields && class_size == 0)
2171 /* Simplify code which depends on class_size != 0 if the class has static fields */
2174 /* Compute klass->has_static_refs */
2175 has_static_refs = FALSE;
2176 for (i = 0; i < top; i++) {
2179 field = &klass->fields [i];
2181 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2182 ftype = mono_type_get_underlying_type (field->type);
2183 ftype = mono_type_get_basic_type_from_generic (ftype);
2184 if (type_has_references (klass, ftype))
2185 has_static_refs = TRUE;
2189 /*valuetypes can't be neither bigger than 1Mb or empty. */
2190 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2191 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2193 /* Publish the data */
2194 mono_loader_lock ();
2196 klass->sizes.class_size = class_size;
2197 klass->has_static_refs = has_static_refs;
2198 for (i = 0; i < top; ++i) {
2199 field = &klass->fields [i];
2201 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2202 field->offset = field_offsets [i];
2205 mono_memory_barrier ();
2206 klass->fields_inited = 1;
2207 mono_loader_unlock ();
2209 g_free (field_offsets);
2210 g_free (fields_has_references);
2214 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2218 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2219 method->klass = klass;
2220 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2221 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2222 method->signature = sig;
2223 method->name = name;
2226 if (name [0] == '.') {
2227 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2229 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2235 * mono_class_setup_methods:
2238 * Initializes the 'methods' array in CLASS.
2239 * Calling this method should be avoided if possible since it allocates a lot
2240 * of long-living MonoMethod structures.
2241 * Methods belonging to an interface are assigned a sequential slot starting
2244 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2247 mono_class_setup_methods (MonoClass *klass)
2250 MonoMethod **methods;
2255 if (mono_class_is_ginst (klass)) {
2257 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2259 mono_class_init (gklass);
2260 if (!mono_class_has_failure (gklass))
2261 mono_class_setup_methods (gklass);
2262 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2265 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2266 count = mono_class_get_method_count (gklass);
2267 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2269 for (i = 0; i < count; i++) {
2270 methods [i] = mono_class_inflate_generic_method_full_checked (
2271 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2272 if (!mono_error_ok (&error)) {
2273 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2274 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2277 mono_error_cleanup (&error);
2281 } else if (klass->rank) {
2283 MonoMethod *amethod;
2284 MonoMethodSignature *sig;
2285 int count_generic = 0, first_generic = 0;
2287 gboolean jagged_ctor = FALSE;
2289 count = 3 + (klass->rank > 1? 2: 1);
2291 mono_class_setup_interfaces (klass, &error);
2292 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2294 if (klass->rank == 1 && klass->element_class->rank) {
2299 if (klass->interface_count) {
2300 count_generic = generic_array_methods (klass);
2301 first_generic = count;
2302 count += klass->interface_count * count_generic;
2305 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2307 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2308 sig->ret = &mono_defaults.void_class->byval_arg;
2309 sig->pinvoke = TRUE;
2310 sig->hasthis = TRUE;
2311 for (i = 0; i < klass->rank; ++i)
2312 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2314 amethod = create_array_method (klass, ".ctor", sig);
2315 methods [method_num++] = amethod;
2316 if (klass->rank > 1) {
2317 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2318 sig->ret = &mono_defaults.void_class->byval_arg;
2319 sig->pinvoke = TRUE;
2320 sig->hasthis = TRUE;
2321 for (i = 0; i < klass->rank * 2; ++i)
2322 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2324 amethod = create_array_method (klass, ".ctor", sig);
2325 methods [method_num++] = amethod;
2329 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2330 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2331 sig->ret = &mono_defaults.void_class->byval_arg;
2332 sig->pinvoke = TRUE;
2333 sig->hasthis = TRUE;
2334 for (i = 0; i < klass->rank + 1; ++i)
2335 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2336 amethod = create_array_method (klass, ".ctor", sig);
2337 methods [method_num++] = amethod;
2340 /* element Get (idx11, [idx2, ...]) */
2341 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2342 sig->ret = &klass->element_class->byval_arg;
2343 sig->pinvoke = TRUE;
2344 sig->hasthis = TRUE;
2345 for (i = 0; i < klass->rank; ++i)
2346 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2347 amethod = create_array_method (klass, "Get", sig);
2348 methods [method_num++] = amethod;
2349 /* element& Address (idx11, [idx2, ...]) */
2350 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2351 sig->ret = &klass->element_class->this_arg;
2352 sig->pinvoke = TRUE;
2353 sig->hasthis = TRUE;
2354 for (i = 0; i < klass->rank; ++i)
2355 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2356 amethod = create_array_method (klass, "Address", sig);
2357 methods [method_num++] = amethod;
2358 /* void Set (idx11, [idx2, ...], element) */
2359 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2360 sig->ret = &mono_defaults.void_class->byval_arg;
2361 sig->pinvoke = TRUE;
2362 sig->hasthis = TRUE;
2363 for (i = 0; i < klass->rank; ++i)
2364 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2365 sig->params [i] = &klass->element_class->byval_arg;
2366 amethod = create_array_method (klass, "Set", sig);
2367 methods [method_num++] = amethod;
2369 GHashTable *cache = g_hash_table_new (NULL, NULL);
2370 for (i = 0; i < klass->interface_count; i++)
2371 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2372 g_hash_table_destroy (cache);
2373 } else if (mono_class_has_static_metadata (klass)) {
2375 int first_idx = mono_class_get_first_method_idx (klass);
2377 count = mono_class_get_method_count (klass);
2378 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2379 for (i = 0; i < count; ++i) {
2380 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2381 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2383 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2384 mono_error_cleanup (&error);
2388 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2392 if (MONO_CLASS_IS_INTERFACE (klass)) {
2394 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2395 for (i = 0; i < count; ++i) {
2396 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2397 methods [i]->slot = slot++;
2401 mono_image_lock (klass->image);
2403 if (!klass->methods) {
2404 mono_class_set_method_count (klass, count);
2406 /* Needed because of the double-checking locking pattern */
2407 mono_memory_barrier ();
2409 klass->methods = methods;
2412 mono_image_unlock (klass->image);
2416 * mono_class_get_method_by_index:
2418 * Returns klass->methods [index], initializing klass->methods if neccesary.
2420 * LOCKING: Acquires the loader lock.
2423 mono_class_get_method_by_index (MonoClass *klass, int index)
2427 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2428 /* Avoid calling setup_methods () if possible */
2429 if (gklass && !klass->methods) {
2432 m = mono_class_inflate_generic_method_full_checked (
2433 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2434 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2436 * If setup_methods () is called later for this class, no duplicates are created,
2437 * since inflate_generic_method guarantees that only one instance of a method
2438 * is created for each context.
2441 mono_class_setup_methods (klass);
2442 g_assert (m == klass->methods [index]);
2446 mono_class_setup_methods (klass);
2447 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2449 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2450 return klass->methods [index];
2455 * mono_class_get_inflated_method:
2457 * Given an inflated class CLASS and a method METHOD which should be a method of
2458 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2461 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2463 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2466 g_assert (method->klass == gklass);
2468 mono_class_setup_methods (gklass);
2469 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2471 mcount = mono_class_get_method_count (gklass);
2472 for (i = 0; i < mcount; ++i) {
2473 if (gklass->methods [i] == method) {
2474 if (klass->methods) {
2475 return klass->methods [i];
2478 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2479 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2489 * mono_class_get_vtable_entry:
2491 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2492 * LOCKING: Acquires the loader lock.
2495 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2499 if (klass->rank == 1) {
2501 * szarrays do not overwrite any methods of Array, so we can avoid
2502 * initializing their vtables in some cases.
2504 mono_class_setup_vtable (klass->parent);
2505 if (offset < klass->parent->vtable_size)
2506 return klass->parent->vtable [offset];
2509 if (mono_class_is_ginst (klass)) {
2511 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2512 mono_class_setup_vtable (gklass);
2513 m = gklass->vtable [offset];
2515 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2516 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2518 mono_class_setup_vtable (klass);
2519 if (mono_class_has_failure (klass))
2521 m = klass->vtable [offset];
2528 * mono_class_get_vtable_size:
2530 * Return the vtable size for KLASS.
2533 mono_class_get_vtable_size (MonoClass *klass)
2535 mono_class_setup_vtable (klass);
2537 return klass->vtable_size;
2541 * mono_class_setup_properties:
2543 * Initialize klass->ext.property and klass->ext.properties.
2545 * This method can fail the class.
2548 mono_class_setup_properties (MonoClass *klass)
2550 guint startm, endm, i, j;
2551 guint32 cols [MONO_PROPERTY_SIZE];
2552 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2553 MonoProperty *properties;
2556 MonoClassPropertyInfo *info;
2558 info = mono_class_get_property_info (klass);
2562 if (mono_class_is_ginst (klass)) {
2563 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2565 mono_class_init (gklass);
2566 mono_class_setup_properties (gklass);
2567 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2570 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2571 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2573 for (i = 0; i < ginfo->count; i++) {
2575 MonoProperty *prop = &properties [i];
2577 *prop = ginfo->properties [i];
2580 prop->get = mono_class_inflate_generic_method_full_checked (
2581 prop->get, klass, mono_class_get_context (klass), &error);
2583 prop->set = mono_class_inflate_generic_method_full_checked (
2584 prop->set, klass, mono_class_get_context (klass), &error);
2586 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2587 prop->parent = klass;
2590 first = ginfo->first;
2591 count = ginfo->count;
2593 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2594 count = last - first;
2597 mono_class_setup_methods (klass);
2598 if (mono_class_has_failure (klass))
2602 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2603 for (i = first; i < last; ++i) {
2604 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2605 properties [i - first].parent = klass;
2606 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2607 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2609 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2610 int first_idx = mono_class_get_first_method_idx (klass);
2611 for (j = startm; j < endm; ++j) {
2614 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2616 if (klass->image->uncompressed_metadata) {
2618 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2619 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2620 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2622 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2625 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2626 case METHOD_SEMANTIC_SETTER:
2627 properties [i - first].set = method;
2629 case METHOD_SEMANTIC_GETTER:
2630 properties [i - first].get = method;
2639 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2640 info->first = first;
2641 info->count = count;
2642 info->properties = properties;
2643 mono_memory_barrier ();
2645 /* This might leak 'info' which was allocated from the image mempool */
2646 mono_class_set_property_info (klass, info);
2650 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2652 MonoMethod **om, **retval;
2655 for (om = methods, count = 0; *om; ++om, ++count)
2658 retval = g_new0 (MonoMethod*, count + 1);
2660 for (om = methods, count = 0; *om; ++om, ++count) {
2662 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2663 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2669 /*This method can fail the class.*/
2671 mono_class_setup_events (MonoClass *klass)
2674 guint startm, endm, i, j;
2675 guint32 cols [MONO_EVENT_SIZE];
2676 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2680 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2684 if (mono_class_is_ginst (klass)) {
2685 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2686 MonoGenericContext *context = NULL;
2688 mono_class_setup_events (gklass);
2689 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2692 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2693 first = ginfo->first;
2694 count = ginfo->count;
2696 events = mono_class_new0 (klass, MonoEvent, count);
2699 context = mono_class_get_context (klass);
2701 for (i = 0; i < count; i++) {
2703 MonoEvent *event = &events [i];
2704 MonoEvent *gevent = &ginfo->events [i];
2706 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2708 event->parent = klass;
2709 event->name = gevent->name;
2710 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2711 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2712 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2713 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2714 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2715 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2717 #ifndef MONO_SMALL_CONFIG
2718 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2720 event->attrs = gevent->attrs;
2723 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2724 count = last - first;
2727 mono_class_setup_methods (klass);
2728 if (mono_class_has_failure (klass)) {
2733 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2734 for (i = first; i < last; ++i) {
2735 MonoEvent *event = &events [i - first];
2737 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2738 event->parent = klass;
2739 event->attrs = cols [MONO_EVENT_FLAGS];
2740 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2742 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2743 int first_idx = mono_class_get_first_method_idx (klass);
2744 for (j = startm; j < endm; ++j) {
2747 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2749 if (klass->image->uncompressed_metadata) {
2751 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2752 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2753 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2755 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2758 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2759 case METHOD_SEMANTIC_ADD_ON:
2760 event->add = method;
2762 case METHOD_SEMANTIC_REMOVE_ON:
2763 event->remove = method;
2765 case METHOD_SEMANTIC_FIRE:
2766 event->raise = method;
2768 case METHOD_SEMANTIC_OTHER: {
2769 #ifndef MONO_SMALL_CONFIG
2772 if (event->other == NULL) {
2773 event->other = g_new0 (MonoMethod*, 2);
2775 while (event->other [n])
2777 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2779 event->other [n] = method;
2780 /* NULL terminated */
2781 event->other [n + 1] = NULL;
2792 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2793 info->events = events;
2794 info->first = first;
2795 info->count = count;
2797 mono_memory_barrier ();
2799 mono_class_set_event_info (klass, info);
2803 * Global pool of interface IDs, represented as a bitset.
2804 * LOCKING: Protected by the classes lock.
2806 static MonoBitSet *global_interface_bitset = NULL;
2809 * mono_unload_interface_ids:
2810 * @bitset: bit set of interface IDs
2812 * When an image is unloaded, the interface IDs associated with
2813 * the image are put back in the global pool of IDs so the numbers
2817 mono_unload_interface_ids (MonoBitSet *bitset)
2820 mono_bitset_sub (global_interface_bitset, bitset);
2825 mono_unload_interface_id (MonoClass *klass)
2827 if (global_interface_bitset && klass->interface_id) {
2829 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2835 * mono_get_unique_iid:
2836 * \param klass interface
2838 * Assign a unique integer ID to the interface represented by \p klass.
2839 * The ID will positive and as small as possible.
2840 * LOCKING: Acquires the classes lock.
2841 * \returns The new ID.
2844 mono_get_unique_iid (MonoClass *klass)
2848 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2852 if (!global_interface_bitset) {
2853 global_interface_bitset = mono_bitset_new (128, 0);
2856 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2858 int old_size = mono_bitset_size (global_interface_bitset);
2859 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2860 mono_bitset_free (global_interface_bitset);
2861 global_interface_bitset = new_set;
2864 mono_bitset_set (global_interface_bitset, iid);
2865 /* set the bit also in the per-image set */
2866 if (!mono_class_is_ginst (klass)) {
2867 if (klass->image->interface_bitset) {
2868 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2869 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2870 mono_bitset_free (klass->image->interface_bitset);
2871 klass->image->interface_bitset = new_set;
2874 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2876 mono_bitset_set (klass->image->interface_bitset, iid);
2881 #ifndef MONO_SMALL_CONFIG
2882 if (mono_print_vtable) {
2884 char *type_name = mono_type_full_name (&klass->byval_arg);
2885 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2886 if (gklass && !gklass->context.class_inst->is_open) {
2887 generic_id = gklass->context.class_inst->id;
2888 g_assert (generic_id != 0);
2892 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2897 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2898 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2899 g_assert (iid < INT_MAX);
2904 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2909 mono_class_setup_interfaces (klass, error);
2910 return_if_nok (error);
2912 for (i = 0; i < klass->interface_count; i++) {
2913 ic = klass->interfaces [i];
2916 *res = g_ptr_array_new ();
2917 if (*ifaces == NULL)
2918 *ifaces = g_hash_table_new (NULL, NULL);
2919 if (g_hash_table_lookup (*ifaces, ic))
2921 g_ptr_array_add (*res, ic);
2922 g_hash_table_insert (*ifaces, ic, ic);
2923 mono_class_init (ic);
2924 if (mono_class_has_failure (ic)) {
2925 mono_error_set_type_load_class (error, ic, "Error Loading class");
2929 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2930 return_if_nok (error);
2935 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2937 GPtrArray *res = NULL;
2938 GHashTable *ifaces = NULL;
2940 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2942 g_hash_table_destroy (ifaces);
2943 if (!mono_error_ok (error)) {
2945 g_ptr_array_free (res, TRUE);
2952 compare_interface_ids (const void *p_key, const void *p_element)
2954 const MonoClass *key = (const MonoClass *)p_key;
2955 const MonoClass *element = *(const MonoClass **)p_element;
2957 return (key->interface_id - element->interface_id);
2960 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2962 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2964 MonoClass **result = (MonoClass **)mono_binary_search (
2966 klass->interfaces_packed,
2967 klass->interface_offsets_count,
2968 sizeof (MonoClass *),
2969 compare_interface_ids);
2971 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2978 * mono_class_interface_offset_with_variance:
2980 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2981 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2983 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2985 * FIXME figure out MS disambiguation rules and fix this function.
2988 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2990 int i = mono_class_interface_offset (klass, itf);
2991 *non_exact_match = FALSE;
2995 if (itf->is_array_special_interface && klass->rank < 2) {
2996 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2998 for (i = 0; i < klass->interface_offsets_count; i++) {
2999 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
3000 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3001 *non_exact_match = TRUE;
3002 return klass->interface_offsets_packed [i];
3007 if (!mono_class_has_variant_generic_params (itf))
3010 for (i = 0; i < klass->interface_offsets_count; i++) {
3011 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3012 *non_exact_match = TRUE;
3013 return klass->interface_offsets_packed [i];
3021 print_implemented_interfaces (MonoClass *klass)
3025 GPtrArray *ifaces = NULL;
3027 int ancestor_level = 0;
3029 name = mono_type_get_full_name (klass);
3030 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3033 for (i = 0; i < klass->interface_offsets_count; i++)
3034 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3035 klass->interfaces_packed [i]->interface_id,
3036 klass->interface_offsets_packed [i],
3037 mono_class_get_method_count (klass->interfaces_packed [i]),
3038 klass->interfaces_packed [i]->name_space,
3039 klass->interfaces_packed [i]->name );
3040 printf ("Interface flags: ");
3041 for (i = 0; i <= klass->max_interface_id; i++)
3042 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3043 printf ("(%d,T)", i);
3045 printf ("(%d,F)", i);
3047 printf ("Dump interface flags:");
3048 #ifdef COMPRESSED_INTERFACE_BITMAP
3050 const uint8_t* p = klass->interface_bitmap;
3051 i = klass->max_interface_id;
3053 printf (" %d x 00 %02X", p [0], p [1]);
3059 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3060 printf (" %02X", klass->interface_bitmap [i]);
3063 while (klass != NULL) {
3064 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3065 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3066 if (!mono_error_ok (&error)) {
3067 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3068 mono_error_cleanup (&error);
3069 } else if (ifaces) {
3070 for (i = 0; i < ifaces->len; i++) {
3071 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3072 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3073 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3075 mono_class_interface_offset (klass, ic),
3076 mono_class_get_method_count (ic),
3080 g_ptr_array_free (ifaces, TRUE);
3083 klass = klass->parent;
3088 * Return the number of virtual methods.
3089 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3090 * Return -1 on failure.
3091 * FIXME It would be nice if this information could be cached somewhere.
3094 count_virtual_methods (MonoClass *klass)
3096 int i, mcount, vcount = 0;
3098 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3100 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3101 mono_class_setup_methods (klass);
3102 if (mono_class_has_failure (klass))
3105 mcount = mono_class_get_method_count (klass);
3106 for (i = 0; i < mcount; ++i) {
3107 flags = klass->methods [i]->flags;
3108 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3112 int first_idx = mono_class_get_first_method_idx (klass);
3113 mcount = mono_class_get_method_count (klass);
3114 for (i = 0; i < mcount; ++i) {
3115 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3117 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3125 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3133 m = (l + num_ifaces) / 2;
3134 if (interfaces_full [m] == ic)
3136 if (l == num_ifaces)
3138 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3147 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3149 int i = find_interface (num_ifaces, interfaces_full, ic);
3153 interface_offsets_full [i] = offset;
3156 for (i = 0; i < num_ifaces; ++i) {
3157 if (interfaces_full [i]) {
3159 if (interfaces_full [i]->interface_id < ic->interface_id)
3162 while (end < num_ifaces && interfaces_full [end]) end++;
3163 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3164 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3166 interfaces_full [i] = ic;
3167 interface_offsets_full [i] = offset;
3173 #ifdef COMPRESSED_INTERFACE_BITMAP
3176 * Compressed interface bitmap design.
3178 * Interface bitmaps take a large amount of memory, because their size is
3179 * linear with the maximum interface id assigned in the process (each interface
3180 * is assigned a unique id as it is loaded). The number of interface classes
3181 * is high because of the many implicit interfaces implemented by arrays (we'll
3182 * need to lazy-load them in the future).
3183 * Most classes implement a very small number of interfaces, so the bitmap is
3184 * sparse. This bitmap needs to be checked by interface casts, so access to the
3185 * needed bit must be fast and doable with few jit instructions.
3187 * The current compression format is as follows:
3188 * *) it is a sequence of one or more two-byte elements
3189 * *) the first byte in the element is the count of empty bitmap bytes
3190 * at the current bitmap position
3191 * *) the second byte in the element is an actual bitmap byte at the current
3194 * As an example, the following compressed bitmap bytes:
3195 * 0x07 0x01 0x00 0x7
3196 * correspond to the following bitmap:
3197 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3199 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3200 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3201 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3205 * mono_compress_bitmap:
3206 * \param dest destination buffer
3207 * \param bitmap bitmap buffer
3208 * \param size size of \p bitmap in bytes
3210 * This is a mono internal function.
3211 * The \p bitmap data is compressed into a format that is small but
3212 * still searchable in few instructions by the JIT and runtime.
3213 * The compressed data is stored in the buffer pointed to by the
3214 * \p dest array. Passing a NULL value for \p dest allows to just compute
3215 * the size of the buffer.
3216 * This compression algorithm assumes the bits set in the bitmap are
3217 * few and far between, like in interface bitmaps.
3218 * \returns The size of the compressed bitmap in bytes.
3221 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3225 const uint8_t *end = bitmap + size;
3226 while (bitmap < end) {
3227 if (*bitmap || numz == 255) {
3251 * mono_class_interface_match:
3252 * \param bitmap a compressed bitmap buffer
3253 * \param id the index to check in the bitmap
3255 * This is a mono internal function.
3256 * Checks if a bit is set in a compressed interface bitmap. \p id must
3257 * be already checked for being smaller than the maximum id encoded in the
3260 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3264 mono_class_interface_match (const uint8_t *bitmap, int id)
3267 id -= bitmap [0] * 8;
3271 return bitmap [1] & (1 << id);
3280 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3281 * LOCKING: Acquires the loader lock.
3284 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3288 int i, j, num_ifaces;
3290 MonoClass **interfaces_full = NULL;
3291 int *interface_offsets_full = NULL;
3293 GPtrArray **ifaces_array = NULL;
3294 int interface_offsets_count;
3296 mono_loader_lock ();
3298 mono_class_setup_supertypes (klass);
3300 /* compute maximum number of slots and maximum interface id */
3302 num_ifaces = 0; /* this can include duplicated ones */
3303 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3304 for (j = 0; j < klass->idepth; j++) {
3305 k = klass->supertypes [j];
3307 num_ifaces += k->interface_count;
3308 for (i = 0; i < k->interface_count; i++) {
3309 ic = k->interfaces [i];
3311 mono_class_init (ic);
3313 if (max_iid < ic->interface_id)
3314 max_iid = ic->interface_id;
3316 ifaces = mono_class_get_implemented_interfaces (k, &error);
3317 if (!mono_error_ok (&error)) {
3318 char *name = mono_type_get_full_name (k);
3319 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3321 mono_error_cleanup (&error);
3326 num_ifaces += ifaces->len;
3327 for (i = 0; i < ifaces->len; ++i) {
3328 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3329 if (max_iid < ic->interface_id)
3330 max_iid = ic->interface_id;
3332 ifaces_array [j] = ifaces;
3336 if (MONO_CLASS_IS_INTERFACE (klass)) {
3338 if (max_iid < klass->interface_id)
3339 max_iid = klass->interface_id;
3342 /* compute vtable offset for interfaces */
3343 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3344 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3346 for (i = 0; i < num_ifaces; i++)
3347 interface_offsets_full [i] = -1;
3349 /* skip the current class */
3350 for (j = 0; j < klass->idepth - 1; j++) {
3351 k = klass->supertypes [j];
3352 ifaces = ifaces_array [j];
3355 for (i = 0; i < ifaces->len; ++i) {
3357 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3359 /*Force the sharing of interface offsets between parent and subtypes.*/
3360 io = mono_class_interface_offset (k, ic);
3362 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3367 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3368 ifaces = ifaces_array [klass->idepth - 1];
3370 for (i = 0; i < ifaces->len; ++i) {
3372 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3373 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3375 count = count_virtual_methods (ic);
3377 char *name = mono_type_get_full_name (ic);
3378 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3387 if (MONO_CLASS_IS_INTERFACE (klass))
3388 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3390 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3391 if (interface_offsets_full [i] != -1)
3392 interface_offsets_count ++;
3395 /* Publish the data */
3396 klass->max_interface_id = max_iid;
3398 * We might get called multiple times:
3399 * - mono_class_init ()
3400 * - mono_class_setup_vtable ().
3401 * - mono_class_setup_interface_offsets ().
3402 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3403 * means we have to overwrite those when called from other places (#4440).
3405 if (klass->interfaces_packed) {
3407 g_assert (klass->interface_offsets_count == interface_offsets_count);
3411 klass->interface_offsets_count = interface_offsets_count;
3412 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3413 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3414 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3415 #ifdef COMPRESSED_INTERFACE_BITMAP
3416 bitmap = g_malloc0 (bsize);
3418 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3420 for (i = 0; i < interface_offsets_count; i++) {
3421 guint32 id = interfaces_full [i]->interface_id;
3422 bitmap [id >> 3] |= (1 << (id & 7));
3423 klass->interfaces_packed [i] = interfaces_full [i];
3424 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3426 #ifdef COMPRESSED_INTERFACE_BITMAP
3427 i = mono_compress_bitmap (NULL, bitmap, bsize);
3428 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3429 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3432 klass->interface_bitmap = bitmap;
3436 mono_loader_unlock ();
3438 g_free (interfaces_full);
3439 g_free (interface_offsets_full);
3440 for (i = 0; i < klass->idepth; i++) {
3441 ifaces = ifaces_array [i];
3443 g_ptr_array_free (ifaces, TRUE);
3445 g_free (ifaces_array);
3447 //printf ("JUST DONE: ");
3448 //print_implemented_interfaces (klass);
3454 * Setup interface offsets for interfaces.
3456 * - klass->max_interface_id
3457 * - klass->interface_offsets_count
3458 * - klass->interfaces_packed
3459 * - klass->interface_offsets_packed
3460 * - klass->interface_bitmap
3462 * This function can fail @class.
3465 mono_class_setup_interface_offsets (MonoClass *klass)
3467 setup_interface_offsets (klass, 0, FALSE);
3470 /*Checks if @klass has @parent as one of it's parents type gtd
3474 * Bar<T> : Foo<Bar<Bar<T>>>
3478 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3480 klass = mono_class_get_generic_type_definition (klass);
3481 parent = mono_class_get_generic_type_definition (parent);
3482 mono_class_setup_supertypes (klass);
3483 mono_class_setup_supertypes (parent);
3485 return klass->idepth >= parent->idepth &&
3486 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3490 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3492 MonoGenericInst *ginst;
3495 if (!mono_class_is_ginst (klass)) {
3496 mono_class_setup_vtable_full (klass, in_setup);
3497 return !mono_class_has_failure (klass);
3500 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3501 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3504 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3505 for (i = 0; i < ginst->type_argc; ++i) {
3507 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3509 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3510 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3511 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3513 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3514 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3522 * mono_class_setup_vtable:
3524 * Creates the generic vtable of CLASS.
3525 * Initializes the following fields in MonoClass:
3528 * Plus all the fields initialized by setup_interface_offsets ().
3529 * If there is an error during vtable construction, klass->has_failure
3530 * is set and details are stored in a MonoErrorBoxed.
3532 * LOCKING: Acquires the loader lock.
3535 mono_class_setup_vtable (MonoClass *klass)
3537 mono_class_setup_vtable_full (klass, NULL);
3541 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3544 MonoMethod **overrides;
3545 MonoGenericContext *context;
3553 if (MONO_CLASS_IS_INTERFACE (klass)) {
3554 /* This sets method->slot for all methods if this is an interface */
3555 mono_class_setup_methods (klass);
3559 if (mono_class_has_failure (klass))
3562 if (g_list_find (in_setup, klass))
3565 mono_loader_lock ();
3567 if (klass->vtable) {
3568 mono_loader_unlock ();
3572 mono_stats.generic_vtable_count ++;
3573 in_setup = g_list_prepend (in_setup, klass);
3575 if (mono_class_is_ginst (klass)) {
3576 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3577 mono_loader_unlock ();
3578 g_list_remove (in_setup, klass);
3582 context = mono_class_get_context (klass);
3583 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3585 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3586 type_token = klass->type_token;
3589 if (image_is_dynamic (klass->image)) {
3590 /* Generic instances can have zero method overrides without causing any harm.
3591 * This is true since we don't do layout all over again for them, we simply inflate
3592 * the layout of the parent.
3594 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3595 if (!is_ok (&error)) {
3596 mono_loader_unlock ();
3597 g_list_remove (in_setup, klass);
3598 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3599 mono_error_cleanup (&error);
3603 /* The following call fails if there are missing methods in the type */
3604 /* FIXME it's probably a good idea to avoid this for generic instances. */
3605 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3609 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3611 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3615 mono_loader_unlock ();
3616 g_list_remove (in_setup, klass);
3621 #define DEBUG_INTERFACE_VTABLE_CODE 0
3622 #define TRACE_INTERFACE_VTABLE_CODE 0
3623 #define VERIFY_INTERFACE_VTABLE_CODE 0
3624 #define VTABLE_SELECTOR (1)
3626 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3627 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3628 if (!(VTABLE_SELECTOR)) break; \
3632 #define DEBUG_INTERFACE_VTABLE(stmt)
3635 #if TRACE_INTERFACE_VTABLE_CODE
3636 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3637 if (!(VTABLE_SELECTOR)) break; \
3641 #define TRACE_INTERFACE_VTABLE(stmt)
3644 #if VERIFY_INTERFACE_VTABLE_CODE
3645 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3646 if (!(VTABLE_SELECTOR)) break; \
3650 #define VERIFY_INTERFACE_VTABLE(stmt)
3654 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3656 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3660 GString *res = g_string_new ("");
3662 g_string_append_c (res, '(');
3663 for (i = 0; i < sig->param_count; ++i) {
3665 g_string_append_c (res, ',');
3666 mono_type_get_desc (res, sig->params [i], include_namespace);
3668 g_string_append (res, ")=>");
3669 if (sig->ret != NULL) {
3670 mono_type_get_desc (res, sig->ret, include_namespace);
3672 g_string_append (res, "NULL");
3675 g_string_free (res, FALSE);
3679 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3680 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3681 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3682 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3690 is_wcf_hack_disabled (void)
3692 static gboolean disabled;
3693 static gboolean inited = FALSE;
3695 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3702 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3704 MonoMethodSignature *cmsig, *imsig;
3705 if (strcmp (im->name, cm->name) == 0) {
3706 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3707 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3710 if (! slot_is_empty) {
3711 if (require_newslot) {
3712 if (! interface_is_explicitly_implemented_by_class) {
3713 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3716 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3717 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3721 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3724 cmsig = mono_method_signature (cm);
3725 imsig = mono_method_signature (im);
3726 if (!cmsig || !imsig) {
3727 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3731 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3732 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3733 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3734 TRACE_INTERFACE_VTABLE (printf ("]"));
3737 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3738 if (mono_security_core_clr_enabled ())
3739 mono_security_core_clr_check_override (klass, cm, im);
3741 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3742 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3743 char *body_name = mono_method_full_name (cm, TRUE);
3744 char *decl_name = mono_method_full_name (im, TRUE);
3745 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3753 MonoClass *ic = im->klass;
3754 const char *ic_name_space = ic->name_space;
3755 const char *ic_name = ic->name;
3758 if (! require_newslot) {
3759 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3762 if (cm->klass->rank == 0) {
3763 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3766 cmsig = mono_method_signature (cm);
3767 imsig = mono_method_signature (im);
3768 if (!cmsig || !imsig) {
3769 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3773 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3774 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3775 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3776 TRACE_INTERFACE_VTABLE (printf ("]"));
3779 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3780 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3783 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3784 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3787 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))) {
3788 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3792 subname = strstr (cm->name, ic_name_space);
3793 if (subname != cm->name) {
3794 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3797 subname += strlen (ic_name_space);
3798 if (subname [0] != '.') {
3799 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3803 if (strstr (subname, ic_name) != subname) {
3804 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3807 subname += strlen (ic_name);
3808 if (subname [0] != '.') {
3809 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3813 if (strcmp (subname, im->name) != 0) {
3814 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3818 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3819 if (mono_security_core_clr_enabled ())
3820 mono_security_core_clr_check_override (klass, cm, im);
3822 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3823 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3824 char *body_name = mono_method_full_name (cm, TRUE);
3825 char *decl_name = mono_method_full_name (im, TRUE);
3826 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3836 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3838 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3839 MonoMethod *method = key;
3840 MonoMethod *override = value;
3841 MonoClass *method_class = mono_method_get_class (method);
3842 MonoClass *override_class = mono_method_get_class (override);
3844 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3845 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3846 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3849 print_overrides (GHashTable *override_map, const char *message) {
3851 printf ("Override map \"%s\" START:\n", message);
3852 g_hash_table_foreach (override_map, foreach_override, NULL);
3853 printf ("Override map \"%s\" END.\n", message);
3855 printf ("Override map \"%s\" EMPTY.\n", message);
3859 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3860 char *full_name = mono_type_full_name (&klass->byval_arg);
3864 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3866 if (print_interfaces) {
3867 print_implemented_interfaces (klass);
3868 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3871 if (klass->parent) {
3872 parent_size = klass->parent->vtable_size;
3876 for (i = 0; i < size; ++i) {
3877 MonoMethod *cm = vtable [i];
3878 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3879 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3881 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3889 #if VERIFY_INTERFACE_VTABLE_CODE
3891 mono_method_try_get_vtable_index (MonoMethod *method)
3893 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3894 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3895 if (imethod->declaring->is_generic)
3896 return imethod->declaring->slot;
3898 return method->slot;
3902 mono_class_verify_vtable (MonoClass *klass)
3905 char *full_name = mono_type_full_name (&klass->byval_arg);
3907 printf ("*** Verifying VTable of class '%s' \n", full_name);
3911 if (!klass->methods)
3914 count = mono_class_method_count (klass);
3915 for (i = 0; i < count; ++i) {
3916 MonoMethod *cm = klass->methods [i];
3919 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3923 full_name = mono_method_full_name (cm, TRUE);
3925 slot = mono_method_try_get_vtable_index (cm);
3927 if (slot >= klass->vtable_size) {
3928 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3932 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3933 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3934 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3935 g_free (other_name);
3938 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3945 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3948 char *method_signature;
3951 for (index = 0; index < onum; ++index) {
3952 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3953 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3955 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3956 type_name = mono_type_full_name (&klass->byval_arg);
3957 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3958 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3959 g_free (method_signature);
3961 mono_class_setup_methods (klass);
3962 if (mono_class_has_failure (klass)) {
3963 char *name = mono_type_get_full_name (klass);
3964 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3968 mcount = mono_class_get_method_count (klass);
3969 for (index = 0; index < mcount; ++index) {
3970 MonoMethod *cm = klass->methods [index];
3971 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3973 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3974 g_free (method_signature);
3979 mono_method_get_method_definition (MonoMethod *method)
3981 while (method->is_inflated)
3982 method = ((MonoMethodInflated*)method)->declaring;
3987 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3991 for (i = 0; i < onum; ++i) {
3992 MonoMethod *decl = overrides [i * 2];
3993 MonoMethod *body = overrides [i * 2 + 1];
3995 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3996 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4000 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4001 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4002 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4004 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4008 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4009 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4010 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4012 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4016 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4017 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4021 body = mono_method_get_method_definition (body);
4022 decl = mono_method_get_method_definition (decl);
4024 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4025 char *body_name = mono_method_full_name (body, TRUE);
4026 char *decl_name = mono_method_full_name (decl, TRUE);
4027 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4037 mono_class_need_stelemref_method (MonoClass *klass)
4039 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4043 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4046 dslot = mono_method_get_vtable_slot (decl);
4048 mono_class_set_type_load_failure (klass, "");
4052 dslot += mono_class_interface_offset (klass, decl->klass);
4053 vtable [dslot] = override;
4054 if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4056 * If override from an interface, then it is an override of a default interface method,
4057 * don't override its slot.
4059 vtable [dslot]->slot = dslot;
4062 if (mono_security_core_clr_enabled ())
4063 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4069 * LOCKING: this is supposed to be called with the loader lock held.
4072 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4076 MonoMethod **vtable = NULL;
4077 int i, max_vtsize = 0, cur_slot = 0;
4079 GPtrArray *ifaces = NULL;
4080 GHashTable *override_map = NULL;
4082 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4083 int first_non_interface_slot;
4085 GSList *virt_methods = NULL, *l;
4086 int stelemref_slot = 0;
4091 if (overrides && !verify_class_overrides (klass, overrides, onum))
4094 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4095 if (!mono_error_ok (&error)) {
4096 char *name = mono_type_get_full_name (klass);
4097 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4099 mono_error_cleanup (&error);
4101 } else if (ifaces) {
4102 for (i = 0; i < ifaces->len; i++) {
4103 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4104 max_vtsize += mono_class_get_method_count (ic);
4106 g_ptr_array_free (ifaces, TRUE);
4110 if (klass->parent) {
4111 mono_class_init (klass->parent);
4112 mono_class_setup_vtable_full (klass->parent, in_setup);
4114 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4117 max_vtsize += klass->parent->vtable_size;
4118 cur_slot = klass->parent->vtable_size;
4121 max_vtsize += mono_class_get_method_count (klass);
4123 /*Array have a slot for stelemref*/
4124 if (mono_class_need_stelemref_method (klass)) {
4125 stelemref_slot = cur_slot;
4130 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4132 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4133 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4136 max_iid = klass->max_interface_id;
4137 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4139 /* Optimized version for generic instances */
4140 if (mono_class_is_ginst (klass)) {
4142 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4145 mono_class_setup_vtable_full (gklass, in_setup);
4146 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4149 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4150 klass->vtable_size = gklass->vtable_size;
4151 for (i = 0; i < gklass->vtable_size; ++i)
4152 if (gklass->vtable [i]) {
4153 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4154 if (!mono_error_ok (&error)) {
4155 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4156 mono_error_cleanup (&error);
4160 tmp [i]->slot = gklass->vtable [i]->slot;
4162 mono_memory_barrier ();
4163 klass->vtable = tmp;
4165 /* Have to set method->slot for abstract virtual methods */
4166 if (klass->methods && gklass->methods) {
4167 int mcount = mono_class_get_method_count (klass);
4168 for (i = 0; i < mcount; ++i)
4169 if (klass->methods [i]->slot == -1)
4170 klass->methods [i]->slot = gklass->methods [i]->slot;
4176 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4178 if (klass->parent && klass->parent->vtable_size) {
4179 MonoClass *parent = klass->parent;
4182 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4184 // Also inherit parent interface vtables, just as a starting point.
4185 // This is needed otherwise bug-77127.exe fails when the property methods
4186 // have different names in the iterface and the class, because for child
4187 // classes the ".override" information is not used anymore.
4188 for (i = 0; i < parent->interface_offsets_count; i++) {
4189 MonoClass *parent_interface = parent->interfaces_packed [i];
4190 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4191 /*FIXME this is now dead code as this condition will never hold true.
4192 Since interface offsets are inherited then the offset of an interface implemented
4193 by a parent will never be the out of it's vtable boundary.
4195 if (interface_offset >= parent->vtable_size) {
4196 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4199 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4200 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4201 int mcount = mono_class_get_method_count (parent_interface);
4202 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4203 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4204 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4205 parent_interface_offset + j, parent_interface_offset, j,
4206 interface_offset + j, interface_offset, j));
4213 /*Array have a slot for stelemref*/
4214 if (mono_class_need_stelemref_method (klass)) {
4215 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4217 method->slot = stelemref_slot;
4219 g_assert (method->slot == stelemref_slot);
4221 vtable [stelemref_slot] = method;
4224 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4226 /* Process overrides from interface default methods */
4227 // FIXME: Ordering between interfaces
4228 for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4229 ic = klass->interfaces_packed [ifindex];
4231 mono_class_setup_methods (ic);
4232 if (mono_class_has_failure (ic))
4235 MonoMethod **iface_overrides;
4237 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4239 for (int i = 0; i < iface_onum; i++) {
4240 MonoMethod *decl = iface_overrides [i*2];
4241 MonoMethod *override = iface_overrides [i*2 + 1];
4242 if (!apply_override (klass, vtable, decl, override))
4246 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4247 g_hash_table_insert (override_map, decl, override);
4249 g_free (iface_overrides);
4253 /* override interface methods */
4254 for (i = 0; i < onum; i++) {
4255 MonoMethod *decl = overrides [i*2];
4256 MonoMethod *override = overrides [i*2 + 1];
4257 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4258 if (!apply_override (klass, vtable, decl, override))
4262 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4263 g_hash_table_insert (override_map, decl, override);
4267 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4268 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4271 * Create a list of virtual methods to avoid calling
4272 * mono_class_get_virtual_methods () which is slow because of the metadata
4276 gpointer iter = NULL;
4279 virt_methods = NULL;
4280 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4281 virt_methods = g_slist_prepend (virt_methods, cm);
4283 if (mono_class_has_failure (klass))
4287 // Loop on all implemented interfaces...
4288 for (i = 0; i < klass->interface_offsets_count; i++) {
4289 MonoClass *parent = klass->parent;
4291 gboolean interface_is_explicitly_implemented_by_class;
4294 ic = klass->interfaces_packed [i];
4295 ic_offset = mono_class_interface_offset (klass, ic);
4297 mono_class_setup_methods (ic);
4298 if (mono_class_has_failure (ic))
4301 // Check if this interface is explicitly implemented (instead of just inherited)
4302 if (parent != NULL) {
4303 int implemented_interfaces_index;
4304 interface_is_explicitly_implemented_by_class = FALSE;
4305 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4306 if (ic == klass->interfaces [implemented_interfaces_index]) {
4307 interface_is_explicitly_implemented_by_class = TRUE;
4312 interface_is_explicitly_implemented_by_class = TRUE;
4315 // Loop on all interface methods...
4316 int mcount = mono_class_get_method_count (ic);
4317 for (im_index = 0; im_index < mcount; im_index++) {
4318 MonoMethod *im = ic->methods [im_index];
4319 int im_slot = ic_offset + im->slot;
4320 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4322 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4325 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4327 // If there is an explicit implementation, just use it right away,
4328 // otherwise look for a matching method
4329 if (override_im == NULL) {
4333 // First look for a suitable method among the class methods
4334 for (l = virt_methods; l; l = l->next) {
4335 cm = (MonoMethod *)l->data;
4336 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)));
4337 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4338 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4339 vtable [im_slot] = cm;
4340 /* Why do we need this? */
4345 TRACE_INTERFACE_VTABLE (printf ("\n"));
4346 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4350 // If the slot is still empty, look in all the inherited virtual methods...
4351 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4352 MonoClass *parent = klass->parent;
4353 // Reverse order, so that last added methods are preferred
4354 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4355 MonoMethod *cm = parent->vtable [cm_index];
4357 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));
4358 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4359 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4360 vtable [im_slot] = cm;
4361 /* Why do we need this? */
4367 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4369 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4373 if (vtable [im_slot] == NULL) {
4374 if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4375 TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
4376 vtable [im_slot] = im;
4380 g_assert (vtable [im_slot] == override_im);
4385 // If the class is not abstract, check that all its interface slots are full.
4386 // The check is done here and not directly at the end of the loop above because
4387 // it can happen (for injected generic array interfaces) that the same slot is
4388 // processed multiple times (those interfaces have overlapping slots), and it
4389 // will not always be the first pass the one that fills the slot.
4390 if (!mono_class_is_abstract (klass)) {
4391 for (i = 0; i < klass->interface_offsets_count; i++) {
4395 ic = klass->interfaces_packed [i];
4396 ic_offset = mono_class_interface_offset (klass, ic);
4398 int mcount = mono_class_get_method_count (ic);
4399 for (im_index = 0; im_index < mcount; im_index++) {
4400 MonoMethod *im = ic->methods [im_index];
4401 int im_slot = ic_offset + im->slot;
4403 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4406 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4407 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4408 if (vtable [im_slot] == NULL) {
4409 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4416 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4417 for (l = virt_methods; l; l = l->next) {
4418 cm = (MonoMethod *)l->data;
4420 * If the method is REUSE_SLOT, we must check in the
4421 * base class for a method to override.
4423 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4425 for (k = klass->parent; k ; k = k->parent) {
4430 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4431 MonoMethodSignature *cmsig, *m1sig;
4433 cmsig = mono_method_signature (cm);
4434 m1sig = mono_method_signature (m1);
4436 if (!cmsig || !m1sig) {
4437 /* FIXME proper error message */
4438 mono_class_set_type_load_failure (klass, "");
4442 if (!strcmp(cm->name, m1->name) &&
4443 mono_metadata_signature_equal (cmsig, m1sig)) {
4445 if (mono_security_core_clr_enabled ())
4446 mono_security_core_clr_check_override (klass, cm, m1);
4448 slot = mono_method_get_vtable_slot (m1);
4452 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4453 char *body_name = mono_method_full_name (cm, TRUE);
4454 char *decl_name = mono_method_full_name (m1, TRUE);
4455 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4461 g_assert (cm->slot < max_vtsize);
4463 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4464 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4465 mono_method_full_name (m1, 1), m1,
4466 mono_method_full_name (cm, 1), cm));
4467 g_hash_table_insert (override_map, m1, cm);
4471 if (mono_class_has_failure (k))
4481 /*Non final newslot methods must be given a non-interface vtable slot*/
4482 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4486 cm->slot = cur_slot++;
4488 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4489 vtable [cm->slot] = cm;
4492 /* override non interface methods */
4493 for (i = 0; i < onum; i++) {
4494 MonoMethod *decl = overrides [i*2];
4495 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4496 g_assert (decl->slot != -1);
4497 vtable [decl->slot] = overrides [i*2 + 1];
4498 overrides [i * 2 + 1]->slot = decl->slot;
4500 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4501 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4502 mono_method_full_name (decl, 1), decl,
4503 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4504 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4506 if (mono_security_core_clr_enabled ())
4507 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4512 * If a method occupies more than one place in the vtable, and it is
4513 * overriden, then change the other occurances too.
4518 for (i = 0; i < max_vtsize; ++i)
4520 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4522 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4527 g_hash_table_destroy (override_map);
4528 override_map = NULL;
4531 g_slist_free (virt_methods);
4532 virt_methods = NULL;
4534 g_assert (cur_slot <= max_vtsize);
4536 /* Ensure that all vtable slots are filled with concrete instance methods */
4537 if (!mono_class_is_abstract (klass)) {
4538 for (i = 0; i < cur_slot; ++i) {
4539 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4540 char *type_name = mono_type_get_full_name (klass);
4541 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4542 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4544 g_free (method_name);
4551 if (mono_class_is_ginst (klass)) {
4552 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4554 mono_class_init (gklass);
4556 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4558 /* Check that the vtable_size value computed in mono_class_init () is correct */
4559 if (klass->vtable_size)
4560 g_assert (cur_slot == klass->vtable_size);
4561 klass->vtable_size = cur_slot;
4564 /* Try to share the vtable with our parent. */
4565 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4566 mono_memory_barrier ();
4567 klass->vtable = klass->parent->vtable;
4569 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4570 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4571 mono_memory_barrier ();
4572 klass->vtable = tmp;
4575 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4576 if (mono_print_vtable) {
4579 print_implemented_interfaces (klass);
4581 for (i = 0; i <= max_iid; i++)
4582 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4585 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4586 klass->vtable_size, icount);
4588 for (i = 0; i < cur_slot; ++i) {
4593 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4594 mono_method_full_name (cm, TRUE));
4600 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4601 klass->name, max_iid);
4603 for (i = 0; i < klass->interface_count; i++) {
4604 ic = klass->interfaces [i];
4605 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4606 mono_class_interface_offset (klass, ic),
4607 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4610 for (k = klass->parent; k ; k = k->parent) {
4611 for (i = 0; i < k->interface_count; i++) {
4612 ic = k->interfaces [i];
4613 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4614 mono_class_interface_offset (klass, ic),
4615 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4623 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4628 char *name = mono_type_get_full_name (klass);
4629 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4633 g_hash_table_destroy (override_map);
4635 g_slist_free (virt_methods);
4640 * mono_method_get_vtable_slot:
4642 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4643 * LOCKING: Acquires the loader lock.
4645 * FIXME Use proper MonoError machinery here.
4648 mono_method_get_vtable_slot (MonoMethod *method)
4650 if (method->slot == -1) {
4651 mono_class_setup_vtable (method->klass);
4652 if (mono_class_has_failure (method->klass))
4654 if (method->slot == -1) {
4658 if (!mono_class_is_ginst (method->klass)) {
4659 g_assert (method->is_inflated);
4660 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4663 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4664 g_assert (mono_class_is_ginst (method->klass));
4665 gklass = mono_class_get_generic_class (method->klass)->container_class;
4666 mono_class_setup_methods (method->klass);
4667 g_assert (method->klass->methods);
4668 mcount = mono_class_get_method_count (method->klass);
4669 for (i = 0; i < mcount; ++i) {
4670 if (method->klass->methods [i] == method)
4673 g_assert (i < mcount);
4674 g_assert (gklass->methods);
4675 method->slot = gklass->methods [i]->slot;
4677 g_assert (method->slot != -1);
4679 return method->slot;
4683 * mono_method_get_vtable_index:
4684 * \param method a method
4686 * Returns the index into the runtime vtable to access the method or,
4687 * in the case of a virtual generic method, the virtual generic method
4688 * thunk. Returns -1 on failure.
4690 * FIXME Use proper MonoError machinery here.
4693 mono_method_get_vtable_index (MonoMethod *method)
4695 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4696 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4697 if (imethod->declaring->is_generic)
4698 return mono_method_get_vtable_slot (imethod->declaring);
4700 return mono_method_get_vtable_slot (method);
4703 static MonoMethod *default_ghc = NULL;
4704 static MonoMethod *default_finalize = NULL;
4705 static int finalize_slot = -1;
4706 static int ghc_slot = -1;
4709 initialize_object_slots (MonoClass *klass)
4714 if (klass == mono_defaults.object_class) {
4715 mono_class_setup_vtable (klass);
4716 for (i = 0; i < klass->vtable_size; ++i) {
4717 MonoMethod *cm = klass->vtable [i];
4719 if (!strcmp (cm->name, "GetHashCode"))
4721 else if (!strcmp (cm->name, "Finalize"))
4725 g_assert (ghc_slot > 0);
4726 default_ghc = klass->vtable [ghc_slot];
4728 g_assert (finalize_slot > 0);
4729 default_finalize = klass->vtable [finalize_slot];
4734 MonoMethod *array_method;
4736 } GenericArrayMethodInfo;
4738 static int generic_array_method_num = 0;
4739 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4742 generic_array_methods (MonoClass *klass)
4744 int i, count_generic = 0, mcount;
4745 GList *list = NULL, *tmp;
4746 if (generic_array_method_num)
4747 return generic_array_method_num;
4748 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4749 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4750 mcount = mono_class_get_method_count (klass->parent);
4751 for (i = 0; i < mcount; i++) {
4752 MonoMethod *m = klass->parent->methods [i];
4753 if (!strncmp (m->name, "InternalArray__", 15)) {
4755 list = g_list_prepend (list, m);
4758 list = g_list_reverse (list);
4759 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4761 for (tmp = list; tmp; tmp = tmp->next) {
4762 const char *mname, *iname;
4764 MonoMethod *m = (MonoMethod *)tmp->data;
4765 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4766 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4768 generic_array_method_info [i].array_method = m;
4769 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4770 iname = "System.Collections.Generic.ICollection`1.";
4771 mname = m->name + 27;
4772 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4773 iname = "System.Collections.Generic.IEnumerable`1.";
4774 mname = m->name + 27;
4775 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4776 iname = "System.Collections.Generic.IReadOnlyList`1.";
4777 mname = m->name + strlen (ireadonlylist_prefix);
4778 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4779 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4780 mname = m->name + strlen (ireadonlycollection_prefix);
4781 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4782 iname = "System.Collections.Generic.IList`1.";
4783 mname = m->name + 15;
4785 g_assert_not_reached ();
4788 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4789 strcpy (name, iname);
4790 strcpy (name + strlen (iname), mname);
4791 generic_array_method_info [i].name = name;
4794 /*g_print ("array generic methods: %d\n", count_generic);*/
4796 generic_array_method_num = count_generic;
4798 return generic_array_method_num;
4802 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4804 MonoGenericContext tmp_context;
4807 tmp_context.class_inst = NULL;
4808 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4809 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4811 for (i = 0; i < generic_array_method_num; i++) {
4813 MonoMethod *m = generic_array_method_info [i].array_method;
4814 MonoMethod *inflated, *helper;
4816 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4817 mono_error_assert_ok (&error);
4818 helper = g_hash_table_lookup (cache, inflated);
4820 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4821 g_hash_table_insert (cache, inflated, helper);
4823 methods [pos ++] = helper;
4828 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4830 int null_length = strlen ("(null)");
4831 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4832 char *s = (char *)mono_image_alloc (image, len);
4835 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4836 g_assert (result == len - 1);
4843 * \param klass the class to initialize
4845 * Compute the \c instance_size, \c class_size and other infos that cannot be
4846 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4847 * Initializes the following fields in \p klass:
4848 * - all the fields initialized by \c mono_class_init_sizes
4853 * LOCKING: Acquires the loader lock.
4855 * \returns TRUE on success or FALSE if there was a problem in loading
4856 * the type (incorrect assemblies, missing assemblies, methods, etc).
4859 mono_class_init (MonoClass *klass)
4861 int i, vtable_size = 0, array_method_count = 0;
4862 MonoCachedClassInfo cached_info;
4863 gboolean has_cached_info;
4864 gboolean locked = FALSE;
4865 gboolean ghcimpl = FALSE;
4866 gboolean has_cctor = FALSE;
4867 int first_iface_slot = 0;
4871 /* Double-checking locking pattern */
4872 if (klass->inited || mono_class_has_failure (klass))
4873 return !mono_class_has_failure (klass);
4875 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4878 * This function can recursively call itself.
4880 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4881 if (g_slist_find (init_list, klass)) {
4882 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4885 init_list = g_slist_prepend (init_list, klass);
4886 mono_native_tls_set_value (init_pending_tls_id, init_list);
4889 * We want to avoid doing complicated work inside locks, so we compute all the required
4890 * information and write it to @klass inside a lock.
4893 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4894 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4898 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4899 MonoClass *element_class = klass->element_class;
4900 if (!element_class->inited)
4901 mono_class_init (element_class);
4902 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4906 mono_stats.initialized_class_count++;
4908 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4909 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4911 mono_class_init (gklass);
4912 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4915 mono_class_setup_interface_id (klass);
4918 if (klass->parent && !klass->parent->inited)
4919 mono_class_init (klass->parent);
4921 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4923 /* Compute instance size etc. */
4924 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4925 if (mono_class_has_failure (klass))
4928 mono_class_setup_supertypes (klass);
4931 initialize_object_slots (klass);
4934 * Initialize the rest of the data without creating a generic vtable if possible.
4935 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4936 * also avoid computing a generic vtable.
4938 if (has_cached_info) {
4940 vtable_size = cached_info.vtable_size;
4941 ghcimpl = cached_info.ghcimpl;
4942 has_cctor = cached_info.has_cctor;
4943 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4944 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4945 * The first slot if for array with.
4947 static int szarray_vtable_size[2] = { 0 };
4949 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4952 if (!szarray_vtable_size [slot]) {
4953 mono_class_setup_vtable (klass);
4954 szarray_vtable_size [slot] = klass->vtable_size;
4955 vtable_size = klass->vtable_size;
4957 vtable_size = szarray_vtable_size[slot];
4959 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4960 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4962 /* Generic instance case */
4963 ghcimpl = gklass->ghcimpl;
4964 has_cctor = gklass->has_cctor;
4966 mono_class_setup_vtable (gklass);
4967 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4970 vtable_size = gklass->vtable_size;
4974 /* ghcimpl is not currently used
4976 if (klass->parent) {
4977 MonoMethod *cmethod = klass->vtable [ghc_slot];
4978 if (cmethod->is_inflated)
4979 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4980 if (cmethod == default_ghc) {
4986 /* C# doesn't allow interfaces to have cctors */
4987 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4988 MonoMethod *cmethod = NULL;
4990 if (mono_class_is_ginst (klass)) {
4991 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4993 /* Generic instance case */
4994 ghcimpl = gklass->ghcimpl;
4995 has_cctor = gklass->has_cctor;
4996 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4997 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4998 /* The find_method function ignores the 'flags' argument */
4999 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5002 mono_class_setup_methods (klass);
5003 if (mono_class_has_failure (klass))
5006 int mcount = mono_class_get_method_count (klass);
5007 for (i = 0; i < mcount; ++i) {
5008 MonoMethod *method = klass->methods [i];
5009 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5010 (strcmp (".cctor", method->name) == 0)) {
5020 array_method_count = 3 + (klass->rank > 1? 2: 1);
5022 if (klass->interface_count) {
5023 int count_generic = generic_array_methods (klass);
5024 array_method_count += klass->interface_count * count_generic;
5028 if (klass->parent) {
5029 if (!klass->parent->vtable_size)
5030 mono_class_setup_vtable (klass->parent);
5031 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5033 g_assert (klass->parent->vtable_size);
5034 first_iface_slot = klass->parent->vtable_size;
5035 if (mono_class_need_stelemref_method (klass))
5040 * Do the actual changes to @klass inside the loader lock
5042 mono_loader_lock ();
5045 if (klass->inited || mono_class_has_failure (klass)) {
5046 mono_loader_unlock ();
5047 /* Somebody might have gotten in before us */
5048 return !mono_class_has_failure (klass);
5051 mono_stats.initialized_class_count++;
5053 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5054 mono_stats.generic_class_count++;
5056 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5057 klass->nested_classes_inited = TRUE;
5058 klass->ghcimpl = ghcimpl;
5059 klass->has_cctor = has_cctor;
5061 klass->vtable_size = vtable_size;
5062 if (has_cached_info) {
5063 klass->has_finalize = cached_info.has_finalize;
5064 klass->has_finalize_inited = TRUE;
5067 mono_class_set_method_count (klass, array_method_count);
5069 mono_loader_unlock ();
5072 setup_interface_offsets (klass, first_iface_slot, TRUE);
5074 if (mono_security_core_clr_enabled ())
5075 mono_security_core_clr_check_inheritance (klass);
5077 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5078 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5083 init_list = g_slist_remove (init_list, klass);
5084 mono_native_tls_set_value (init_pending_tls_id, init_list);
5087 mono_loader_unlock ();
5089 /* Leave this for last */
5090 mono_loader_lock ();
5092 mono_loader_unlock ();
5094 return !mono_class_has_failure (klass);
5098 * mono_class_has_finalizer:
5100 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5104 mono_class_has_finalizer (MonoClass *klass)
5106 gboolean has_finalize = FALSE;
5108 if (klass->has_finalize_inited)
5109 return klass->has_finalize;
5111 /* Interfaces and valuetypes are not supposed to have finalizers */
5112 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5113 MonoMethod *cmethod = NULL;
5115 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5116 } else if (mono_class_is_ginst (klass)) {
5117 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5119 has_finalize = mono_class_has_finalizer (gklass);
5120 } else if (klass->parent && klass->parent->has_finalize) {
5121 has_finalize = TRUE;
5123 if (klass->parent) {
5125 * Can't search in metadata for a method named Finalize, because that
5126 * ignores overrides.
5128 mono_class_setup_vtable (klass);
5129 if (mono_class_has_failure (klass))
5132 cmethod = klass->vtable [finalize_slot];
5136 g_assert (klass->vtable_size > finalize_slot);
5138 if (klass->parent) {
5139 if (cmethod->is_inflated)
5140 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5141 if (cmethod != default_finalize)
5142 has_finalize = TRUE;
5148 mono_loader_lock ();
5149 if (!klass->has_finalize_inited) {
5150 klass->has_finalize = has_finalize ? 1 : 0;
5152 mono_memory_barrier ();
5153 klass->has_finalize_inited = TRUE;
5155 mono_loader_unlock ();
5157 return klass->has_finalize;
5161 mono_is_corlib_image (MonoImage *image)
5163 return image == mono_defaults.corlib;
5167 * LOCKING: this assumes the loader lock is held
5170 mono_class_setup_mono_type (MonoClass *klass)
5172 const char *name = klass->name;
5173 const char *nspace = klass->name_space;
5174 gboolean is_corlib = mono_is_corlib_image (klass->image);
5176 klass->this_arg.byref = 1;
5177 klass->this_arg.data.klass = klass;
5178 klass->this_arg.type = MONO_TYPE_CLASS;
5179 klass->byval_arg.data.klass = klass;
5180 klass->byval_arg.type = MONO_TYPE_CLASS;
5182 if (is_corlib && !strcmp (nspace, "System")) {
5183 if (!strcmp (name, "ValueType")) {
5185 * do not set the valuetype bit for System.ValueType.
5186 * klass->valuetype = 1;
5188 klass->blittable = TRUE;
5189 } else if (!strcmp (name, "Enum")) {
5191 * do not set the valuetype bit for System.Enum.
5192 * klass->valuetype = 1;
5194 klass->valuetype = 0;
5195 klass->enumtype = 0;
5196 } else if (!strcmp (name, "Object")) {
5197 klass->byval_arg.type = MONO_TYPE_OBJECT;
5198 klass->this_arg.type = MONO_TYPE_OBJECT;
5199 } else if (!strcmp (name, "String")) {
5200 klass->byval_arg.type = MONO_TYPE_STRING;
5201 klass->this_arg.type = MONO_TYPE_STRING;
5202 } else if (!strcmp (name, "TypedReference")) {
5203 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5204 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5208 if (klass->valuetype) {
5209 int t = MONO_TYPE_VALUETYPE;
5211 if (is_corlib && !strcmp (nspace, "System")) {
5214 if (!strcmp (name, "Boolean")) {
5215 t = MONO_TYPE_BOOLEAN;
5216 } else if (!strcmp(name, "Byte")) {
5218 klass->blittable = TRUE;
5222 if (!strcmp (name, "Char")) {
5227 if (!strcmp (name, "Double")) {
5229 klass->blittable = TRUE;
5233 if (!strcmp (name, "Int32")) {
5235 klass->blittable = TRUE;
5236 } else if (!strcmp(name, "Int16")) {
5238 klass->blittable = TRUE;
5239 } else if (!strcmp(name, "Int64")) {
5241 klass->blittable = TRUE;
5242 } else if (!strcmp(name, "IntPtr")) {
5244 klass->blittable = TRUE;
5248 if (!strcmp (name, "Single")) {
5250 klass->blittable = TRUE;
5251 } else if (!strcmp(name, "SByte")) {
5253 klass->blittable = TRUE;
5257 if (!strcmp (name, "UInt32")) {
5259 klass->blittable = TRUE;
5260 } else if (!strcmp(name, "UInt16")) {
5262 klass->blittable = TRUE;
5263 } else if (!strcmp(name, "UInt64")) {
5265 klass->blittable = TRUE;
5266 } else if (!strcmp(name, "UIntPtr")) {
5268 klass->blittable = TRUE;
5272 if (!strcmp (name, "TypedReference")) {
5273 t = MONO_TYPE_TYPEDBYREF;
5274 klass->blittable = TRUE;
5278 if (!strcmp (name, "Void")) {
5286 klass->byval_arg.type = (MonoTypeEnum)t;
5287 klass->this_arg.type = (MonoTypeEnum)t;
5290 if (MONO_CLASS_IS_INTERFACE (klass)) {
5291 klass->interface_id = mono_get_unique_iid (klass);
5293 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5294 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5295 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5296 * MS returns diferrent types based on which instance is called. For example:
5297 * object obj = new byte[10][];
5298 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5299 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5302 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5303 klass->is_array_special_interface = 1;
5310 * COM initialization is delayed until needed.
5311 * However when a [ComImport] attribute is present on a type it will trigger
5312 * the initialization. This is not a problem unless the BCL being executed
5313 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5316 init_com_from_comimport (MonoClass *klass)
5318 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5319 if (mono_security_core_clr_enabled ()) {
5320 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5321 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5322 /* but it can not be made available for application (i.e. user code) since all COM calls
5323 * are considered native calls. In this case we fail with a TypeLoadException (just like
5324 * Silverlight 2 does */
5325 mono_class_set_type_load_failure (klass, "");
5330 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5332 #endif /*DISABLE_COM*/
5335 * LOCKING: this assumes the loader lock is held
5338 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5340 gboolean system_namespace;
5341 gboolean is_corlib = mono_is_corlib_image (klass->image);
5343 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5345 /* if root of the hierarchy */
5346 if (system_namespace && !strcmp (klass->name, "Object")) {
5347 klass->parent = NULL;
5348 klass->instance_size = sizeof (MonoObject);
5351 if (!strcmp (klass->name, "<Module>")) {
5352 klass->parent = NULL;
5353 klass->instance_size = 0;
5357 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5358 /* Imported COM Objects always derive from __ComObject. */
5360 if (MONO_CLASS_IS_IMPORT (klass)) {
5361 init_com_from_comimport (klass);
5362 if (parent == mono_defaults.object_class)
5363 parent = mono_class_get_com_object_class ();
5367 /* set the parent to something useful and safe, but mark the type as broken */
5368 parent = mono_defaults.object_class;
5369 mono_class_set_type_load_failure (klass, "");
5373 klass->parent = parent;
5375 if (mono_class_is_ginst (parent) && !parent->name) {
5377 * If the parent is a generic instance, we may get
5378 * called before it is fully initialized, especially
5379 * before it has its name.
5384 #ifndef DISABLE_REMOTING
5385 klass->marshalbyref = parent->marshalbyref;
5386 klass->contextbound = parent->contextbound;
5389 klass->delegate = parent->delegate;
5391 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5392 mono_class_set_is_com_object (klass);
5394 if (system_namespace) {
5395 #ifndef DISABLE_REMOTING
5396 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5397 klass->marshalbyref = 1;
5399 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5400 klass->contextbound = 1;
5402 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5403 klass->delegate = 1;
5406 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5407 (strcmp (klass->parent->name_space, "System") == 0)))
5408 klass->valuetype = 1;
5409 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5410 klass->valuetype = klass->enumtype = 1;
5412 /*klass->enumtype = klass->parent->enumtype; */
5414 /* initialize com types if COM interfaces are present */
5416 if (MONO_CLASS_IS_IMPORT (klass))
5417 init_com_from_comimport (klass);
5419 klass->parent = NULL;
5425 * mono_class_setup_supertypes:
5428 * Build the data structure needed to make fast type checks work.
5429 * This currently sets two fields in @class:
5430 * - idepth: distance between @class and System.Object in the type
5432 * - supertypes: array of classes: each element has a class in the hierarchy
5433 * starting from @class up to System.Object
5435 * LOCKING: Acquires the loader lock.
5438 mono_class_setup_supertypes (MonoClass *klass)
5441 MonoClass **supertypes;
5443 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5447 if (klass->parent && !klass->parent->supertypes)
5448 mono_class_setup_supertypes (klass->parent);
5450 idepth = klass->parent->idepth + 1;
5454 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5455 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5457 if (klass->parent) {
5458 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5461 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5462 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5464 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5467 mono_memory_barrier ();
5469 mono_loader_lock ();
5470 klass->idepth = idepth;
5471 /* Needed so idepth is visible before supertypes is set */
5472 mono_memory_barrier ();
5473 klass->supertypes = supertypes;
5474 mono_loader_unlock ();
5478 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5480 return mono_class_get_generic_class (gclass)->container_class == user_data;
5484 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5486 MonoClass *gtd = (MonoClass*)user_data;
5487 /* Only try to fix generic instances of @gtd */
5488 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5491 /* Check if the generic instance has no parent. */
5492 if (gtd->parent && !gclass->parent)
5493 mono_generic_class_setup_parent (gclass, gtd);
5499 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5501 mono_class_set_type_load_failure (klass, "%s", msg);
5502 mono_error_set_type_load_class (error, klass, "%s", msg);
5506 * mono_class_create_from_typedef:
5507 * \param image: image where the token is valid
5508 * \param type_token: typedef token
5509 * \param error: used to return any error found while creating the type
5511 * Create the MonoClass* representing the specified type token.
5512 * \p type_token must be a TypeDef token.
5514 * FIXME: don't return NULL on failure, just the the caller figure it out.
5517 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5519 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5520 MonoClass *klass, *parent = NULL;
5521 guint32 cols [MONO_TYPEDEF_SIZE];
5522 guint32 cols_next [MONO_TYPEDEF_SIZE];
5523 guint tidx = mono_metadata_token_index (type_token);
5524 MonoGenericContext *context = NULL;
5525 const char *name, *nspace;
5527 MonoClass **interfaces;
5528 guint32 field_last, method_last;
5529 guint32 nesting_tokeen;
5533 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5534 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5538 mono_loader_lock ();
5540 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5541 mono_loader_unlock ();
5545 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5547 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5548 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5550 if (mono_metadata_has_generic_params (image, type_token)) {
5551 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5552 klass->class_kind = MONO_CLASS_GTD;
5553 classes_size += sizeof (MonoClassGtd);
5556 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5557 klass->class_kind = MONO_CLASS_DEF;
5558 classes_size += sizeof (MonoClassDef);
5563 klass->name_space = nspace;
5565 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5567 klass->image = image;
5568 klass->type_token = type_token;
5569 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5571 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5574 * Check whether we're a generic type definition.
5576 if (mono_class_is_gtd (klass)) {
5577 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5578 generic_container->owner.klass = klass;
5579 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5580 context = &generic_container->context;
5581 mono_class_set_generic_container (klass, generic_container);
5582 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5583 canonical_inst->type = MONO_TYPE_GENERICINST;
5584 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5585 enable_gclass_recording ();
5588 if (cols [MONO_TYPEDEF_EXTENDS]) {
5590 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5592 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5593 /*WARNING: this must satisfy mono_metadata_type_hash*/
5594 klass->this_arg.byref = 1;
5595 klass->this_arg.data.klass = klass;
5596 klass->this_arg.type = MONO_TYPE_CLASS;
5597 klass->byval_arg.data.klass = klass;
5598 klass->byval_arg.type = MONO_TYPE_CLASS;
5600 parent = mono_class_get_checked (image, parent_token, error);
5601 if (parent && context) /* Always inflate */
5602 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5604 if (parent == NULL) {
5605 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5606 goto parent_failure;
5609 for (tmp = parent; tmp; tmp = tmp->parent) {
5611 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5612 goto parent_failure;
5614 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5615 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5616 goto parent_failure;
5621 mono_class_setup_parent (klass, parent);
5623 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5624 mono_class_setup_mono_type (klass);
5626 if (mono_class_is_gtd (klass))
5627 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5630 * This might access klass->byval_arg for recursion generated by generic constraints,
5631 * so it has to come after setup_mono_type ().
5633 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5634 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5635 if (!mono_error_ok (error)) {
5636 /*FIXME implement a mono_class_set_failure_from_mono_error */
5637 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5638 mono_loader_unlock ();
5639 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5644 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5648 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5652 klass->cast_class = klass->element_class = klass;
5653 if (mono_is_corlib_image (klass->image)) {
5654 switch (klass->byval_arg.type) {
5656 if (mono_defaults.byte_class)
5657 klass->cast_class = mono_defaults.byte_class;
5660 if (mono_defaults.sbyte_class)
5661 mono_defaults.sbyte_class = klass;
5664 if (mono_defaults.uint16_class)
5665 mono_defaults.uint16_class = klass;
5668 if (mono_defaults.int16_class)
5669 klass->cast_class = mono_defaults.int16_class;
5672 if (mono_defaults.uint32_class)
5673 mono_defaults.uint32_class = klass;
5676 if (mono_defaults.int32_class)
5677 klass->cast_class = mono_defaults.int32_class;
5680 if (mono_defaults.uint64_class)
5681 mono_defaults.uint64_class = klass;
5684 if (mono_defaults.int64_class)
5685 klass->cast_class = mono_defaults.int64_class;
5690 if (!klass->enumtype) {
5691 if (!mono_metadata_interfaces_from_typedef_full (
5692 image, type_token, &interfaces, &icount, FALSE, context, error)){
5694 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5695 mono_loader_unlock ();
5696 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5700 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5701 g_assert(icount <= 65535);
5703 klass->interfaces = interfaces;
5704 klass->interface_count = icount;
5705 klass->interfaces_inited = 1;
5708 /*g_print ("Load class %s\n", name);*/
5711 * Compute the field and method lists
5713 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5714 mono_class_set_first_field_idx (klass, first_field_idx);
5715 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5716 mono_class_set_first_method_idx (klass, first_method_idx);
5718 if (tt->rows > tidx){
5719 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5720 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5721 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5723 field_last = image->tables [MONO_TABLE_FIELD].rows;
5724 method_last = image->tables [MONO_TABLE_METHOD].rows;
5727 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5728 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5729 mono_class_set_field_count (klass, field_last - first_field_idx);
5730 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5731 mono_class_set_method_count (klass, method_last - first_method_idx);
5733 /* reserve space to store vector pointer in arrays */
5734 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5735 klass->instance_size += 2 * sizeof (gpointer);
5736 g_assert (mono_class_get_field_count (klass) == 0);
5739 if (klass->enumtype) {
5740 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5741 if (!enum_basetype) {
5742 /*set it to a default value as the whole runtime can't handle this to be null*/
5743 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5744 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5745 mono_loader_unlock ();
5746 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5749 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5753 * If we're a generic type definition, load the constraints.
5754 * We must do this after the class has been constructed to make certain recursive scenarios
5757 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5758 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5759 mono_loader_unlock ();
5760 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5764 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5765 if (!strncmp (name, "Vector", 6))
5766 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");
5767 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5768 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5769 klass->simd_type = 1;
5772 mono_loader_unlock ();
5774 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5779 if (mono_class_is_gtd (klass))
5780 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5782 mono_class_setup_mono_type (klass);
5783 mono_loader_unlock ();
5784 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5788 /** Is klass a Nullable<T> ginst? */
5790 mono_class_is_nullable (MonoClass *klass)
5792 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5793 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5797 /** if klass is T? return T */
5799 mono_class_get_nullable_param (MonoClass *klass)
5801 g_assert (mono_class_is_nullable (klass));
5802 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5806 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5810 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5812 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5813 if (!mono_error_ok (&error)) {
5814 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5815 klass->parent = mono_defaults.object_class;
5816 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5817 mono_error_cleanup (&error);
5820 mono_loader_lock ();
5822 mono_class_setup_parent (klass, klass->parent);
5824 if (klass->enumtype) {
5825 klass->cast_class = gtd->cast_class;
5826 klass->element_class = gtd->element_class;
5828 mono_loader_unlock ();
5832 mono_type_is_primitive (MonoType *type)
5834 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5835 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5839 * Create the `MonoClass' for an instantiation of a generic type.
5840 * We only do this if we actually need it.
5843 mono_generic_class_get_class (MonoGenericClass *gclass)
5845 MonoClass *klass, *gklass;
5847 if (gclass->cached_class)
5848 return gclass->cached_class;
5850 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5852 gklass = gclass->container_class;
5854 if (gklass->nested_in) {
5855 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5856 klass->nested_in = gklass->nested_in;
5859 klass->name = gklass->name;
5860 klass->name_space = gklass->name_space;
5862 klass->image = gklass->image;
5863 klass->type_token = gklass->type_token;
5865 klass->class_kind = MONO_CLASS_GINST;
5867 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5869 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5870 klass->this_arg.type = klass->byval_arg.type;
5871 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5872 klass->this_arg.byref = TRUE;
5873 klass->enumtype = gklass->enumtype;
5874 klass->valuetype = gklass->valuetype;
5877 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5878 g_assert (gclass->context.class_inst);
5879 g_assert (gclass->context.class_inst->type_argc > 0);
5880 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5881 klass->simd_type = 1;
5883 klass->is_array_special_interface = gklass->is_array_special_interface;
5885 klass->cast_class = klass->element_class = klass;
5887 if (gclass->is_dynamic) {
5889 * 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.
5890 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5891 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5893 if (!gklass->wastypebuilder)
5896 if (klass->enumtype) {
5898 * For enums, gklass->fields might not been set, but instance_size etc. is
5899 * already set in mono_reflection_create_internal_class (). For non-enums,
5900 * these will be computed normally in mono_class_layout_fields ().
5902 klass->instance_size = gklass->instance_size;
5903 klass->sizes.class_size = gklass->sizes.class_size;
5904 klass->size_inited = 1;
5908 mono_loader_lock ();
5910 if (gclass->cached_class) {
5911 mono_loader_unlock ();
5912 return gclass->cached_class;
5915 if (record_gclass_instantiation > 0)
5916 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5918 if (mono_class_is_nullable (klass))
5919 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5921 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5923 mono_generic_class_setup_parent (klass, gklass);
5925 if (gclass->is_dynamic)
5926 mono_class_setup_supertypes (klass);
5928 mono_memory_barrier ();
5929 gclass->cached_class = klass;
5931 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5933 ++class_ginst_count;
5934 inflated_classes_size += sizeof (MonoClassGenericInst);
5936 mono_loader_unlock ();
5942 get_image_for_container (MonoGenericContainer *container)
5945 if (container->is_anonymous) {
5946 result = container->owner.image;
5949 if (container->is_method) {
5950 MonoMethod *method = container->owner.method;
5951 g_assert_checked (method);
5952 klass = method->klass;
5954 klass = container->owner.klass;
5956 g_assert_checked (klass);
5957 result = klass->image;
5964 get_image_for_generic_param (MonoGenericParam *param)
5966 MonoGenericContainer *container = mono_generic_param_owner (param);
5967 g_assert_checked (container);
5968 return get_image_for_container (container);
5971 // Make a string in the designated image consisting of a single integer.
5972 #define INT_STRING_SIZE 16
5974 make_generic_name_string (MonoImage *image, int num)
5976 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5977 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5981 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5982 // pinfo is derived from param by the caller for us.
5984 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5986 MonoClass *klass, **ptr;
5988 MonoGenericContainer *container = mono_generic_param_owner (param);
5989 g_assert_checked (container);
5991 MonoImage *image = get_image_for_container (container);
5992 gboolean is_mvar = container->is_method;
5993 gboolean is_anonymous = container->is_anonymous;
5995 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5996 klass->class_kind = MONO_CLASS_GPARAM;
5997 classes_size += sizeof (MonoClassGenericParam);
5998 ++class_gparam_count;
6001 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6003 int n = mono_generic_param_num (param);
6004 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6008 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6009 } else if (is_mvar) {
6010 MonoMethod *omethod = container->owner.method;
6011 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6013 MonoClass *oklass = container->owner.klass;
6014 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6017 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6019 // Count non-NULL items in pinfo->constraints
6022 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6026 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6027 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6029 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6030 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6032 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6035 if (count - pos > 0) {
6036 klass->interface_count = count - pos;
6037 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6038 klass->interfaces_inited = TRUE;
6039 for (i = pos; i < count; i++)
6040 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6043 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6045 klass->inited = TRUE;
6046 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6047 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6049 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6050 klass->this_arg.type = klass->byval_arg.type;
6051 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6052 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6053 klass->this_arg.byref = TRUE;
6055 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6056 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6058 /*Init these fields to sane values*/
6059 klass->min_align = 1;
6061 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6062 * constrained to, the JIT depends on this.
6064 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6065 mono_memory_barrier ();
6066 klass->size_inited = 1;
6068 mono_class_setup_supertypes (klass);
6070 if (count - pos > 0) {
6071 mono_class_setup_vtable (klass->parent);
6072 if (mono_class_has_failure (klass->parent))
6073 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6075 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6081 #define FAST_CACHE_SIZE 16
6084 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6085 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6086 * we cache the MonoClasses.
6087 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6088 * LOCKING: Takes the image lock depending on @take_lock.
6091 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6093 int n = mono_generic_param_num (param);
6094 MonoImage *image = get_image_for_generic_param (param);
6095 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6096 MonoClass *klass = NULL;
6101 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6102 // For high numbers or constraints we have to use pointer hashes.
6103 if (param->gshared_constraint) {
6104 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6107 mono_image_lock (image);
6108 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6110 mono_image_unlock (image);
6115 if (n < FAST_CACHE_SIZE) {
6117 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6119 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6121 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6124 mono_image_lock (image);
6125 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6127 mono_image_unlock (image);
6134 * LOCKING: Image lock (param->image) must be held
6137 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6139 int n = mono_generic_param_num (param);
6140 MonoImage *image = get_image_for_generic_param (param);
6141 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6145 if (param->gshared_constraint) {
6146 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6148 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6149 mono_memory_barrier ();
6151 image->mvar_cache_constrained = ht;
6153 image->var_cache_constrained = ht;
6155 g_hash_table_insert (ht, param, klass);
6156 } else if (n < FAST_CACHE_SIZE) {
6158 /* Requires locking to avoid droping an already published class */
6159 if (!image->mvar_cache_fast)
6160 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6161 image->mvar_cache_fast [n] = klass;
6163 if (!image->var_cache_fast)
6164 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6165 image->var_cache_fast [n] = klass;
6168 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6170 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6172 ht = g_hash_table_new (NULL, NULL);
6173 mono_memory_barrier ();
6175 image->mvar_cache_slow = ht;
6177 image->var_cache_slow = ht;
6180 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6185 * LOCKING: Acquires the image lock (@image).
6188 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6190 MonoImage *image = get_image_for_generic_param (param);
6191 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6192 MonoClass *klass, *klass2;
6194 // If a klass already exists for this object and is cached, return it.
6195 if (pinfo) // Non-anonymous
6196 klass = pinfo->pklass;
6198 klass = get_anon_gparam_class (param, TRUE);
6203 // Create a new klass
6204 klass = make_generic_param_class (param, pinfo);
6206 // Now we need to cache the klass we created.
6207 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6208 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6209 // and allow our newly-created klass object to just leak.
6210 mono_memory_barrier ();
6212 mono_image_lock (image);
6214 // Here "klass2" refers to the klass potentially created by the other thread.
6215 if (pinfo) // Repeat check from above
6216 klass2 = pinfo->pklass;
6218 klass2 = get_anon_gparam_class (param, FALSE);
6225 pinfo->pklass = klass;
6227 set_anon_gparam_class (param, klass);
6229 mono_image_unlock (image);
6231 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6233 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6235 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6241 * mono_class_from_generic_parameter:
6242 * \param param Parameter to find/construct a class for.
6243 * \param arg2 Is ignored.
6244 * \param arg3 Is ignored.
6247 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6249 return mono_class_from_generic_parameter_internal (param);
6253 * mono_ptr_class_get:
6256 mono_ptr_class_get (MonoType *type)
6259 MonoClass *el_class;
6263 el_class = mono_class_from_mono_type (type);
6264 image = el_class->image;
6266 mono_image_lock (image);
6267 if (image->ptr_cache) {
6268 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6269 mono_image_unlock (image);
6273 mono_image_unlock (image);
6275 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6277 classes_size += sizeof (MonoClassPointer);
6278 ++class_pointer_count;
6280 result->parent = NULL; /* no parent for PTR types */
6281 result->name_space = el_class->name_space;
6282 name = g_strdup_printf ("%s*", el_class->name);
6283 result->name = mono_image_strdup (image, name);
6284 result->class_kind = MONO_CLASS_POINTER;
6287 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6289 result->image = el_class->image;
6290 result->inited = TRUE;
6291 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6292 result->cast_class = result->element_class = el_class;
6293 result->blittable = TRUE;
6295 result->byval_arg.type = MONO_TYPE_PTR;
6296 result->this_arg.type = result->byval_arg.type;
6297 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6298 result->this_arg.byref = TRUE;
6300 mono_class_setup_supertypes (result);
6302 mono_image_lock (image);
6303 if (image->ptr_cache) {
6305 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6306 mono_image_unlock (image);
6307 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6311 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6313 g_hash_table_insert (image->ptr_cache, el_class, result);
6314 mono_image_unlock (image);
6316 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6322 mono_fnptr_class_get (MonoMethodSignature *sig)
6324 MonoClass *result, *cached;
6325 static GHashTable *ptr_hash = NULL;
6327 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6329 mono_loader_lock ();
6331 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6332 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6333 mono_loader_unlock ();
6337 result = g_new0 (MonoClass, 1);
6339 result->parent = NULL; /* no parent for PTR types */
6340 result->name_space = "System";
6341 result->name = "MonoFNPtrFakeClass";
6342 result->class_kind = MONO_CLASS_POINTER;
6344 result->image = mono_defaults.corlib; /* need to fix... */
6345 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6346 result->cast_class = result->element_class = result;
6347 result->byval_arg.type = MONO_TYPE_FNPTR;
6348 result->this_arg.type = result->byval_arg.type;
6349 result->this_arg.data.method = result->byval_arg.data.method = sig;
6350 result->this_arg.byref = TRUE;
6351 result->blittable = TRUE;
6352 result->inited = TRUE;
6354 mono_class_setup_supertypes (result);
6356 mono_loader_lock ();
6358 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6361 mono_loader_unlock ();
6365 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6367 classes_size += sizeof (MonoClassPointer);
6368 ++class_pointer_count;
6370 g_hash_table_insert (ptr_hash, sig, result);
6372 mono_loader_unlock ();
6374 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6380 * mono_class_from_mono_type:
6381 * \param type describes the type to return
6382 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6385 mono_class_from_mono_type (MonoType *type)
6387 switch (type->type) {
6388 case MONO_TYPE_OBJECT:
6389 return type->data.klass? type->data.klass: mono_defaults.object_class;
6390 case MONO_TYPE_VOID:
6391 return type->data.klass? type->data.klass: mono_defaults.void_class;
6392 case MONO_TYPE_BOOLEAN:
6393 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6394 case MONO_TYPE_CHAR:
6395 return type->data.klass? type->data.klass: mono_defaults.char_class;
6397 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6399 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6401 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6403 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6405 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6407 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6409 return type->data.klass? type->data.klass: mono_defaults.int_class;
6411 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6413 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6415 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6417 return type->data.klass? type->data.klass: mono_defaults.single_class;
6419 return type->data.klass? type->data.klass: mono_defaults.double_class;
6420 case MONO_TYPE_STRING:
6421 return type->data.klass? type->data.klass: mono_defaults.string_class;
6422 case MONO_TYPE_TYPEDBYREF:
6423 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6424 case MONO_TYPE_ARRAY:
6425 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6427 return mono_ptr_class_get (type->data.type);
6428 case MONO_TYPE_FNPTR:
6429 return mono_fnptr_class_get (type->data.method);
6430 case MONO_TYPE_SZARRAY:
6431 return mono_array_class_get (type->data.klass, 1);
6432 case MONO_TYPE_CLASS:
6433 case MONO_TYPE_VALUETYPE:
6434 return type->data.klass;
6435 case MONO_TYPE_GENERICINST:
6436 return mono_generic_class_get_class (type->data.generic_class);
6437 case MONO_TYPE_MVAR:
6439 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6441 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6442 g_assert_not_reached ();
6445 // Yes, this returns NULL, even if it is documented as not doing so, but there
6446 // is no way for the code to make it this far, due to the assert above.
6451 * mono_type_retrieve_from_typespec
6452 * \param image context where the image is created
6453 * \param type_spec typespec token
6454 * \param context the generic context used to evaluate generic instantiations in
6457 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6459 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6461 *did_inflate = FALSE;
6466 if (context && (context->class_inst || context->method_inst)) {
6467 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6469 if (!mono_error_ok (error)) {
6475 *did_inflate = TRUE;
6482 * mono_class_create_from_typespec
6483 * \param image context where the image is created
6484 * \param type_spec typespec token
6485 * \param context the generic context used to evaluate generic instantiations in
6488 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6491 gboolean inflated = FALSE;
6492 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6493 return_val_if_nok (error, NULL);
6494 ret = mono_class_from_mono_type (t);
6496 mono_metadata_free_type (t);
6501 * mono_bounded_array_class_get:
6502 * \param element_class element class
6503 * \param rank the dimension of the array class
6504 * \param bounded whenever the array has non-zero bounds
6505 * \returns A class object describing the array with element type \p element_type and
6506 * dimension \p rank.
6509 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6512 MonoClass *klass, *cached, *k;
6513 MonoClass *parent = NULL;
6514 GSList *list, *rootlist = NULL;
6518 g_assert (rank <= 255);
6521 /* bounded only matters for one-dimensional arrays */
6524 image = eclass->image;
6528 if (rank == 1 && !bounded) {
6530 * This case is very frequent not just during compilation because of calls
6531 * from mono_class_from_mono_type (), mono_array_new (),
6532 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6534 mono_os_mutex_lock (&image->szarray_cache_lock);
6535 if (!image->szarray_cache)
6536 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6537 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6538 mono_os_mutex_unlock (&image->szarray_cache_lock);
6540 mono_loader_lock ();
6541 if (!image->array_cache)
6542 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6543 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6544 for (list = rootlist; list; list = list->next) {
6545 k = (MonoClass *)list->data;
6546 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6551 mono_loader_unlock ();
6556 parent = mono_defaults.array_class;
6557 if (!parent->inited)
6558 mono_class_init (parent);
6560 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6562 klass->image = image;
6563 klass->name_space = eclass->name_space;
6564 klass->class_kind = MONO_CLASS_ARRAY;
6566 nsize = strlen (eclass->name);
6567 name = (char *)g_malloc (nsize + 2 + rank + 1);
6568 memcpy (name, eclass->name, nsize);
6571 memset (name + nsize + 1, ',', rank - 1);
6573 name [nsize + rank] = '*';
6574 name [nsize + rank + bounded] = ']';
6575 name [nsize + rank + bounded + 1] = 0;
6576 klass->name = mono_image_strdup (image, name);
6579 klass->type_token = 0;
6580 klass->parent = parent;
6581 klass->instance_size = mono_class_instance_size (klass->parent);
6583 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6584 /*Arrays of those two types are invalid.*/
6585 MonoError prepared_error;
6586 error_init (&prepared_error);
6587 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6588 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6589 mono_error_cleanup (&prepared_error);
6590 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6591 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6592 if (!ref_info_handle || eclass->wastypebuilder) {
6593 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6594 g_assert (ref_info_handle && !eclass->wastypebuilder);
6596 /* element_size -1 is ok as this is not an instantitable type*/
6597 klass->sizes.element_size = -1;
6599 klass->sizes.element_size = mono_class_array_element_size (eclass);
6601 mono_class_setup_supertypes (klass);
6603 if (mono_class_is_ginst (eclass))
6604 mono_class_init (eclass);
6605 if (!eclass->size_inited)
6606 mono_class_setup_fields (eclass);
6607 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6608 /*FIXME we fail the array type, but we have to let other fields be set.*/
6610 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6614 if (eclass->enumtype)
6615 klass->cast_class = eclass->element_class;
6617 klass->cast_class = eclass;
6619 switch (klass->cast_class->byval_arg.type) {
6621 klass->cast_class = mono_defaults.byte_class;
6624 klass->cast_class = mono_defaults.int16_class;
6627 #if SIZEOF_VOID_P == 4
6631 klass->cast_class = mono_defaults.int32_class;
6634 #if SIZEOF_VOID_P == 8
6638 klass->cast_class = mono_defaults.int64_class;
6644 klass->element_class = eclass;
6646 if ((rank > 1) || bounded) {
6647 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6648 klass->byval_arg.type = MONO_TYPE_ARRAY;
6649 klass->byval_arg.data.array = at;
6650 at->eklass = eclass;
6652 /* FIXME: complete.... */
6654 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6655 klass->byval_arg.data.klass = eclass;
6657 klass->this_arg = klass->byval_arg;
6658 klass->this_arg.byref = 1;
6661 MonoError prepared_error;
6662 error_init (&prepared_error);
6663 name = mono_type_get_full_name (klass);
6664 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6665 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6666 mono_error_cleanup (&prepared_error);
6670 mono_loader_lock ();
6672 /* Check cache again */
6674 if (rank == 1 && !bounded) {
6675 mono_os_mutex_lock (&image->szarray_cache_lock);
6676 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6677 mono_os_mutex_unlock (&image->szarray_cache_lock);
6679 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6680 for (list = rootlist; list; list = list->next) {
6681 k = (MonoClass *)list->data;
6682 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6689 mono_loader_unlock ();
6693 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6695 classes_size += sizeof (MonoClassArray);
6696 ++class_array_count;
6698 if (rank == 1 && !bounded) {
6699 mono_os_mutex_lock (&image->szarray_cache_lock);
6700 g_hash_table_insert (image->szarray_cache, eclass, klass);
6701 mono_os_mutex_unlock (&image->szarray_cache_lock);
6703 list = g_slist_append (rootlist, klass);
6704 g_hash_table_insert (image->array_cache, eclass, list);
6707 mono_loader_unlock ();
6709 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6715 * mono_array_class_get:
6716 * \param element_class element class
6717 * \param rank the dimension of the array class
6718 * \returns A class object describing the array with element type \p element_type and
6719 * dimension \p rank.
6722 mono_array_class_get (MonoClass *eclass, guint32 rank)
6724 return mono_bounded_array_class_get (eclass, rank, FALSE);
6728 * mono_class_instance_size:
6729 * \param klass a class
6731 * Use to get the size of a class in bytes.
6733 * \returns The size of an object instance
6736 mono_class_instance_size (MonoClass *klass)
6738 if (!klass->size_inited)
6739 mono_class_init (klass);
6741 return klass->instance_size;
6745 * mono_class_min_align:
6746 * \param klass a class
6748 * Use to get the computed minimum alignment requirements for the specified class.
6750 * Returns: minimum alignment requirements
6753 mono_class_min_align (MonoClass *klass)
6755 if (!klass->size_inited)
6756 mono_class_init (klass);
6758 return klass->min_align;
6762 * mono_class_value_size:
6763 * \param klass a class
6765 * This function is used for value types, and return the
6766 * space and the alignment to store that kind of value object.
6768 * \returns the size of a value of kind \p klass
6771 mono_class_value_size (MonoClass *klass, guint32 *align)
6775 /* fixme: check disable, because we still have external revereces to
6776 * mscorlib and Dummy Objects
6778 /*g_assert (klass->valuetype);*/
6780 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6783 *align = klass->min_align;
6789 * mono_class_data_size:
6790 * \param klass a class
6792 * \returns The size of the static class data
6795 mono_class_data_size (MonoClass *klass)
6798 mono_class_init (klass);
6799 /* This can happen with dynamically created types */
6800 if (!klass->fields_inited)
6801 mono_class_setup_fields (klass);
6803 /* in arrays, sizes.class_size is unioned with element_size
6804 * and arrays have no static fields
6808 return klass->sizes.class_size;
6812 * Auxiliary routine to mono_class_get_field
6814 * Takes a field index instead of a field token.
6816 static MonoClassField *
6817 mono_class_get_field_idx (MonoClass *klass, int idx)
6819 mono_class_setup_fields (klass);
6820 if (mono_class_has_failure (klass))
6824 int first_field_idx = mono_class_get_first_field_idx (klass);
6825 int fcount = mono_class_get_field_count (klass);
6826 if (klass->image->uncompressed_metadata) {
6828 * first_field_idx points to the FieldPtr table, while idx points into the
6829 * Field table, so we have to do a search.
6831 /*FIXME this is broken for types with multiple fields with the same name.*/
6832 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6835 for (i = 0; i < fcount; ++i)
6836 if (mono_field_get_name (&klass->fields [i]) == name)
6837 return &klass->fields [i];
6838 g_assert_not_reached ();
6841 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6842 return &klass->fields [idx - first_field_idx];
6846 klass = klass->parent;
6852 * mono_class_get_field:
6853 * \param class the class to lookup the field.
6854 * \param field_token the field token
6856 * \returns A \c MonoClassField representing the type and offset of
6857 * the field, or a NULL value if the field does not belong to this
6861 mono_class_get_field (MonoClass *klass, guint32 field_token)
6863 int idx = mono_metadata_token_index (field_token);
6865 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6867 return mono_class_get_field_idx (klass, idx - 1);
6871 * mono_class_get_field_from_name:
6872 * \param klass the class to lookup the field.
6873 * \param name the field name
6875 * Search the class \p klass and its parents for a field with the name \p name.
6877 * \returns The \c MonoClassField pointer of the named field or NULL
6880 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6882 return mono_class_get_field_from_name_full (klass, name, NULL);
6886 * mono_class_get_field_from_name_full:
6887 * \param klass the class to lookup the field.
6888 * \param name the field name
6889 * \param type the type of the fields. This optional.
6891 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6893 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6894 * of its generic type definition.
6896 * \returns The MonoClassField pointer of the named field or NULL
6899 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6903 mono_class_setup_fields (klass);
6904 if (mono_class_has_failure (klass))
6908 int fcount = mono_class_get_field_count (klass);
6909 for (i = 0; i < fcount; ++i) {
6910 MonoClassField *field = &klass->fields [i];
6912 if (strcmp (name, mono_field_get_name (field)) != 0)
6916 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6917 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6922 klass = klass->parent;
6928 * mono_class_get_field_token:
6929 * \param field the field we need the token of
6931 * Get the token of a field. Note that the tokesn is only valid for the image
6932 * the field was loaded from. Don't use this function for fields in dynamic types.
6934 * \returns The token representing the field in the image it was loaded from.
6937 mono_class_get_field_token (MonoClassField *field)
6939 MonoClass *klass = field->parent;
6942 mono_class_setup_fields (klass);
6947 int first_field_idx = mono_class_get_first_field_idx (klass);
6948 int fcount = mono_class_get_field_count (klass);
6949 for (i = 0; i < fcount; ++i) {
6950 if (&klass->fields [i] == field) {
6951 int idx = first_field_idx + i + 1;
6953 if (klass->image->uncompressed_metadata)
6954 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6955 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6958 klass = klass->parent;
6961 g_assert_not_reached ();
6966 mono_field_get_index (MonoClassField *field)
6968 int index = field - field->parent->fields;
6969 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6975 * mono_class_get_field_default_value:
6977 * Return the default value of the field as a pointer into the metadata blob.
6980 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6983 guint32 constant_cols [MONO_CONSTANT_SIZE];
6985 MonoClass *klass = field->parent;
6986 MonoFieldDefaultValue *def_values;
6988 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6990 def_values = mono_class_get_field_def_values (klass);
6992 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6994 mono_class_set_field_def_values (klass, def_values);
6997 field_index = mono_field_get_index (field);
6999 if (!def_values [field_index].data) {
7000 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7004 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7006 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7007 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7008 mono_memory_barrier ();
7009 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7012 *def_type = def_values [field_index].def_type;
7013 return def_values [field_index].data;
7017 mono_property_get_index (MonoProperty *prop)
7019 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7020 int index = prop - info->properties;
7022 g_assert (index >= 0 && index < info->count);
7028 * mono_class_get_property_default_value:
7030 * Return the default value of the field as a pointer into the metadata blob.
7033 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7036 guint32 constant_cols [MONO_CONSTANT_SIZE];
7037 MonoClass *klass = property->parent;
7039 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7041 * We don't cache here because it is not used by C# so it's quite rare, but
7042 * we still do the lookup in klass->ext because that is where the data
7043 * is stored for dynamic assemblies.
7046 if (image_is_dynamic (klass->image)) {
7047 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7048 int prop_index = mono_property_get_index (property);
7049 if (info->def_values && info->def_values [prop_index].data) {
7050 *def_type = info->def_values [prop_index].def_type;
7051 return info->def_values [prop_index].data;
7055 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7059 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7060 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7061 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7065 * mono_class_get_event_token:
7068 mono_class_get_event_token (MonoEvent *event)
7070 MonoClass *klass = event->parent;
7074 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7076 for (i = 0; i < info->count; ++i) {
7077 if (&info->events [i] == event)
7078 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7081 klass = klass->parent;
7084 g_assert_not_reached ();
7089 * mono_class_get_property_from_name:
7090 * \param klass a class
7091 * \param name name of the property to lookup in the specified class
7093 * Use this method to lookup a property in a class
7094 * \returns the \c MonoProperty with the given name, or NULL if the property
7095 * does not exist on the \p klass.
7098 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7102 gpointer iter = NULL;
7103 while ((p = mono_class_get_properties (klass, &iter))) {
7104 if (! strcmp (name, p->name))
7107 klass = klass->parent;
7113 * mono_class_get_property_token:
7114 * \param prop MonoProperty to query
7116 * \returns The ECMA token for the specified property.
7119 mono_class_get_property_token (MonoProperty *prop)
7121 MonoClass *klass = prop->parent;
7125 gpointer iter = NULL;
7126 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7127 while ((p = mono_class_get_properties (klass, &iter))) {
7128 if (&info->properties [i] == prop)
7129 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7133 klass = klass->parent;
7136 g_assert_not_reached ();
7141 * mono_class_name_from_token:
7144 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7146 const char *name, *nspace;
7147 if (image_is_dynamic (image))
7148 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7150 switch (type_token & 0xff000000){
7151 case MONO_TOKEN_TYPE_DEF: {
7152 guint32 cols [MONO_TYPEDEF_SIZE];
7153 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7154 guint tidx = mono_metadata_token_index (type_token);
7156 if (tidx > tt->rows)
7157 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7159 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7160 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7161 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7162 if (strlen (nspace) == 0)
7163 return g_strdup_printf ("%s", name);
7165 return g_strdup_printf ("%s.%s", nspace, name);
7168 case MONO_TOKEN_TYPE_REF: {
7170 guint32 cols [MONO_TYPEREF_SIZE];
7171 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7172 guint tidx = mono_metadata_token_index (type_token);
7175 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7177 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7178 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7179 mono_error_cleanup (&error);
7183 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7184 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7185 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7186 if (strlen (nspace) == 0)
7187 return g_strdup_printf ("%s", name);
7189 return g_strdup_printf ("%s.%s", nspace, name);
7192 case MONO_TOKEN_TYPE_SPEC:
7193 return g_strdup_printf ("Typespec 0x%08x", type_token);
7195 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7200 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7202 if (image_is_dynamic (image))
7203 return g_strdup_printf ("DynamicAssembly %s", image->name);
7205 switch (type_token & 0xff000000){
7206 case MONO_TOKEN_TYPE_DEF:
7207 if (image->assembly)
7208 return mono_stringify_assembly_name (&image->assembly->aname);
7209 else if (image->assembly_name)
7210 return g_strdup (image->assembly_name);
7211 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7212 case MONO_TOKEN_TYPE_REF: {
7214 MonoAssemblyName aname;
7215 guint32 cols [MONO_TYPEREF_SIZE];
7216 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7217 guint32 idx = mono_metadata_token_index (type_token);
7220 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7222 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7223 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7224 mono_error_cleanup (&error);
7227 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7229 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7230 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7231 case MONO_RESOLUTION_SCOPE_MODULE:
7233 return g_strdup ("");
7234 case MONO_RESOLUTION_SCOPE_MODULEREF:
7236 return g_strdup ("");
7237 case MONO_RESOLUTION_SCOPE_TYPEREF:
7239 return g_strdup ("");
7240 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7241 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7242 return mono_stringify_assembly_name (&aname);
7244 g_assert_not_reached ();
7248 case MONO_TOKEN_TYPE_SPEC:
7250 return g_strdup ("");
7252 g_assert_not_reached ();
7259 * mono_class_get_full:
7260 * \param image the image where the class resides
7261 * \param type_token the token for the class
7262 * \param context the generic context used to evaluate generic instantiations in
7263 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7264 * \returns The \c MonoClass that represents \p type_token in \p image
7267 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7271 klass = mono_class_get_checked (image, type_token, &error);
7273 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7274 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7276 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7282 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7287 klass = mono_class_get_checked (image, type_token, error);
7289 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7290 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7295 * mono_class_get_checked:
7296 * \param image the image where the class resides
7297 * \param type_token the token for the class
7298 * \param error error object to return any error
7300 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7303 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7305 MonoClass *klass = NULL;
7309 if (image_is_dynamic (image)) {
7310 int table = mono_metadata_token_table (type_token);
7312 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7313 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7316 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7320 switch (type_token & 0xff000000){
7321 case MONO_TOKEN_TYPE_DEF:
7322 klass = mono_class_create_from_typedef (image, type_token, error);
7324 case MONO_TOKEN_TYPE_REF:
7325 klass = mono_class_from_typeref_checked (image, type_token, error);
7327 case MONO_TOKEN_TYPE_SPEC:
7328 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7331 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7335 /* Generic case, should be avoided for when a better error is possible. */
7336 if (!klass && mono_error_ok (error)) {
7337 char *name = mono_class_name_from_token (image, type_token);
7338 char *assembly = mono_assembly_name_from_token (image, type_token);
7339 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7347 * mono_type_get_checked:
7348 * \param image the image where the type resides
7349 * \param type_token the token for the type
7350 * \param context the generic context used to evaluate generic instantiations in
7351 * \param error Error handling context
7353 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7355 * \returns The MonoType that represents \p type_token in \p image
7358 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7360 MonoType *type = NULL;
7361 gboolean inflated = FALSE;
7365 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7366 if (image_is_dynamic (image)) {
7367 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7368 return_val_if_nok (error, NULL);
7369 return mono_class_get_type (klass);
7372 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7373 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7380 return mono_class_get_type (klass);
7383 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7390 MonoType *tmp = type;
7391 type = mono_class_get_type (mono_class_from_mono_type (type));
7392 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7393 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7394 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7396 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7398 if (type->type != tmp->type)
7401 mono_metadata_free_type (tmp);
7408 * \param image image where the class token will be looked up.
7409 * \param type_token a type token from the image
7410 * \returns the \c MonoClass with the given \p type_token on the \p image
7413 mono_class_get (MonoImage *image, guint32 type_token)
7415 return mono_class_get_full (image, type_token, NULL);
7419 * mono_image_init_name_cache:
7421 * Initializes the class name cache stored in image->name_cache.
7423 * LOCKING: Acquires the corresponding image lock.
7426 mono_image_init_name_cache (MonoImage *image)
7428 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7429 guint32 cols [MONO_TYPEDEF_SIZE];
7432 guint32 i, visib, nspace_index;
7433 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7435 if (image->name_cache)
7438 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7440 if (image_is_dynamic (image)) {
7441 mono_image_lock (image);
7442 if (image->name_cache) {
7443 /* Somebody initialized it before us */
7444 g_hash_table_destroy (the_name_cache);
7446 mono_atomic_store_release (&image->name_cache, the_name_cache);
7448 mono_image_unlock (image);
7452 /* Temporary hash table to avoid lookups in the nspace_table */
7453 name_cache2 = g_hash_table_new (NULL, NULL);
7455 for (i = 1; i <= t->rows; ++i) {
7456 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7457 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7459 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7460 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7462 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7464 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7465 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7467 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7468 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7469 if (!nspace_table) {
7470 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7471 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7472 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7475 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7478 /* Load type names from EXPORTEDTYPES table */
7480 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7481 guint32 cols [MONO_EXP_TYPE_SIZE];
7484 for (i = 0; i < t->rows; ++i) {
7485 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7487 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7488 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7492 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7493 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7495 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7496 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7497 if (!nspace_table) {
7498 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7499 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7500 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7503 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7507 g_hash_table_destroy (name_cache2);
7509 mono_image_lock (image);
7510 if (image->name_cache) {
7511 /* Somebody initialized it before us */
7512 g_hash_table_destroy (the_name_cache);
7514 mono_atomic_store_release (&image->name_cache, the_name_cache);
7516 mono_image_unlock (image);
7519 /*FIXME Only dynamic assemblies should allow this operation.*/
7521 * mono_image_add_to_name_cache:
7524 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7525 const char *name, guint32 index)
7527 GHashTable *nspace_table;
7528 GHashTable *name_cache;
7531 mono_image_init_name_cache (image);
7532 mono_image_lock (image);
7534 name_cache = image->name_cache;
7535 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7536 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7537 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7540 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7541 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7543 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7545 mono_image_unlock (image);
7554 find_nocase (gpointer key, gpointer value, gpointer user_data)
7556 char *name = (char*)key;
7557 FindUserData *data = (FindUserData*)user_data;
7559 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7560 data->value = value;
7564 * mono_class_from_name_case:
7565 * \param image The MonoImage where the type is looked up in
7566 * \param name_space the type namespace
7567 * \param name the type short name.
7568 * \deprecated use the mono_class_from_name_case_checked variant instead.
7570 * Obtains a \c MonoClass with a given namespace and a given name which
7571 * is located in the given \c MonoImage. The namespace and name
7572 * lookups are case insensitive.
7575 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7578 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7579 mono_error_cleanup (&error);
7585 * mono_class_from_name_case_checked:
7586 * \param image The MonoImage where the type is looked up in
7587 * \param name_space the type namespace
7588 * \param name the type short name.
7591 * Obtains a MonoClass with a given namespace and a given name which
7592 * is located in the given MonoImage. The namespace and name
7593 * lookups are case insensitive.
7595 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7596 * was not found. The \p error object will contain information about the problem
7600 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7602 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7603 guint32 cols [MONO_TYPEDEF_SIZE];
7610 if (image_is_dynamic (image)) {
7612 FindUserData user_data;
7614 mono_image_init_name_cache (image);
7615 mono_image_lock (image);
7617 user_data.key = name_space;
7618 user_data.value = NULL;
7619 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7621 if (user_data.value) {
7622 GHashTable *nspace_table = (GHashTable*)user_data.value;
7624 user_data.key = name;
7625 user_data.value = NULL;
7627 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7629 if (user_data.value)
7630 token = GPOINTER_TO_UINT (user_data.value);
7633 mono_image_unlock (image);
7636 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7642 /* add a cache if needed */
7643 for (i = 1; i <= t->rows; ++i) {
7644 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7645 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7647 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7648 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7650 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7652 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7653 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7654 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7655 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7661 return_nested_in (MonoClass *klass, char *nested)
7664 char *s = strchr (nested, '/');
7665 gpointer iter = NULL;
7672 while ((found = mono_class_get_nested_types (klass, &iter))) {
7673 if (strcmp (found->name, nested) == 0) {
7675 return return_nested_in (found, s);
7683 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7685 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7686 MonoImage *file_image;
7693 * The EXPORTEDTYPES table only contains public types, so have to search the
7695 * Note: image->modules contains the contents of the MODULEREF table, while
7696 * the real module list is in the FILE table.
7698 for (i = 0; i < file_table->rows; i++) {
7699 guint32 cols [MONO_FILE_SIZE];
7700 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7701 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7704 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7706 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7707 if (klass || !is_ok (error))
7716 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7718 GHashTable *nspace_table;
7719 MonoImage *loaded_image;
7728 // Checking visited images avoids stack overflows when cyclic references exist.
7729 if (g_hash_table_lookup (visited_images, image))
7732 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7734 if ((nested = strchr (name, '/'))) {
7735 int pos = nested - name;
7736 int len = strlen (name);
7739 memcpy (buf, name, len + 1);
7741 nested = buf + pos + 1;
7745 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7746 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7747 gboolean res = get_class_from_name (image, name_space, name, &klass);
7750 klass = search_modules (image, name_space, name, error);
7755 return klass ? return_nested_in (klass, nested) : NULL;
7761 mono_image_init_name_cache (image);
7762 mono_image_lock (image);
7764 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7767 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7769 mono_image_unlock (image);
7771 if (!token && image_is_dynamic (image) && image->modules) {
7772 /* Search modules as well */
7773 for (i = 0; i < image->module_count; ++i) {
7774 MonoImage *module = image->modules [i];
7776 klass = mono_class_from_name_checked (module, name_space, name, error);
7777 if (klass || !is_ok (error))
7783 klass = search_modules (image, name_space, name, error);
7784 if (klass || !is_ok (error))
7789 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7790 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7791 guint32 cols [MONO_EXP_TYPE_SIZE];
7794 idx = mono_metadata_token_index (token);
7796 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7798 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7799 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7800 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7803 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7805 return klass ? return_nested_in (klass, nested) : NULL;
7807 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7808 guint32 assembly_idx;
7810 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7812 mono_assembly_load_reference (image, assembly_idx - 1);
7813 g_assert (image->references [assembly_idx - 1]);
7814 if (image->references [assembly_idx - 1] == (gpointer)-1)
7816 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7818 return klass ? return_nested_in (klass, nested) : NULL;
7821 g_assert_not_reached ();
7825 token = MONO_TOKEN_TYPE_DEF | token;
7827 klass = mono_class_get_checked (image, token, error);
7829 return return_nested_in (klass, nested);
7834 * mono_class_from_name_checked:
7835 * \param image The MonoImage where the type is looked up in
7836 * \param name_space the type namespace
7837 * \param name the type short name.
7839 * Obtains a MonoClass with a given namespace and a given name which
7840 * is located in the given MonoImage.
7842 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7843 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7846 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7849 GHashTable *visited_images;
7851 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7853 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7855 g_hash_table_destroy (visited_images);
7861 * mono_class_from_name:
7862 * \param image The \c MonoImage where the type is looked up in
7863 * \param name_space the type namespace
7864 * \param name the type short name.
7866 * Obtains a \c MonoClass with a given namespace and a given name which
7867 * is located in the given \c MonoImage.
7869 * To reference nested classes, use the "/" character as a separator.
7870 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7871 * inside \c Foo, like this: "class Foo { class Bar {} }".
7874 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7879 klass = mono_class_from_name_checked (image, name_space, name, &error);
7880 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7886 * mono_class_load_from_name:
7887 * \param image The MonoImage where the type is looked up in
7888 * \param name_space the type namespace
7889 * \param name the type short name.
7891 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7892 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7893 * If they are missing. Thing of System.Object or System.String.
7896 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7901 klass = mono_class_from_name_checked (image, name_space, name, &error);
7903 g_error ("Runtime critical type %s.%s not found", name_space, name);
7904 if (!mono_error_ok (&error))
7905 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7910 * mono_class_try_load_from_name:
7911 * \param image The MonoImage where the type is looked up in
7912 * \param name_space the type namespace
7913 * \param name the type short name.
7915 * This function tries to load a type, returning the class was found or NULL otherwise.
7916 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7918 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7919 * a type that we would otherwise assume to be available but was not due some error.
7923 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7928 klass = mono_class_from_name_checked (image, name_space, name, &error);
7929 if (!mono_error_ok (&error))
7930 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7936 * mono_class_is_subclass_of:
7937 * \param klass class to probe if it is a subclass of another one
7938 * \param klassc the class we suspect is the base class
7939 * \param check_interfaces whether we should perform interface checks
7941 * This method determines whether \p klass is a subclass of \p klassc.
7943 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7944 * this method return TRUE if the \p klass implements the interface or
7945 * if \p klass is an interface, if one of its base classes is \p klass.
7947 * If \p check_interfaces is false, then if \p klass is not an interface,
7948 * it returns TRUE if the \p klass is a subclass of \p klassc.
7950 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7955 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7956 gboolean check_interfaces)
7958 /* FIXME test for interfaces with variant generic arguments */
7959 mono_class_init (klass);
7960 mono_class_init (klassc);
7962 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7963 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7965 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7968 for (i = 0; i < klass->interface_count; i ++) {
7969 MonoClass *ic = klass->interfaces [i];
7974 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7979 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7982 if (klassc == mono_defaults.object_class)
7989 mono_type_is_generic_argument (MonoType *type)
7991 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7995 mono_class_has_variant_generic_params (MonoClass *klass)
7998 MonoGenericContainer *container;
8000 if (!mono_class_is_ginst (klass))
8003 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8005 for (i = 0; i < container->type_argc; ++i)
8006 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8013 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8015 if (target == candidate)
8018 if (check_for_reference_conv &&
8019 mono_type_is_generic_argument (&target->byval_arg) &&
8020 mono_type_is_generic_argument (&candidate->byval_arg)) {
8021 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8022 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8024 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8027 if (!mono_class_is_assignable_from (target, candidate))
8033 * @container the generic container from the GTD
8034 * @klass: the class to be assigned to
8035 * @oklass: the source class
8037 * Both @klass and @oklass must be instances of the same generic interface.
8039 * Returns: TRUE if @klass can be assigned to a @klass variable
8042 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8045 MonoType **klass_argv, **oklass_argv;
8046 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8047 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8049 if (klass == oklass)
8052 /*Viable candidates are instances of the same generic interface*/
8053 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8056 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8057 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8059 for (j = 0; j < container->type_argc; ++j) {
8060 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8061 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8063 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8067 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8068 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8070 if (param1_class != param2_class) {
8071 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8072 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8074 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8075 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8085 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8087 MonoGenericParam *gparam, *ogparam;
8088 MonoGenericParamInfo *tinfo, *cinfo;
8089 MonoClass **candidate_class;
8090 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8093 if (target == candidate)
8095 if (target->byval_arg.type != candidate->byval_arg.type)
8098 gparam = target->byval_arg.data.generic_param;
8099 ogparam = candidate->byval_arg.data.generic_param;
8100 tinfo = mono_generic_param_info (gparam);
8101 cinfo = mono_generic_param_info (ogparam);
8103 class_constraint_satisfied = FALSE;
8104 valuetype_constraint_satisfied = FALSE;
8106 /*candidate must have a super set of target's special constraints*/
8107 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8108 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8110 if (cinfo->constraints) {
8111 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8112 MonoClass *cc = *candidate_class;
8114 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8115 class_constraint_satisfied = TRUE;
8116 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8117 valuetype_constraint_satisfied = TRUE;
8120 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8121 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8123 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8125 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8127 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8128 valuetype_constraint_satisfied)) {
8133 /*candidate type constraints must be a superset of target's*/
8134 if (tinfo->constraints) {
8135 MonoClass **target_class;
8136 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8137 MonoClass *tc = *target_class;
8140 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8141 * check it's constraints since it satisfy the constraint by itself.
8143 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8146 if (!cinfo->constraints)
8149 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8150 MonoClass *cc = *candidate_class;
8152 if (mono_class_is_assignable_from (tc, cc))
8156 * This happens when we have the following:
8158 * Bar<K> where K : IFace
8159 * Foo<T, U> where T : U where U : IFace
8161 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8164 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8165 if (mono_gparam_is_assignable_from (target, cc))
8169 if (!*candidate_class)
8174 /*candidate itself must have a constraint that satisfy target*/
8175 if (cinfo->constraints) {
8176 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8177 MonoClass *cc = *candidate_class;
8178 if (mono_class_is_assignable_from (target, cc))
8186 * mono_class_is_assignable_from:
8187 * \param klass the class to be assigned to
8188 * \param oklass the source class
8190 * \returns TRUE if an instance of class \p oklass can be assigned to an
8191 * instance of class \p klass
8194 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8197 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8199 mono_class_init (klass);
8201 if (!oklass->inited)
8202 mono_class_init (oklass);
8204 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8207 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8208 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8210 return mono_gparam_is_assignable_from (klass, oklass);
8213 if (MONO_CLASS_IS_INTERFACE (klass)) {
8214 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8215 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8216 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8220 for (i = 0; constraints [i]; ++i) {
8221 if (mono_class_is_assignable_from (klass, constraints [i]))
8229 /* interface_offsets might not be set for dynamic classes */
8230 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8232 * oklass might be a generic type parameter but they have
8233 * interface_offsets set.
8235 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8236 if (!is_ok (&error)) {
8237 mono_error_cleanup (&error);
8242 if (!oklass->interface_bitmap)
8243 /* Happens with generic instances of not-yet created dynamic types */
8245 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8248 if (klass->is_array_special_interface && oklass->rank == 1) {
8249 //XXX we could offset this by having the cast target computed at JIT time
8250 //XXX we could go even further and emit a wrapper that would do the extra type check
8251 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8252 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8254 // If the target we're trying to cast to is a valuetype, we must account of weird valuetype equivalences such as IntEnum <> int or uint <> int
8255 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8256 if (iface_klass->valuetype)
8257 iface_klass = iface_klass->cast_class;
8259 //array covariant casts only operates on scalar to scalar
8260 //This is so int[] can't be casted to IComparable<int>[]
8261 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8265 if (mono_class_has_variant_generic_params (klass)) {
8267 mono_class_setup_interfaces (oklass, &error);
8268 if (!mono_error_ok (&error)) {
8269 mono_error_cleanup (&error);
8273 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8274 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8275 MonoClass *iface = oklass->interfaces_packed [i];
8277 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8282 } else if (klass->delegate) {
8283 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8285 }else if (klass->rank) {
8286 MonoClass *eclass, *eoclass;
8288 if (oklass->rank != klass->rank)
8291 /* vectors vs. one dimensional arrays */
8292 if (oklass->byval_arg.type != klass->byval_arg.type)
8295 eclass = klass->cast_class;
8296 eoclass = oklass->cast_class;
8299 * a is b does not imply a[] is b[] when a is a valuetype, and
8300 * b is a reference type.
8303 if (eoclass->valuetype) {
8304 if ((eclass == mono_defaults.enum_class) ||
8305 (eclass == mono_defaults.enum_class->parent) ||
8306 (eclass == mono_defaults.object_class))
8310 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8311 } else if (mono_class_is_nullable (klass)) {
8312 if (mono_class_is_nullable (oklass))
8313 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8315 return mono_class_is_assignable_from (klass->cast_class, oklass);
8316 } else if (klass == mono_defaults.object_class)
8319 return mono_class_has_parent (oklass, klass);
8322 /*Check if @oklass is variant compatible with @klass.*/
8324 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8327 MonoType **klass_argv, **oklass_argv;
8328 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8329 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8331 /*Viable candidates are instances of the same generic interface*/
8332 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8335 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8336 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8338 for (j = 0; j < container->type_argc; ++j) {
8339 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8340 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8342 if (param1_class->valuetype != param2_class->valuetype)
8346 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8347 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8349 if (param1_class != param2_class) {
8350 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8351 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8353 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8354 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8362 /*Check if @candidate implements the interface @target*/
8364 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8368 gboolean is_variant = mono_class_has_variant_generic_params (target);
8370 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8371 if (mono_class_is_variant_compatible_slow (target, candidate))
8376 if (candidate == target)
8379 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8380 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8381 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8383 if (tb && tb->interfaces) {
8384 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8385 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8386 MonoClass *iface_class;
8388 /* we can't realize the type here since it can do pretty much anything. */
8391 iface_class = mono_class_from_mono_type (iface->type);
8392 if (iface_class == target)
8394 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8396 if (mono_class_implement_interface_slow (target, iface_class))
8401 /*setup_interfaces don't mono_class_init anything*/
8402 /*FIXME this doesn't handle primitive type arrays.
8403 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8404 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8406 mono_class_setup_interfaces (candidate, &error);
8407 if (!mono_error_ok (&error)) {
8408 mono_error_cleanup (&error);
8412 for (i = 0; i < candidate->interface_count; ++i) {
8413 if (candidate->interfaces [i] == target)
8416 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8419 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8423 candidate = candidate->parent;
8424 } while (candidate);
8430 * Check if @oklass can be assigned to @klass.
8431 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8434 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8436 if (candidate == target)
8438 if (target == mono_defaults.object_class)
8441 if (mono_class_has_parent (candidate, target))
8444 /*If target is not an interface there is no need to check them.*/
8445 if (MONO_CLASS_IS_INTERFACE (target))
8446 return mono_class_implement_interface_slow (target, candidate);
8448 if (target->delegate && mono_class_has_variant_generic_params (target))
8449 return mono_class_is_variant_compatible (target, candidate, FALSE);
8452 MonoClass *eclass, *eoclass;
8454 if (target->rank != candidate->rank)
8457 /* vectors vs. one dimensional arrays */
8458 if (target->byval_arg.type != candidate->byval_arg.type)
8461 eclass = target->cast_class;
8462 eoclass = candidate->cast_class;
8465 * a is b does not imply a[] is b[] when a is a valuetype, and
8466 * b is a reference type.
8469 if (eoclass->valuetype) {
8470 if ((eclass == mono_defaults.enum_class) ||
8471 (eclass == mono_defaults.enum_class->parent) ||
8472 (eclass == mono_defaults.object_class))
8476 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8478 /*FIXME properly handle nullables */
8479 /*FIXME properly handle (M)VAR */
8484 * mono_class_get_cctor:
8485 * \param klass A MonoClass pointer
8487 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8490 mono_class_get_cctor (MonoClass *klass)
8492 MonoCachedClassInfo cached_info;
8494 if (image_is_dynamic (klass->image)) {
8496 * has_cctor is not set for these classes because mono_class_init () is
8499 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8502 mono_class_init (klass);
8504 if (!klass->has_cctor)
8507 if (mono_class_is_ginst (klass) && !klass->methods)
8508 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8510 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8512 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8513 if (!mono_error_ok (&error))
8514 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8518 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8522 * mono_class_get_finalizer:
8523 * \param klass: The MonoClass pointer
8525 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8528 mono_class_get_finalizer (MonoClass *klass)
8530 MonoCachedClassInfo cached_info;
8533 mono_class_init (klass);
8534 if (!mono_class_has_finalizer (klass))
8537 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8539 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8540 if (!mono_error_ok (&error))
8541 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8544 mono_class_setup_vtable (klass);
8545 return klass->vtable [finalize_slot];
8550 * mono_class_needs_cctor_run:
8551 * \param klass the MonoClass pointer
8552 * \param caller a MonoMethod describing the caller
8554 * Determines whenever the class has a static constructor and whenever it
8555 * needs to be called when executing CALLER.
8558 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8562 method = mono_class_get_cctor (klass);
8564 return (method == caller) ? FALSE : TRUE;
8570 * mono_class_array_element_size:
8573 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8576 mono_class_array_element_size (MonoClass *klass)
8578 MonoType *type = &klass->byval_arg;
8581 switch (type->type) {
8584 case MONO_TYPE_BOOLEAN:
8588 case MONO_TYPE_CHAR:
8597 case MONO_TYPE_CLASS:
8598 case MONO_TYPE_STRING:
8599 case MONO_TYPE_OBJECT:
8600 case MONO_TYPE_SZARRAY:
8601 case MONO_TYPE_ARRAY:
8602 return sizeof (gpointer);
8607 case MONO_TYPE_VALUETYPE:
8608 if (type->data.klass->enumtype) {
8609 type = mono_class_enum_basetype (type->data.klass);
8610 klass = klass->element_class;
8613 return mono_class_instance_size (klass) - sizeof (MonoObject);
8614 case MONO_TYPE_GENERICINST:
8615 type = &type->data.generic_class->container_class->byval_arg;
8618 case MONO_TYPE_MVAR: {
8621 return mono_type_size (type, &align);
8623 case MONO_TYPE_VOID:
8627 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8633 * mono_array_element_size:
8634 * \param ac pointer to a \c MonoArrayClass
8636 * \returns The size of single array element.
8639 mono_array_element_size (MonoClass *ac)
8641 g_assert (ac->rank);
8642 return ac->sizes.element_size;
8649 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8650 MonoGenericContext *context)
8653 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8654 g_assert (mono_error_ok (&error));
8659 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8660 MonoGenericContext *context, MonoError *error)
8664 if (image_is_dynamic (image)) {
8665 MonoClass *tmp_handle_class;
8666 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8668 mono_error_assert_ok (error);
8669 g_assert (tmp_handle_class);
8671 *handle_class = tmp_handle_class;
8673 if (tmp_handle_class == mono_defaults.typehandle_class)
8674 return &((MonoClass*)obj)->byval_arg;
8679 switch (token & 0xff000000) {
8680 case MONO_TOKEN_TYPE_DEF:
8681 case MONO_TOKEN_TYPE_REF:
8682 case MONO_TOKEN_TYPE_SPEC: {
8685 *handle_class = mono_defaults.typehandle_class;
8686 type = mono_type_get_checked (image, token, context, error);
8690 mono_class_init (mono_class_from_mono_type (type));
8691 /* We return a MonoType* as handle */
8694 case MONO_TOKEN_FIELD_DEF: {
8696 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8698 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8702 *handle_class = mono_defaults.fieldhandle_class;
8703 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8707 mono_class_init (klass);
8708 return mono_class_get_field (klass, token);
8710 case MONO_TOKEN_METHOD_DEF:
8711 case MONO_TOKEN_METHOD_SPEC: {
8713 meth = mono_get_method_checked (image, token, NULL, context, error);
8715 *handle_class = mono_defaults.methodhandle_class;
8721 case MONO_TOKEN_MEMBER_REF: {
8722 guint32 cols [MONO_MEMBERREF_SIZE];
8724 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8725 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8726 mono_metadata_decode_blob_size (sig, &sig);
8727 if (*sig == 0x6) { /* it's a field */
8729 MonoClassField *field;
8730 field = mono_field_from_token_checked (image, token, &klass, context, error);
8732 *handle_class = mono_defaults.fieldhandle_class;
8736 meth = mono_get_method_checked (image, token, NULL, context, error);
8738 *handle_class = mono_defaults.methodhandle_class;
8743 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8749 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8751 MonoClass *handle_class;
8753 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8757 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8759 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8762 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8765 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8767 get_cached_class_info = func;
8771 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8773 if (!get_cached_class_info)
8776 return get_cached_class_info (klass, res);
8780 mono_install_get_class_from_name (MonoGetClassFromName func)
8782 get_class_from_name = func;
8786 * mono_class_get_image:
8788 * Use this method to get the \c MonoImage* where this class came from.
8790 * \returns The image where this class is defined.
8793 mono_class_get_image (MonoClass *klass)
8795 return klass->image;
8799 * mono_class_get_element_class:
8800 * \param klass the \c MonoClass to act on
8802 * Use this function to get the element class of an array.
8804 * \returns The element class of an array.
8807 mono_class_get_element_class (MonoClass *klass)
8809 return klass->element_class;
8813 * mono_class_is_valuetype:
8814 * \param klass the \c MonoClass to act on
8816 * Use this method to determine if the provided \c MonoClass* represents a value type,
8817 * or a reference type.
8819 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8822 mono_class_is_valuetype (MonoClass *klass)
8824 return klass->valuetype;
8828 * mono_class_is_enum:
8829 * \param klass the \c MonoClass to act on
8831 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8833 * \returns TRUE if the \c MonoClass represents an enumeration.
8836 mono_class_is_enum (MonoClass *klass)
8838 return klass->enumtype;
8842 * mono_class_enum_basetype:
8843 * \param klass the \c MonoClass to act on
8845 * Use this function to get the underlying type for an enumeration value.
8847 * \returns The underlying type representation for an enumeration.
8850 mono_class_enum_basetype (MonoClass *klass)
8852 if (klass->element_class == klass)
8853 /* SRE or broken types */
8856 return &klass->element_class->byval_arg;
8860 * mono_class_get_parent
8861 * \param klass the \c MonoClass to act on
8863 * \returns The parent class for this class.
8866 mono_class_get_parent (MonoClass *klass)
8868 return klass->parent;
8872 * mono_class_get_nesting_type:
8873 * \param klass the \c MonoClass to act on
8875 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8877 * If the return is NULL, this indicates that this class is not nested.
8879 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8882 mono_class_get_nesting_type (MonoClass *klass)
8884 return klass->nested_in;
8888 * mono_class_get_rank:
8889 * \param klass the MonoClass to act on
8891 * \returns The rank for the array (the number of dimensions).
8894 mono_class_get_rank (MonoClass *klass)
8900 * mono_class_get_name
8901 * \param klass the \c MonoClass to act on
8903 * \returns The name of the class.
8906 mono_class_get_name (MonoClass *klass)
8912 * mono_class_get_namespace:
8913 * \param klass the \c MonoClass to act on
8915 * \returns The namespace of the class.
8918 mono_class_get_namespace (MonoClass *klass)
8920 return klass->name_space;
8924 * mono_class_get_type:
8925 * \param klass the \c MonoClass to act on
8927 * This method returns the internal \c MonoType representation for the class.
8929 * \returns The \c MonoType from the class.
8932 mono_class_get_type (MonoClass *klass)
8934 return &klass->byval_arg;
8938 * mono_class_get_type_token:
8939 * \param klass the \c MonoClass to act on
8941 * This method returns type token for the class.
8943 * \returns The type token for the class.
8946 mono_class_get_type_token (MonoClass *klass)
8948 return klass->type_token;
8952 * mono_class_get_byref_type:
8953 * \param klass the \c MonoClass to act on
8958 mono_class_get_byref_type (MonoClass *klass)
8960 return &klass->this_arg;
8964 * mono_class_num_fields:
8965 * \param klass the \c MonoClass to act on
8967 * \returns The number of static and instance fields in the class.
8970 mono_class_num_fields (MonoClass *klass)
8972 return mono_class_get_field_count (klass);
8976 * mono_class_num_methods:
8977 * \param klass the \c MonoClass to act on
8979 * \returns The number of methods in the class.
8982 mono_class_num_methods (MonoClass *klass)
8984 return mono_class_get_method_count (klass);
8988 * mono_class_num_properties
8989 * \param klass the \c MonoClass to act on
8991 * \returns The number of properties in the class.
8994 mono_class_num_properties (MonoClass *klass)
8996 mono_class_setup_properties (klass);
8998 return mono_class_get_property_info (klass)->count;
9002 * mono_class_num_events:
9003 * \param klass the \c MonoClass to act on
9005 * \returns The number of events in the class.
9008 mono_class_num_events (MonoClass *klass)
9010 mono_class_setup_events (klass);
9012 return mono_class_get_event_info (klass)->count;
9016 * mono_class_get_fields:
9017 * \param klass the \c MonoClass to act on
9019 * This routine is an iterator routine for retrieving the fields in a class.
9021 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9022 * iterate over all of the elements. When no more values are
9023 * available, the return value is NULL.
9025 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9028 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9030 MonoClassField* field;
9034 mono_class_setup_fields (klass);
9035 if (mono_class_has_failure (klass))
9037 /* start from the first */
9038 if (mono_class_get_field_count (klass)) {
9039 *iter = &klass->fields [0];
9040 return &klass->fields [0];
9046 field = (MonoClassField *)*iter;
9048 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9056 * mono_class_get_methods:
9057 * \param klass the \c MonoClass to act on
9059 * This routine is an iterator routine for retrieving the fields in a class.
9061 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9062 * iterate over all of the elements. When no more values are
9063 * available, the return value is NULL.
9065 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9068 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9070 MonoMethod** method;
9074 mono_class_setup_methods (klass);
9077 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9078 * FIXME we should better report this error to the caller
9080 if (!klass->methods)
9082 /* start from the first */
9083 if (mono_class_get_method_count (klass)) {
9084 *iter = &klass->methods [0];
9085 return klass->methods [0];
9091 method = (MonoMethod **)*iter;
9093 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9101 * mono_class_get_virtual_methods:
9103 * Iterate over the virtual methods of KLASS.
9105 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9108 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9110 MonoMethod** method;
9113 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9115 mono_class_setup_methods (klass);
9117 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9118 * FIXME we should better report this error to the caller
9120 if (!klass->methods)
9122 /* start from the first */
9123 method = &klass->methods [0];
9125 method = (MonoMethod **)*iter;
9128 int mcount = mono_class_get_method_count (klass);
9129 while (method < &klass->methods [mcount]) {
9130 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9134 if (method < &klass->methods [mcount]) {
9141 /* Search directly in metadata to avoid calling setup_methods () */
9142 MonoMethod *res = NULL;
9148 start_index = GPOINTER_TO_UINT (*iter);
9151 int first_idx = mono_class_get_first_method_idx (klass);
9152 int mcount = mono_class_get_method_count (klass);
9153 for (i = start_index; i < mcount; ++i) {
9156 /* first_idx points into the methodptr table */
9157 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9159 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9165 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9166 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9168 /* Add 1 here so the if (*iter) check fails */
9169 *iter = GUINT_TO_POINTER (i + 1);
9178 * mono_class_get_properties:
9179 * \param klass the \c MonoClass to act on
9181 * This routine is an iterator routine for retrieving the properties in a class.
9183 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9184 * iterate over all of the elements. When no more values are
9185 * available, the return value is NULL.
9187 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9190 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9192 MonoProperty* property;
9196 mono_class_setup_properties (klass);
9197 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9198 /* start from the first */
9200 *iter = &info->properties [0];
9201 return (MonoProperty *)*iter;
9207 property = (MonoProperty *)*iter;
9209 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9210 if (property < &info->properties [info->count]) {
9212 return (MonoProperty *)*iter;
9218 * mono_class_get_events:
9219 * \param klass the \c MonoClass to act on
9221 * This routine is an iterator routine for retrieving the properties in a class.
9223 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9224 * iterate over all of the elements. When no more values are
9225 * available, the return value is NULL.
9227 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9230 mono_class_get_events (MonoClass* klass, gpointer *iter)
9236 mono_class_setup_events (klass);
9237 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9238 /* start from the first */
9240 *iter = &info->events [0];
9241 return (MonoEvent *)*iter;
9247 event = (MonoEvent *)*iter;
9249 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9250 if (event < &info->events [info->count]) {
9252 return (MonoEvent *)*iter;
9258 * mono_class_get_interfaces
9259 * \param klass the \c MonoClass to act on
9261 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9263 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9264 * iterate over all of the elements. When no more values are
9265 * available, the return value is NULL.
9267 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9270 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9278 mono_class_init (klass);
9279 if (!klass->interfaces_inited) {
9280 mono_class_setup_interfaces (klass, &error);
9281 if (!mono_error_ok (&error)) {
9282 mono_error_cleanup (&error);
9286 /* start from the first */
9287 if (klass->interface_count) {
9288 *iter = &klass->interfaces [0];
9289 return klass->interfaces [0];
9295 iface = (MonoClass **)*iter;
9297 if (iface < &klass->interfaces [klass->interface_count]) {
9305 setup_nested_types (MonoClass *klass)
9308 GList *classes, *nested_classes, *l;
9311 if (klass->nested_classes_inited)
9314 if (!klass->type_token) {
9315 mono_loader_lock ();
9316 klass->nested_classes_inited = TRUE;
9317 mono_loader_unlock ();
9321 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9325 guint32 cols [MONO_NESTED_CLASS_SIZE];
9326 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9327 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9328 if (!mono_error_ok (&error)) {
9329 /*FIXME don't swallow the error message*/
9330 mono_error_cleanup (&error);
9332 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9336 classes = g_list_prepend (classes, nclass);
9338 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9341 nested_classes = NULL;
9342 for (l = classes; l; l = l->next)
9343 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9344 g_list_free (classes);
9346 mono_loader_lock ();
9347 if (!klass->nested_classes_inited) {
9348 mono_class_set_nested_classes_property (klass, nested_classes);
9349 mono_memory_barrier ();
9350 klass->nested_classes_inited = TRUE;
9352 mono_loader_unlock ();
9356 * mono_class_get_nested_types
9357 * \param klass the \c MonoClass to act on
9359 * This routine is an iterator routine for retrieving the nested types of a class.
9360 * This works only if \p klass is non-generic, or a generic type definition.
9362 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9363 * iterate over all of the elements. When no more values are
9364 * available, the return value is NULL.
9366 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9369 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9375 if (!klass->nested_classes_inited)
9376 setup_nested_types (klass);
9379 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9380 /* start from the first */
9381 if (nested_classes) {
9382 *iter = nested_classes;
9383 return (MonoClass *)nested_classes->data;
9385 /* no nested types */
9389 item = (GList *)*iter;
9393 return (MonoClass *)item->data;
9400 * mono_class_is_delegate
9401 * \param klass the \c MonoClass to act on
9403 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9406 mono_class_is_delegate (MonoClass *klass)
9408 return klass->delegate;
9412 * mono_class_implements_interface
9413 * \param klass The MonoClass to act on
9414 * \param interface The interface to check if \p klass implements.
9416 * \returns TRUE if \p klass implements \p interface.
9419 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9421 return mono_class_is_assignable_from (iface, klass);
9425 * mono_field_get_name:
9426 * \param field the \c MonoClassField to act on
9428 * \returns The name of the field.
9431 mono_field_get_name (MonoClassField *field)
9437 * mono_field_get_type:
9438 * \param field the \c MonoClassField to act on
9439 * \returns \c MonoType of the field.
9442 mono_field_get_type (MonoClassField *field)
9445 MonoType *type = mono_field_get_type_checked (field, &error);
9446 if (!mono_error_ok (&error)) {
9447 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9448 mono_error_cleanup (&error);
9455 * mono_field_get_type_checked:
9456 * \param field the \c MonoClassField to act on
9457 * \param error used to return any error found while retrieving \p field type
9459 * \returns \c MonoType of the field.
9462 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9466 mono_field_resolve_type (field, error);
9471 * mono_field_get_parent:
9472 * \param field the \c MonoClassField to act on
9474 * \returns \c MonoClass where the field was defined.
9477 mono_field_get_parent (MonoClassField *field)
9479 return field->parent;
9483 * mono_field_get_flags;
9484 * \param field the \c MonoClassField to act on
9486 * The metadata flags for a field are encoded using the
9487 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9489 * \returns The flags for the field.
9492 mono_field_get_flags (MonoClassField *field)
9495 return mono_field_resolve_flags (field);
9496 return field->type->attrs;
9500 * mono_field_get_offset:
9501 * \param field the \c MonoClassField to act on
9503 * \returns The field offset.
9506 mono_field_get_offset (MonoClassField *field)
9508 return field->offset;
9512 mono_field_get_rva (MonoClassField *field)
9516 MonoClass *klass = field->parent;
9517 MonoFieldDefaultValue *def_values;
9519 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9521 def_values = mono_class_get_field_def_values (klass);
9523 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9525 mono_class_set_field_def_values (klass, def_values);
9528 field_index = mono_field_get_index (field);
9530 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9531 int first_field_idx = mono_class_get_first_field_idx (klass);
9532 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9534 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9535 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9538 return def_values [field_index].data;
9542 * mono_field_get_data:
9543 * \param field the \c MonoClassField to act on
9545 * \returns A pointer to the metadata constant value or to the field
9546 * data if it has an RVA flag.
9549 mono_field_get_data (MonoClassField *field)
9551 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9552 MonoTypeEnum def_type;
9554 return mono_class_get_field_default_value (field, &def_type);
9555 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9556 return mono_field_get_rva (field);
9563 * mono_property_get_name:
9564 * \param prop the \c MonoProperty to act on
9565 * \returns The name of the property
9568 mono_property_get_name (MonoProperty *prop)
9574 * mono_property_get_set_method
9575 * \param prop the \c MonoProperty to act on.
9576 * \returns The setter method of the property, a \c MonoMethod.
9579 mono_property_get_set_method (MonoProperty *prop)
9585 * mono_property_get_get_method
9586 * \param prop the MonoProperty to act on.
9587 * \returns The getter method of the property (A \c MonoMethod)
9590 mono_property_get_get_method (MonoProperty *prop)
9596 * mono_property_get_parent:
9597 * \param prop the \c MonoProperty to act on.
9598 * \returns The \c MonoClass where the property was defined.
9601 mono_property_get_parent (MonoProperty *prop)
9603 return prop->parent;
9607 * mono_property_get_flags:
9608 * \param prop the \c MonoProperty to act on.
9610 * The metadata flags for a property are encoded using the
9611 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9613 * \returns The flags for the property.
9616 mono_property_get_flags (MonoProperty *prop)
9622 * mono_event_get_name:
9623 * \param event the MonoEvent to act on
9624 * \returns The name of the event.
9627 mono_event_get_name (MonoEvent *event)
9633 * mono_event_get_add_method:
9634 * \param event The \c MonoEvent to act on.
9635 * \returns The \c add method for the event, a \c MonoMethod.
9638 mono_event_get_add_method (MonoEvent *event)
9644 * mono_event_get_remove_method:
9645 * \param event The \c MonoEvent to act on.
9646 * \returns The \c remove method for the event, a \c MonoMethod.
9649 mono_event_get_remove_method (MonoEvent *event)
9651 return event->remove;
9655 * mono_event_get_raise_method:
9656 * \param event The \c MonoEvent to act on.
9657 * \returns The \c raise method for the event, a \c MonoMethod.
9660 mono_event_get_raise_method (MonoEvent *event)
9662 return event->raise;
9666 * mono_event_get_parent:
9667 * \param event the MonoEvent to act on.
9668 * \returns The \c MonoClass where the event is defined.
9671 mono_event_get_parent (MonoEvent *event)
9673 return event->parent;
9677 * mono_event_get_flags
9678 * \param event the \c MonoEvent to act on.
9680 * The metadata flags for an event are encoded using the
9681 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9683 * \returns The flags for the event.
9686 mono_event_get_flags (MonoEvent *event)
9688 return event->attrs;
9692 * mono_class_get_method_from_name:
9693 * \param klass where to look for the method
9694 * \param name name of the method
9695 * \param param_count number of parameters. -1 for any number.
9697 * Obtains a \c MonoMethod with a given name and number of parameters.
9698 * It only works if there are no multiple signatures for any given method name.
9701 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9703 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9707 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9709 MonoMethod *res = NULL;
9712 /* Search directly in the metadata to avoid calling setup_methods () */
9713 int first_idx = mono_class_get_first_method_idx (klass);
9714 int mcount = mono_class_get_method_count (klass);
9715 for (i = 0; i < mcount; ++i) {
9717 guint32 cols [MONO_METHOD_SIZE];
9719 MonoMethodSignature *sig;
9721 /* first_idx points into the methodptr table */
9722 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9724 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9725 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9727 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9730 if (param_count == -1) {
9734 sig = mono_method_signature_checked (method, &error);
9736 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9739 if (sig->param_count == param_count) {
9750 * mono_class_get_method_from_name_flags:
9751 * \param klass where to look for the method
9752 * \param name_space name of the method
9753 * \param param_count number of parameters. -1 for any number.
9754 * \param flags flags which must be set in the method
9756 * Obtains a \c MonoMethod with a given name and number of parameters.
9757 * It only works if there are no multiple signatures for any given method name.
9760 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9762 MonoMethod *res = NULL;
9765 mono_class_init (klass);
9767 if (mono_class_is_ginst (klass) && !klass->methods) {
9768 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9771 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9772 if (!mono_error_ok (&error))
9773 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9778 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9779 mono_class_setup_methods (klass);
9781 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9782 See mono/tests/array_load_exception.il
9783 FIXME we should better report this error to the caller
9785 if (!klass->methods)
9787 int mcount = mono_class_get_method_count (klass);
9788 for (i = 0; i < mcount; ++i) {
9789 MonoMethod *method = klass->methods [i];
9791 if (method->name[0] == name [0] &&
9792 !strcmp (name, method->name) &&
9793 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9794 ((method->flags & flags) == flags)) {
9801 res = find_method_in_metadata (klass, name, param_count, flags);
9808 * mono_class_set_failure:
9809 * \param klass class in which the failure was detected
9810 * \param ex_type the kind of exception/error to be thrown (later)
9811 * \param ex_data exception data (specific to each type of exception/error)
9813 * Keep a detected failure informations in the class for later processing.
9814 * Note that only the first failure is kept.
9816 * LOCKING: Acquires the loader lock.
9819 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9821 g_assert (boxed_error != NULL);
9823 if (mono_class_has_failure (klass))
9826 mono_loader_lock ();
9827 klass->has_failure = 1;
9828 mono_class_set_exception_data (klass, boxed_error);
9829 mono_loader_unlock ();
9835 mono_class_has_failure (const MonoClass *klass)
9837 g_assert (klass != NULL);
9838 return klass->has_failure != 0;
9843 * mono_class_set_type_load_failure:
9844 * \param klass class in which the failure was detected
9845 * \param fmt \c printf -style error message string.
9847 * Collect detected failure informaion in the class for later processing.
9848 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9849 * Note that only the first failure is kept.
9851 * LOCKING: Acquires the loader lock.
9853 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9856 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9858 MonoError prepare_error;
9861 if (mono_class_has_failure (klass))
9864 error_init (&prepare_error);
9866 va_start (args, fmt);
9867 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9870 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9871 mono_error_cleanup (&prepare_error);
9872 return mono_class_set_failure (klass, box);
9876 * mono_classes_init:
9878 * Initialize the resources used by this module.
9881 mono_classes_init (void)
9883 mono_os_mutex_init (&classes_mutex);
9885 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9886 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9888 mono_counters_register ("MonoClassDef count",
9889 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9890 mono_counters_register ("MonoClassGtd count",
9891 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9892 mono_counters_register ("MonoClassGenericInst count",
9893 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9894 mono_counters_register ("MonoClassGenericParam count",
9895 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9896 mono_counters_register ("MonoClassArray count",
9897 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9898 mono_counters_register ("MonoClassPointer count",
9899 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9900 mono_counters_register ("Inflated methods size",
9901 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9902 mono_counters_register ("Inflated classes size",
9903 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9904 mono_counters_register ("MonoClass size",
9905 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9909 * mono_classes_cleanup:
9911 * Free the resources used by this module.
9914 mono_classes_cleanup (void)
9916 mono_native_tls_free (setup_fields_tls_id);
9917 mono_native_tls_free (init_pending_tls_id);
9919 if (global_interface_bitset)
9920 mono_bitset_free (global_interface_bitset);
9921 global_interface_bitset = NULL;
9922 mono_os_mutex_destroy (&classes_mutex);
9926 * mono_class_get_exception_for_failure:
9927 * \param klass class in which the failure was detected
9929 * \returns a constructed MonoException than the caller can then throw
9930 * using mono_raise_exception - or NULL if no failure is present (or
9931 * doesn't result in an exception).
9934 mono_class_get_exception_for_failure (MonoClass *klass)
9936 if (!mono_class_has_failure (klass))
9938 MonoError unboxed_error;
9939 error_init (&unboxed_error);
9940 mono_error_set_for_class_failure (&unboxed_error, klass);
9941 return mono_error_convert_to_exception (&unboxed_error);
9945 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9947 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9948 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9950 if (outer_klass == inner_klass)
9952 inner_klass = inner_klass->nested_in;
9953 } while (inner_klass);
9958 mono_class_get_generic_type_definition (MonoClass *klass)
9960 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9961 return gklass ? gklass->container_class : klass;
9965 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9967 * Generic instantiations are ignored for all super types of @klass.
9969 * Visibility checks ignoring generic instantiations.
9972 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9975 klass = mono_class_get_generic_type_definition (klass);
9976 parent = mono_class_get_generic_type_definition (parent);
9977 mono_class_setup_supertypes (klass);
9979 for (i = 0; i < klass->idepth; ++i) {
9980 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9986 * Subtype can only access parent members with family protection if the site object
9987 * is subclass of Subtype. For example:
9988 * class A { protected int x; }
9990 * void valid_access () {
9994 * void invalid_access () {
10001 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10003 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10006 if (context_klass == NULL)
10008 /*if access_klass is not member_klass context_klass must be type compat*/
10009 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10015 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10018 if (accessing == accessed)
10020 if (!accessed || !accessing)
10023 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10024 * anywhere so untrusted friends are not safe to access platform's code internals */
10025 if (mono_security_core_clr_enabled ()) {
10026 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10030 mono_assembly_load_friends (accessed);
10031 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10032 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10033 /* Be conservative with checks */
10034 if (!friend_->name)
10036 if (strcmp (accessing->aname.name, friend_->name))
10038 if (friend_->public_key_token [0]) {
10039 if (!accessing->aname.public_key_token [0])
10041 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10050 * If klass is a generic type or if it is derived from a generic type, return the
10051 * MonoClass of the generic definition
10052 * Returns NULL if not found
10055 get_generic_definition_class (MonoClass *klass)
10058 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10059 if (gklass && gklass->container_class)
10060 return gklass->container_class;
10061 klass = klass->parent;
10067 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10070 for (i = 0; i < ginst->type_argc; ++i) {
10071 MonoType *type = ginst->type_argv[i];
10072 switch (type->type) {
10073 case MONO_TYPE_SZARRAY:
10074 if (!can_access_type (access_klass, type->data.klass))
10077 case MONO_TYPE_ARRAY:
10078 if (!can_access_type (access_klass, type->data.array->eklass))
10081 case MONO_TYPE_PTR:
10082 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10085 case MONO_TYPE_CLASS:
10086 case MONO_TYPE_VALUETYPE:
10087 case MONO_TYPE_GENERICINST:
10088 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10098 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10102 if (access_klass == member_klass)
10105 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10108 if (access_klass->element_class && !access_klass->enumtype)
10109 access_klass = access_klass->element_class;
10111 if (member_klass->element_class && !member_klass->enumtype)
10112 member_klass = member_klass->element_class;
10114 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10116 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10119 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10122 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10125 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10128 /*Non nested type with nested visibility. We just fail it.*/
10129 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10132 switch (access_level) {
10133 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10134 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10136 case TYPE_ATTRIBUTE_PUBLIC:
10139 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10142 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10143 return is_nesting_type (member_klass, access_klass);
10145 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10146 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10148 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10149 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10151 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10152 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10153 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10155 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10156 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10157 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10162 /* FIXME: check visibility of type, too */
10164 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10166 MonoClass *member_generic_def;
10167 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10170 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10171 if (((access_gklass && access_gklass->container_class) ||
10172 mono_class_is_gtd (access_klass)) &&
10173 (member_generic_def = get_generic_definition_class (member_klass))) {
10174 MonoClass *access_container;
10176 if (mono_class_is_gtd (access_klass))
10177 access_container = access_klass;
10179 access_container = access_gklass->container_class;
10181 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10185 /* Partition I 8.5.3.2 */
10186 /* the access level values are the same for fields and methods */
10187 switch (access_level) {
10188 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10189 /* same compilation unit */
10190 return access_klass->image == member_klass->image;
10191 case FIELD_ATTRIBUTE_PRIVATE:
10192 return access_klass == member_klass;
10193 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10194 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10195 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10198 case FIELD_ATTRIBUTE_ASSEMBLY:
10199 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10200 case FIELD_ATTRIBUTE_FAMILY:
10201 if (is_valid_family_access (access_klass, member_klass, context_klass))
10204 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10205 if (is_valid_family_access (access_klass, member_klass, context_klass))
10207 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10208 case FIELD_ATTRIBUTE_PUBLIC:
10215 * mono_method_can_access_field:
10216 * \param method Method that will attempt to access the field
10217 * \param field the field to access
10219 * Used to determine if a method is allowed to access the specified field.
10221 * \returns TRUE if the given \p method is allowed to access the \p field while following
10222 * the accessibility rules of the CLI.
10225 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10227 /* FIXME: check all overlapping fields */
10228 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10230 MonoClass *nested = method->klass->nested_in;
10232 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10235 nested = nested->nested_in;
10242 * mono_method_can_access_method:
10243 * \param method Method that will attempt to access the other method
10244 * \param called the method that we want to probe for accessibility.
10246 * Used to determine if the \p method is allowed to access the specified \p called method.
10248 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10249 * the accessibility rules of the CLI.
10252 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10254 method = mono_method_get_method_definition (method);
10255 called = mono_method_get_method_definition (called);
10256 return mono_method_can_access_method_full (method, called, NULL);
10260 * mono_method_can_access_method_full:
10261 * @method: The caller method
10262 * @called: The called method
10263 * @context_klass: The static type on stack of the owner @called object used
10265 * This function must be used with instance calls, as they have more strict family accessibility.
10266 * It can be used with static methods, but context_klass should be NULL.
10268 * Returns: TRUE if caller have proper visibility and acessibility to @called
10271 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10273 /* Wrappers are except from access checks */
10274 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10277 MonoClass *access_class = method->klass;
10278 MonoClass *member_class = called->klass;
10279 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10281 MonoClass *nested = access_class->nested_in;
10283 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10286 nested = nested->nested_in;
10293 can = can_access_type (access_class, member_class);
10295 MonoClass *nested = access_class->nested_in;
10297 can = can_access_type (nested, member_class);
10300 nested = nested->nested_in;
10307 if (called->is_inflated) {
10308 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10309 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10318 * mono_method_can_access_field_full:
10319 * @method: The caller method
10320 * @field: The accessed field
10321 * @context_klass: The static type on stack of the owner @field object used
10323 * This function must be used with instance fields, as they have more strict family accessibility.
10324 * It can be used with static fields, but context_klass should be NULL.
10326 * Returns: TRUE if caller have proper visibility and acessibility to @field
10329 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10331 MonoClass *access_class = method->klass;
10332 MonoClass *member_class = field->parent;
10333 /* FIXME: check all overlapping fields */
10334 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10336 MonoClass *nested = access_class->nested_in;
10338 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10341 nested = nested->nested_in;
10348 can = can_access_type (access_class, member_class);
10350 MonoClass *nested = access_class->nested_in;
10352 can = can_access_type (nested, member_class);
10355 nested = nested->nested_in;
10365 * mono_class_can_access_class:
10366 * @source_class: The source class
10367 * @target_class: The accessed class
10369 * This function returns is @target_class is visible to @source_class
10371 * Returns: TRUE if source have proper visibility and acessibility to target
10374 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10376 return can_access_type (source_class, target_class);
10380 * mono_type_is_valid_enum_basetype:
10381 * \param type The MonoType to check
10382 * \returns TRUE if the type can be used as the basetype of an enum
10384 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10385 switch (type->type) {
10388 case MONO_TYPE_BOOLEAN:
10391 case MONO_TYPE_CHAR:
10405 * mono_class_is_valid_enum:
10406 * \param klass An enum class to be validated
10408 * This method verify the required properties an enum should have.
10410 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10411 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10412 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10414 * \returns TRUE if the informed enum class is valid
10417 mono_class_is_valid_enum (MonoClass *klass)
10419 MonoClassField * field;
10420 gpointer iter = NULL;
10421 gboolean found_base_field = FALSE;
10423 g_assert (klass->enumtype);
10424 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10425 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10429 if (!mono_class_is_auto_layout (klass))
10432 while ((field = mono_class_get_fields (klass, &iter))) {
10433 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10434 if (found_base_field)
10436 found_base_field = TRUE;
10437 if (!mono_type_is_valid_enum_basetype (field->type))
10442 if (!found_base_field)
10445 if (mono_class_get_method_count (klass) > 0)
10452 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10454 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10458 * mono_class_setup_interface_id:
10460 * Initializes MonoClass::interface_id if required.
10462 * LOCKING: Acquires the loader lock.
10465 mono_class_setup_interface_id (MonoClass *klass)
10467 mono_loader_lock ();
10468 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10469 klass->interface_id = mono_get_unique_iid (klass);
10470 mono_loader_unlock ();
10474 * mono_class_setup_interfaces:
10476 * Initialize klass->interfaces/interfaces_count.
10477 * LOCKING: Acquires the loader lock.
10478 * This function can fail the type.
10481 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10483 int i, interface_count;
10484 MonoClass **interfaces;
10486 error_init (error);
10488 if (klass->interfaces_inited)
10491 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10492 MonoType *args [1];
10494 /* generic IList, ICollection, IEnumerable */
10495 interface_count = 2;
10496 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10498 args [0] = &klass->element_class->byval_arg;
10499 interfaces [0] = mono_class_bind_generic_parameters (
10500 mono_defaults.generic_ilist_class, 1, args, FALSE);
10501 interfaces [1] = mono_class_bind_generic_parameters (
10502 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10503 } else if (mono_class_is_ginst (klass)) {
10504 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10506 mono_class_setup_interfaces (gklass, error);
10507 if (!mono_error_ok (error)) {
10508 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10512 interface_count = gklass->interface_count;
10513 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10514 for (i = 0; i < interface_count; i++) {
10515 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10516 if (!mono_error_ok (error)) {
10517 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10522 interface_count = 0;
10526 mono_loader_lock ();
10527 if (!klass->interfaces_inited) {
10528 klass->interface_count = interface_count;
10529 klass->interfaces = interfaces;
10531 mono_memory_barrier ();
10533 klass->interfaces_inited = TRUE;
10535 mono_loader_unlock ();
10539 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10541 MonoClass *klass = field->parent;
10542 MonoImage *image = klass->image;
10543 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10545 int field_idx = field - klass->fields;
10547 error_init (error);
10550 MonoClassField *gfield = >d->fields [field_idx];
10551 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10552 if (!mono_error_ok (error)) {
10553 char *full_name = mono_type_get_full_name (gtd);
10554 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));
10555 g_free (full_name);
10558 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10559 if (!mono_error_ok (error)) {
10560 char *full_name = mono_type_get_full_name (klass);
10561 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));
10562 g_free (full_name);
10566 guint32 cols [MONO_FIELD_SIZE];
10567 MonoGenericContainer *container = NULL;
10568 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10570 /*FIXME, in theory we do not lazy load SRE fields*/
10571 g_assert (!image_is_dynamic (image));
10573 if (mono_class_is_gtd (klass)) {
10574 container = mono_class_get_generic_container (klass);
10576 container = mono_class_get_generic_container (gtd);
10577 g_assert (container);
10580 /* first_field_idx and idx points into the fieldptr table */
10581 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10583 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10584 char *full_name = mono_type_get_full_name (klass);
10585 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10586 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10587 g_free (full_name);
10591 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10593 mono_metadata_decode_value (sig, &sig);
10594 /* FIELD signature == 0x06 */
10595 g_assert (*sig == 0x06);
10597 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10599 char *full_name = mono_type_get_full_name (klass);
10600 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));
10601 g_free (full_name);
10604 mono_memory_barrier ();
10605 field->type = ftype;
10609 mono_field_resolve_flags (MonoClassField *field)
10611 MonoClass *klass = field->parent;
10612 MonoImage *image = klass->image;
10613 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10614 int field_idx = field - klass->fields;
10617 MonoClassField *gfield = >d->fields [field_idx];
10618 return mono_field_get_flags (gfield);
10620 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10622 /*FIXME, in theory we do not lazy load SRE fields*/
10623 g_assert (!image_is_dynamic (image));
10625 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10630 * mono_class_get_fields_lazy:
10631 * \param klass the MonoClass to act on
10633 * This routine is an iterator routine for retrieving the fields in a class.
10634 * Only minimal information about fields are loaded. Accessors must be used
10635 * for all MonoClassField returned.
10637 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10638 * iterate over all of the elements. When no more values are
10639 * available, the return value is NULL.
10641 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10644 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10646 MonoClassField* field;
10650 mono_class_setup_basic_field_info (klass);
10651 if (!klass->fields)
10653 /* start from the first */
10654 if (mono_class_get_field_count (klass)) {
10655 *iter = &klass->fields [0];
10656 return (MonoClassField *)*iter;
10662 field = (MonoClassField *)*iter;
10664 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10666 return (MonoClassField *)*iter;
10672 mono_class_full_name (MonoClass *klass)
10674 return mono_type_full_name (&klass->byval_arg);
10677 /* Declare all shared lazy type lookup functions */
10678 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10681 * mono_method_get_base_method:
10682 * \param method a method
10683 * \param definition if true, get the definition
10684 * \param error set on failure
10686 * Given a virtual method associated with a subclass, return the corresponding
10687 * method from an ancestor. If \p definition is FALSE, returns the method in the
10688 * superclass of the given method. If \p definition is TRUE, return the method
10689 * in the ancestor class where it was first declared. The type arguments will
10690 * be inflated in the ancestor classes. If the method is not associated with a
10691 * class, or isn't virtual, returns the method itself. On failure returns NULL
10692 * and sets \p error.
10695 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10697 MonoClass *klass, *parent;
10698 MonoGenericContext *generic_inst = NULL;
10699 MonoMethod *result = NULL;
10702 if (method->klass == NULL)
10705 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10706 MONO_CLASS_IS_INTERFACE (method->klass) ||
10707 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10710 slot = mono_method_get_vtable_slot (method);
10714 klass = method->klass;
10715 if (mono_class_is_ginst (klass)) {
10716 generic_inst = mono_class_get_context (klass);
10717 klass = mono_class_get_generic_class (klass)->container_class;
10722 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10723 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10724 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10725 or klass is the generic container class and generic_inst is the instantiation.
10727 when we go to the parent, if the parent is an open constructed type, we need to
10728 replace the type parameters by the definitions from the generic_inst, and then take it
10729 apart again into the klass and the generic_inst.
10731 For cases like this:
10732 class C<T> : B<T, int> {
10733 public override void Foo () { ... }
10735 class B<U,V> : A<HashMap<U,V>> {
10736 public override void Foo () { ... }
10739 public virtual void Foo () { ... }
10742 if at each iteration the parent isn't open, we can skip inflating it. if at some
10743 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10746 MonoGenericContext *parent_inst = NULL;
10747 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10748 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10749 return_val_if_nok (error, NULL);
10751 if (mono_class_is_ginst (parent)) {
10752 parent_inst = mono_class_get_context (parent);
10753 parent = mono_class_get_generic_class (parent)->container_class;
10756 mono_class_setup_vtable (parent);
10757 if (parent->vtable_size <= slot)
10760 generic_inst = parent_inst;
10763 klass = klass->parent;
10766 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10767 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10768 return_val_if_nok (error, NULL);
10770 generic_inst = NULL;
10772 if (mono_class_is_ginst (klass)) {
10773 generic_inst = mono_class_get_context (klass);
10774 klass = mono_class_get_generic_class (klass)->container_class;
10779 if (generic_inst) {
10780 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10781 return_val_if_nok (error, NULL);
10784 if (klass == method->klass)
10787 /*This is possible if definition == FALSE.
10788 * Do it here to be really sure we don't read invalid memory.
10790 if (slot >= klass->vtable_size)
10793 mono_class_setup_vtable (klass);
10795 result = klass->vtable [slot];
10796 if (result == NULL) {
10797 /* It is an abstract method */
10798 gboolean found = FALSE;
10799 gpointer iter = NULL;
10800 while ((result = mono_class_get_methods (klass, &iter))) {
10801 if (result->slot == slot) {
10806 /* found might be FALSE if we looked in an abstract class
10807 * that doesn't override an abstract method of its
10809 * abstract class Base {
10810 * public abstract void Foo ();
10812 * abstract class Derived : Base { }
10813 * class Child : Derived {
10814 * public override void Foo () { }
10817 * if m was Child.Foo and we ask for the base method,
10818 * then we get here with klass == Derived and found == FALSE
10820 /* but it shouldn't be the case that if we're looking
10821 * for the definition and didn't find a result; the
10822 * loop above should've taken us as far as we could
10824 g_assert (!(definition && !found));
10829 g_assert (result != NULL);