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_field_is_deleted (field))
1607 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1609 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1610 int offset = uoffset;
1612 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1613 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1616 if (offset < -1) { /*-1 is used to encode special static fields */
1617 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1620 if (mono_class_is_gtd (klass)) {
1621 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1625 if (mono_type_has_exceptions (field->type)) {
1626 char *class_name = mono_type_get_full_name (klass);
1627 char *type_name = mono_type_full_name (field->type);
1629 mono_class_set_type_load_failure (klass, "");
1630 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1631 g_free (class_name);
1635 /* The def_value of fields is compute lazily during vtable creation */
1638 if (!mono_class_has_failure (klass)) {
1639 mono_loader_lock ();
1640 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1641 mono_loader_unlock ();
1644 init_list = g_slist_remove (init_list, klass);
1645 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1649 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1652 mono_loader_lock ();
1653 klass->instance_size = cached_info->instance_size;
1654 klass->sizes.class_size = cached_info->class_size;
1655 klass->packing_size = cached_info->packing_size;
1656 klass->min_align = cached_info->min_align;
1657 klass->blittable = cached_info->blittable;
1658 klass->has_references = cached_info->has_references;
1659 klass->has_static_refs = cached_info->has_static_refs;
1660 klass->no_special_static_fields = cached_info->no_special_static_fields;
1661 mono_loader_unlock ();
1664 if (!klass->size_inited)
1665 mono_class_setup_fields (klass);
1670 * mono_class_init_sizes:
1672 * Initializes the size related fields of @klass without loading all field data if possible.
1673 * Sets the following fields in @klass:
1675 * - sizes.class_size
1682 * Can fail the class.
1684 * LOCKING: Acquires the loader lock.
1687 mono_class_init_sizes (MonoClass *klass)
1689 MonoCachedClassInfo cached_info;
1690 gboolean has_cached_info;
1692 if (klass->size_inited)
1695 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1697 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1701 * mono_type_get_basic_type_from_generic:
1704 * Returns a closed type corresponding to the possibly open type
1708 mono_type_get_basic_type_from_generic (MonoType *type)
1710 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1711 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1712 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1713 return &mono_defaults.object_class->byval_arg;
1718 class_has_references (MonoClass *klass)
1720 mono_class_init_sizes (klass);
1723 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1724 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1727 return klass->has_references;
1731 type_has_references (MonoClass *klass, MonoType *ftype)
1733 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1735 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1736 MonoGenericParam *gparam = ftype->data.generic_param;
1738 if (gparam->gshared_constraint)
1739 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1745 * mono_class_layout_fields:
1747 * @base_instance_size: base instance size
1750 * This contains the common code for computing the layout of classes and sizes.
1751 * This should only be called from mono_class_setup_fields () and
1752 * typebuilder_setup_fields ().
1754 * LOCKING: Acquires the loader lock
1757 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1760 const int top = mono_class_get_field_count (klass);
1761 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1762 guint32 pass, passes, real_size;
1763 gboolean gc_aware_layout = FALSE;
1764 gboolean has_static_fields = FALSE;
1765 gboolean has_references = FALSE;
1766 gboolean has_static_refs = FALSE;
1767 MonoClassField *field;
1769 int instance_size = base_instance_size;
1770 int class_size, min_align;
1772 gboolean *fields_has_references;
1775 * We want to avoid doing complicated work inside locks, so we compute all the required
1776 * information and write it to @klass inside a lock.
1778 if (klass->fields_inited)
1781 if ((packing_size & 0xffffff00) != 0) {
1782 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1786 if (klass->parent) {
1787 min_align = klass->parent->min_align;
1788 /* we use | since it may have been set already */
1789 has_references = klass->has_references | klass->parent->has_references;
1793 /* We can't really enable 16 bytes alignment until the GC supports it.
1794 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1795 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1796 Bug #506144 is an example of this issue.
1798 if (klass->simd_type)
1803 * When we do generic sharing we need to have layout
1804 * information for open generic classes (either with a generic
1805 * context containing type variables or with a generic
1806 * container), so we don't return in that case anymore.
1809 if (klass->enumtype) {
1810 for (i = 0; i < top; i++) {
1811 field = &klass->fields [i];
1812 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1813 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1818 if (!mono_class_enum_basetype (klass)) {
1819 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1825 * Enable GC aware auto layout: in this mode, reference
1826 * fields are grouped together inside objects, increasing collector
1828 * Requires that all classes whose layout is known to native code be annotated
1829 * with [StructLayout (LayoutKind.Sequential)]
1830 * Value types have gc_aware_layout disabled by default, as per
1831 * what the default is for other runtimes.
1833 /* corlib is missing [StructLayout] directives in many places */
1834 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1835 if (!klass->valuetype)
1836 gc_aware_layout = TRUE;
1839 /* Compute klass->blittable */
1842 blittable = klass->parent->blittable;
1843 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1845 for (i = 0; i < top; i++) {
1846 field = &klass->fields [i];
1848 if (mono_field_is_deleted (field))
1850 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1853 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1856 MonoClass *field_class = mono_class_from_mono_type (field->type);
1858 mono_class_setup_fields (field_class);
1859 if (mono_class_has_failure (field_class)) {
1860 MonoError field_error;
1861 error_init (&field_error);
1862 mono_error_set_for_class_failure (&field_error, field_class);
1863 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1864 mono_error_cleanup (&field_error);
1868 if (!field_class || !field_class->blittable)
1872 if (klass->enumtype)
1873 blittable = klass->element_class->blittable;
1875 if (mono_class_has_failure (klass))
1877 if (klass == mono_defaults.string_class)
1880 /* Compute klass->has_references */
1882 * Process non-static fields first, since static fields might recursively
1883 * refer to the class itself.
1885 for (i = 0; i < top; i++) {
1888 field = &klass->fields [i];
1890 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1891 ftype = mono_type_get_underlying_type (field->type);
1892 ftype = mono_type_get_basic_type_from_generic (ftype);
1893 if (type_has_references (klass, ftype))
1894 has_references = TRUE;
1899 * Compute field layout and total size (not considering static fields)
1901 field_offsets = g_new0 (int, top);
1902 fields_has_references = g_new0 (gboolean, top);
1903 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1905 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1906 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1907 if (gc_aware_layout)
1912 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1915 if (klass->parent) {
1916 mono_class_setup_fields (klass->parent);
1917 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1919 real_size = klass->parent->instance_size;
1921 real_size = sizeof (MonoObject);
1924 for (pass = 0; pass < passes; ++pass) {
1925 for (i = 0; i < top; i++){
1930 field = &klass->fields [i];
1932 if (mono_field_is_deleted (field))
1934 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (gc_aware_layout) {
1940 fields_has_references [i] = type_has_references (klass, ftype);
1941 if (fields_has_references [i]) {
1950 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1951 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1952 /* This field is a hack inserted by MCS to empty structures */
1956 size = mono_type_size (field->type, &align);
1958 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1959 align = packing_size ? MIN (packing_size, align): align;
1960 /* if the field has managed references, we need to force-align it
1963 if (type_has_references (klass, ftype))
1964 align = MAX (align, sizeof (gpointer));
1966 min_align = MAX (align, min_align);
1967 field_offsets [i] = real_size;
1969 field_offsets [i] += align - 1;
1970 field_offsets [i] &= ~(align - 1);
1972 /*TypeBuilders produce all sort of weird things*/
1973 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1974 real_size = field_offsets [i] + size;
1977 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1978 if (klass->simd_type)
1979 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1980 instance_size = MAX (real_size, instance_size);
1982 if (instance_size & (min_align - 1)) {
1983 instance_size += min_align - 1;
1984 instance_size &= ~(min_align - 1);
1988 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1992 for (i = 0; i < top; i++) {
1997 field = &klass->fields [i];
2000 * There must be info about all the fields in a type if it
2001 * uses explicit layout.
2003 if (mono_field_is_deleted (field))
2005 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2008 size = mono_type_size (field->type, &align);
2009 align = packing_size ? MIN (packing_size, align): align;
2010 min_align = MAX (align, min_align);
2013 /* Already set by typebuilder_setup_fields () */
2014 field_offsets [i] = field->offset + sizeof (MonoObject);
2016 int idx = first_field_idx + i;
2018 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2019 field_offsets [i] = offset + sizeof (MonoObject);
2021 ftype = mono_type_get_underlying_type (field->type);
2022 ftype = mono_type_get_basic_type_from_generic (ftype);
2023 if (type_has_references (klass, ftype)) {
2024 if (field_offsets [i] % sizeof (gpointer)) {
2025 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2032 real_size = MAX (real_size, size + field_offsets [i]);
2035 if (klass->has_references) {
2036 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2038 /* Check for overlapping reference and non-reference fields */
2039 for (i = 0; i < top; i++) {
2042 field = &klass->fields [i];
2044 if (mono_field_is_deleted (field))
2046 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2048 ftype = mono_type_get_underlying_type (field->type);
2049 if (MONO_TYPE_IS_REFERENCE (ftype))
2050 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2052 for (i = 0; i < top; i++) {
2053 field = &klass->fields [i];
2055 if (mono_field_is_deleted (field))
2057 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2060 // FIXME: Too much code does this
2062 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2063 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]);
2067 g_free (ref_bitmap);
2070 instance_size = MAX (real_size, instance_size);
2071 if (instance_size & (min_align - 1)) {
2072 instance_size += min_align - 1;
2073 instance_size &= ~(min_align - 1);
2079 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2081 * This leads to all kinds of problems with nested structs, so only
2082 * enable it when a MONO_DEBUG property is set.
2084 * For small structs, set min_align to at least the struct size to improve
2085 * performance, and since the JIT memset/memcpy code assumes this and generates
2086 * unaligned accesses otherwise. See #78990 for a testcase.
2088 if (mono_align_small_structs && top) {
2089 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2090 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2094 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2095 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2096 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2097 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2099 /* Publish the data */
2100 mono_loader_lock ();
2101 if (klass->instance_size && !klass->image->dynamic) {
2102 /* Might be already set using cached info */
2103 if (klass->instance_size != instance_size) {
2104 /* Emit info to help debugging */
2105 g_print ("%s\n", mono_class_full_name (klass));
2106 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2107 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2108 g_print ("%d %d\n", klass->min_align, min_align);
2109 for (i = 0; i < top; ++i) {
2110 field = &klass->fields [i];
2111 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2112 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2115 g_assert (klass->instance_size == instance_size);
2117 klass->instance_size = instance_size;
2119 klass->blittable = blittable;
2120 klass->has_references = has_references;
2121 klass->packing_size = packing_size;
2122 klass->min_align = min_align;
2123 for (i = 0; i < top; ++i) {
2124 field = &klass->fields [i];
2125 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2126 klass->fields [i].offset = field_offsets [i];
2129 mono_memory_barrier ();
2130 klass->size_inited = 1;
2131 mono_loader_unlock ();
2134 * Compute static field layout and size
2135 * Static fields can reference the class itself, so this has to be
2136 * done after instance_size etc. are initialized.
2139 for (i = 0; i < top; i++) {
2143 field = &klass->fields [i];
2145 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2147 if (mono_field_is_deleted (field))
2150 if (mono_type_has_exceptions (field->type)) {
2151 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2155 has_static_fields = TRUE;
2157 size = mono_type_size (field->type, &align);
2158 field_offsets [i] = class_size;
2159 /*align is always non-zero here*/
2160 field_offsets [i] += align - 1;
2161 field_offsets [i] &= ~(align - 1);
2162 class_size = field_offsets [i] + size;
2165 if (has_static_fields && class_size == 0)
2166 /* Simplify code which depends on class_size != 0 if the class has static fields */
2169 /* Compute klass->has_static_refs */
2170 has_static_refs = FALSE;
2171 for (i = 0; i < top; i++) {
2174 field = &klass->fields [i];
2176 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2177 ftype = mono_type_get_underlying_type (field->type);
2178 ftype = mono_type_get_basic_type_from_generic (ftype);
2179 if (type_has_references (klass, ftype))
2180 has_static_refs = TRUE;
2184 /*valuetypes can't be neither bigger than 1Mb or empty. */
2185 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2186 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2188 /* Publish the data */
2189 mono_loader_lock ();
2191 klass->sizes.class_size = class_size;
2192 klass->has_static_refs = has_static_refs;
2193 for (i = 0; i < top; ++i) {
2194 field = &klass->fields [i];
2196 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2197 field->offset = field_offsets [i];
2200 mono_memory_barrier ();
2201 klass->fields_inited = 1;
2202 mono_loader_unlock ();
2204 g_free (field_offsets);
2205 g_free (fields_has_references);
2209 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2213 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2214 method->klass = klass;
2215 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2216 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2217 method->signature = sig;
2218 method->name = name;
2221 if (name [0] == '.') {
2222 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2224 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2230 * mono_class_setup_methods:
2233 * Initializes the 'methods' array in CLASS.
2234 * Calling this method should be avoided if possible since it allocates a lot
2235 * of long-living MonoMethod structures.
2236 * Methods belonging to an interface are assigned a sequential slot starting
2239 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2242 mono_class_setup_methods (MonoClass *klass)
2245 MonoMethod **methods;
2250 if (mono_class_is_ginst (klass)) {
2252 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2254 mono_class_init (gklass);
2255 if (!mono_class_has_failure (gklass))
2256 mono_class_setup_methods (gklass);
2257 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2260 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2261 count = mono_class_get_method_count (gklass);
2262 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2264 for (i = 0; i < count; i++) {
2265 methods [i] = mono_class_inflate_generic_method_full_checked (
2266 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2267 if (!mono_error_ok (&error)) {
2268 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2269 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2272 mono_error_cleanup (&error);
2276 } else if (klass->rank) {
2278 MonoMethod *amethod;
2279 MonoMethodSignature *sig;
2280 int count_generic = 0, first_generic = 0;
2282 gboolean jagged_ctor = FALSE;
2284 count = 3 + (klass->rank > 1? 2: 1);
2286 mono_class_setup_interfaces (klass, &error);
2287 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2289 if (klass->rank == 1 && klass->element_class->rank) {
2294 if (klass->interface_count) {
2295 count_generic = generic_array_methods (klass);
2296 first_generic = count;
2297 count += klass->interface_count * count_generic;
2300 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2302 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2303 sig->ret = &mono_defaults.void_class->byval_arg;
2304 sig->pinvoke = TRUE;
2305 sig->hasthis = TRUE;
2306 for (i = 0; i < klass->rank; ++i)
2307 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2309 amethod = create_array_method (klass, ".ctor", sig);
2310 methods [method_num++] = amethod;
2311 if (klass->rank > 1) {
2312 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2313 sig->ret = &mono_defaults.void_class->byval_arg;
2314 sig->pinvoke = TRUE;
2315 sig->hasthis = TRUE;
2316 for (i = 0; i < klass->rank * 2; ++i)
2317 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2319 amethod = create_array_method (klass, ".ctor", sig);
2320 methods [method_num++] = amethod;
2324 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2325 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2326 sig->ret = &mono_defaults.void_class->byval_arg;
2327 sig->pinvoke = TRUE;
2328 sig->hasthis = TRUE;
2329 for (i = 0; i < klass->rank + 1; ++i)
2330 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2331 amethod = create_array_method (klass, ".ctor", sig);
2332 methods [method_num++] = amethod;
2335 /* element Get (idx11, [idx2, ...]) */
2336 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2337 sig->ret = &klass->element_class->byval_arg;
2338 sig->pinvoke = TRUE;
2339 sig->hasthis = TRUE;
2340 for (i = 0; i < klass->rank; ++i)
2341 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2342 amethod = create_array_method (klass, "Get", sig);
2343 methods [method_num++] = amethod;
2344 /* element& Address (idx11, [idx2, ...]) */
2345 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2346 sig->ret = &klass->element_class->this_arg;
2347 sig->pinvoke = TRUE;
2348 sig->hasthis = TRUE;
2349 for (i = 0; i < klass->rank; ++i)
2350 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2351 amethod = create_array_method (klass, "Address", sig);
2352 methods [method_num++] = amethod;
2353 /* void Set (idx11, [idx2, ...], element) */
2354 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2355 sig->ret = &mono_defaults.void_class->byval_arg;
2356 sig->pinvoke = TRUE;
2357 sig->hasthis = TRUE;
2358 for (i = 0; i < klass->rank; ++i)
2359 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2360 sig->params [i] = &klass->element_class->byval_arg;
2361 amethod = create_array_method (klass, "Set", sig);
2362 methods [method_num++] = amethod;
2364 GHashTable *cache = g_hash_table_new (NULL, NULL);
2365 for (i = 0; i < klass->interface_count; i++)
2366 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2367 g_hash_table_destroy (cache);
2368 } else if (mono_class_has_static_metadata (klass)) {
2370 int first_idx = mono_class_get_first_method_idx (klass);
2372 count = mono_class_get_method_count (klass);
2373 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2374 for (i = 0; i < count; ++i) {
2375 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2376 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2378 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2379 mono_error_cleanup (&error);
2383 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2387 if (MONO_CLASS_IS_INTERFACE (klass)) {
2389 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2390 for (i = 0; i < count; ++i) {
2391 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2392 methods [i]->slot = slot++;
2396 mono_image_lock (klass->image);
2398 if (!klass->methods) {
2399 mono_class_set_method_count (klass, count);
2401 /* Needed because of the double-checking locking pattern */
2402 mono_memory_barrier ();
2404 klass->methods = methods;
2407 mono_image_unlock (klass->image);
2411 * mono_class_get_method_by_index:
2413 * Returns klass->methods [index], initializing klass->methods if neccesary.
2415 * LOCKING: Acquires the loader lock.
2418 mono_class_get_method_by_index (MonoClass *klass, int index)
2422 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2423 /* Avoid calling setup_methods () if possible */
2424 if (gklass && !klass->methods) {
2427 m = mono_class_inflate_generic_method_full_checked (
2428 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2429 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2431 * If setup_methods () is called later for this class, no duplicates are created,
2432 * since inflate_generic_method guarantees that only one instance of a method
2433 * is created for each context.
2436 mono_class_setup_methods (klass);
2437 g_assert (m == klass->methods [index]);
2441 mono_class_setup_methods (klass);
2442 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2444 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2445 return klass->methods [index];
2450 * mono_class_get_inflated_method:
2452 * Given an inflated class CLASS and a method METHOD which should be a method of
2453 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2456 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2458 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2461 g_assert (method->klass == gklass);
2463 mono_class_setup_methods (gklass);
2464 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2466 mcount = mono_class_get_method_count (gklass);
2467 for (i = 0; i < mcount; ++i) {
2468 if (gklass->methods [i] == method) {
2469 if (klass->methods) {
2470 return klass->methods [i];
2473 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2474 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2484 * mono_class_get_vtable_entry:
2486 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2487 * LOCKING: Acquires the loader lock.
2490 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2494 if (klass->rank == 1) {
2496 * szarrays do not overwrite any methods of Array, so we can avoid
2497 * initializing their vtables in some cases.
2499 mono_class_setup_vtable (klass->parent);
2500 if (offset < klass->parent->vtable_size)
2501 return klass->parent->vtable [offset];
2504 if (mono_class_is_ginst (klass)) {
2506 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2507 mono_class_setup_vtable (gklass);
2508 m = gklass->vtable [offset];
2510 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2511 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2513 mono_class_setup_vtable (klass);
2514 if (mono_class_has_failure (klass))
2516 m = klass->vtable [offset];
2523 * mono_class_get_vtable_size:
2525 * Return the vtable size for KLASS.
2528 mono_class_get_vtable_size (MonoClass *klass)
2530 mono_class_setup_vtable (klass);
2532 return klass->vtable_size;
2536 * mono_class_setup_properties:
2538 * Initialize klass->ext.property and klass->ext.properties.
2540 * This method can fail the class.
2543 mono_class_setup_properties (MonoClass *klass)
2545 guint startm, endm, i, j;
2546 guint32 cols [MONO_PROPERTY_SIZE];
2547 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2548 MonoProperty *properties;
2551 MonoClassPropertyInfo *info;
2553 info = mono_class_get_property_info (klass);
2557 if (mono_class_is_ginst (klass)) {
2558 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2560 mono_class_init (gklass);
2561 mono_class_setup_properties (gklass);
2562 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2565 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2566 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2568 for (i = 0; i < ginfo->count; i++) {
2570 MonoProperty *prop = &properties [i];
2572 *prop = ginfo->properties [i];
2575 prop->get = mono_class_inflate_generic_method_full_checked (
2576 prop->get, klass, mono_class_get_context (klass), &error);
2578 prop->set = mono_class_inflate_generic_method_full_checked (
2579 prop->set, klass, mono_class_get_context (klass), &error);
2581 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2582 prop->parent = klass;
2585 first = ginfo->first;
2586 count = ginfo->count;
2588 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2589 count = last - first;
2592 mono_class_setup_methods (klass);
2593 if (mono_class_has_failure (klass))
2597 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2598 for (i = first; i < last; ++i) {
2599 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2600 properties [i - first].parent = klass;
2601 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2602 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2604 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2605 int first_idx = mono_class_get_first_method_idx (klass);
2606 for (j = startm; j < endm; ++j) {
2609 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2611 if (klass->image->uncompressed_metadata) {
2613 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2614 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2615 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2617 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2620 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2621 case METHOD_SEMANTIC_SETTER:
2622 properties [i - first].set = method;
2624 case METHOD_SEMANTIC_GETTER:
2625 properties [i - first].get = method;
2634 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2635 info->first = first;
2636 info->count = count;
2637 info->properties = properties;
2638 mono_memory_barrier ();
2640 /* This might leak 'info' which was allocated from the image mempool */
2641 mono_class_set_property_info (klass, info);
2645 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2647 MonoMethod **om, **retval;
2650 for (om = methods, count = 0; *om; ++om, ++count)
2653 retval = g_new0 (MonoMethod*, count + 1);
2655 for (om = methods, count = 0; *om; ++om, ++count) {
2657 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2658 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2664 /*This method can fail the class.*/
2666 mono_class_setup_events (MonoClass *klass)
2669 guint startm, endm, i, j;
2670 guint32 cols [MONO_EVENT_SIZE];
2671 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2675 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2679 if (mono_class_is_ginst (klass)) {
2680 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2681 MonoGenericContext *context = NULL;
2683 mono_class_setup_events (gklass);
2684 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2687 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2688 first = ginfo->first;
2689 count = ginfo->count;
2691 events = mono_class_new0 (klass, MonoEvent, count);
2694 context = mono_class_get_context (klass);
2696 for (i = 0; i < count; i++) {
2698 MonoEvent *event = &events [i];
2699 MonoEvent *gevent = &ginfo->events [i];
2701 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2703 event->parent = klass;
2704 event->name = gevent->name;
2705 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2706 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2707 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2709 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2710 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2712 #ifndef MONO_SMALL_CONFIG
2713 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2715 event->attrs = gevent->attrs;
2718 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2719 count = last - first;
2722 mono_class_setup_methods (klass);
2723 if (mono_class_has_failure (klass)) {
2728 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2729 for (i = first; i < last; ++i) {
2730 MonoEvent *event = &events [i - first];
2732 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2733 event->parent = klass;
2734 event->attrs = cols [MONO_EVENT_FLAGS];
2735 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2737 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2738 int first_idx = mono_class_get_first_method_idx (klass);
2739 for (j = startm; j < endm; ++j) {
2742 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2744 if (klass->image->uncompressed_metadata) {
2746 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2747 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2748 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2750 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2753 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2754 case METHOD_SEMANTIC_ADD_ON:
2755 event->add = method;
2757 case METHOD_SEMANTIC_REMOVE_ON:
2758 event->remove = method;
2760 case METHOD_SEMANTIC_FIRE:
2761 event->raise = method;
2763 case METHOD_SEMANTIC_OTHER: {
2764 #ifndef MONO_SMALL_CONFIG
2767 if (event->other == NULL) {
2768 event->other = g_new0 (MonoMethod*, 2);
2770 while (event->other [n])
2772 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2774 event->other [n] = method;
2775 /* NULL terminated */
2776 event->other [n + 1] = NULL;
2787 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2788 info->events = events;
2789 info->first = first;
2790 info->count = count;
2792 mono_memory_barrier ();
2794 mono_class_set_event_info (klass, info);
2798 * Global pool of interface IDs, represented as a bitset.
2799 * LOCKING: Protected by the classes lock.
2801 static MonoBitSet *global_interface_bitset = NULL;
2804 * mono_unload_interface_ids:
2805 * @bitset: bit set of interface IDs
2807 * When an image is unloaded, the interface IDs associated with
2808 * the image are put back in the global pool of IDs so the numbers
2812 mono_unload_interface_ids (MonoBitSet *bitset)
2815 mono_bitset_sub (global_interface_bitset, bitset);
2820 mono_unload_interface_id (MonoClass *klass)
2822 if (global_interface_bitset && klass->interface_id) {
2824 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2830 * mono_get_unique_iid:
2831 * \param klass interface
2833 * Assign a unique integer ID to the interface represented by \p klass.
2834 * The ID will positive and as small as possible.
2835 * LOCKING: Acquires the classes lock.
2836 * \returns The new ID.
2839 mono_get_unique_iid (MonoClass *klass)
2843 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2847 if (!global_interface_bitset) {
2848 global_interface_bitset = mono_bitset_new (128, 0);
2851 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2853 int old_size = mono_bitset_size (global_interface_bitset);
2854 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2855 mono_bitset_free (global_interface_bitset);
2856 global_interface_bitset = new_set;
2859 mono_bitset_set (global_interface_bitset, iid);
2860 /* set the bit also in the per-image set */
2861 if (!mono_class_is_ginst (klass)) {
2862 if (klass->image->interface_bitset) {
2863 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2864 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2865 mono_bitset_free (klass->image->interface_bitset);
2866 klass->image->interface_bitset = new_set;
2869 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2871 mono_bitset_set (klass->image->interface_bitset, iid);
2876 #ifndef MONO_SMALL_CONFIG
2877 if (mono_print_vtable) {
2879 char *type_name = mono_type_full_name (&klass->byval_arg);
2880 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2881 if (gklass && !gklass->context.class_inst->is_open) {
2882 generic_id = gklass->context.class_inst->id;
2883 g_assert (generic_id != 0);
2887 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2892 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2893 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2894 g_assert (iid < INT_MAX);
2899 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2904 mono_class_setup_interfaces (klass, error);
2905 return_if_nok (error);
2907 for (i = 0; i < klass->interface_count; i++) {
2908 ic = klass->interfaces [i];
2911 *res = g_ptr_array_new ();
2912 if (*ifaces == NULL)
2913 *ifaces = g_hash_table_new (NULL, NULL);
2914 if (g_hash_table_lookup (*ifaces, ic))
2916 g_ptr_array_add (*res, ic);
2917 g_hash_table_insert (*ifaces, ic, ic);
2918 mono_class_init (ic);
2919 if (mono_class_has_failure (ic)) {
2920 mono_error_set_type_load_class (error, ic, "Error Loading class");
2924 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2925 return_if_nok (error);
2930 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2932 GPtrArray *res = NULL;
2933 GHashTable *ifaces = NULL;
2935 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2937 g_hash_table_destroy (ifaces);
2938 if (!mono_error_ok (error)) {
2940 g_ptr_array_free (res, TRUE);
2947 compare_interface_ids (const void *p_key, const void *p_element)
2949 const MonoClass *key = (const MonoClass *)p_key;
2950 const MonoClass *element = *(const MonoClass **)p_element;
2952 return (key->interface_id - element->interface_id);
2955 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2957 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2959 MonoClass **result = (MonoClass **)mono_binary_search (
2961 klass->interfaces_packed,
2962 klass->interface_offsets_count,
2963 sizeof (MonoClass *),
2964 compare_interface_ids);
2966 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2973 * mono_class_interface_offset_with_variance:
2975 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2976 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2978 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2980 * FIXME figure out MS disambiguation rules and fix this function.
2983 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2985 int i = mono_class_interface_offset (klass, itf);
2986 *non_exact_match = FALSE;
2990 if (itf->is_array_special_interface && klass->rank < 2) {
2991 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2993 for (i = 0; i < klass->interface_offsets_count; i++) {
2994 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2995 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2996 *non_exact_match = TRUE;
2997 return klass->interface_offsets_packed [i];
3002 if (!mono_class_has_variant_generic_params (itf))
3005 for (i = 0; i < klass->interface_offsets_count; i++) {
3006 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3007 *non_exact_match = TRUE;
3008 return klass->interface_offsets_packed [i];
3016 print_implemented_interfaces (MonoClass *klass)
3020 GPtrArray *ifaces = NULL;
3022 int ancestor_level = 0;
3024 name = mono_type_get_full_name (klass);
3025 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3028 for (i = 0; i < klass->interface_offsets_count; i++)
3029 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3030 klass->interfaces_packed [i]->interface_id,
3031 klass->interface_offsets_packed [i],
3032 mono_class_get_method_count (klass->interfaces_packed [i]),
3033 klass->interfaces_packed [i]->name_space,
3034 klass->interfaces_packed [i]->name );
3035 printf ("Interface flags: ");
3036 for (i = 0; i <= klass->max_interface_id; i++)
3037 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3038 printf ("(%d,T)", i);
3040 printf ("(%d,F)", i);
3042 printf ("Dump interface flags:");
3043 #ifdef COMPRESSED_INTERFACE_BITMAP
3045 const uint8_t* p = klass->interface_bitmap;
3046 i = klass->max_interface_id;
3048 printf (" %d x 00 %02X", p [0], p [1]);
3054 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3055 printf (" %02X", klass->interface_bitmap [i]);
3058 while (klass != NULL) {
3059 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3060 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3061 if (!mono_error_ok (&error)) {
3062 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3063 mono_error_cleanup (&error);
3064 } else if (ifaces) {
3065 for (i = 0; i < ifaces->len; i++) {
3066 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3067 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3068 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3070 mono_class_interface_offset (klass, ic),
3071 mono_class_get_method_count (ic),
3075 g_ptr_array_free (ifaces, TRUE);
3078 klass = klass->parent;
3083 * Return the number of virtual methods.
3084 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3085 * Return -1 on failure.
3086 * FIXME It would be nice if this information could be cached somewhere.
3089 count_virtual_methods (MonoClass *klass)
3091 int i, mcount, vcount = 0;
3093 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3095 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3096 mono_class_setup_methods (klass);
3097 if (mono_class_has_failure (klass))
3100 mcount = mono_class_get_method_count (klass);
3101 for (i = 0; i < mcount; ++i) {
3102 flags = klass->methods [i]->flags;
3103 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3107 int first_idx = mono_class_get_first_method_idx (klass);
3108 mcount = mono_class_get_method_count (klass);
3109 for (i = 0; i < mcount; ++i) {
3110 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3112 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3120 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3128 m = (l + num_ifaces) / 2;
3129 if (interfaces_full [m] == ic)
3131 if (l == num_ifaces)
3133 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3142 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3144 int i = find_interface (num_ifaces, interfaces_full, ic);
3148 interface_offsets_full [i] = offset;
3151 for (i = 0; i < num_ifaces; ++i) {
3152 if (interfaces_full [i]) {
3154 if (interfaces_full [i]->interface_id < ic->interface_id)
3157 while (end < num_ifaces && interfaces_full [end]) end++;
3158 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3159 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3161 interfaces_full [i] = ic;
3162 interface_offsets_full [i] = offset;
3168 #ifdef COMPRESSED_INTERFACE_BITMAP
3171 * Compressed interface bitmap design.
3173 * Interface bitmaps take a large amount of memory, because their size is
3174 * linear with the maximum interface id assigned in the process (each interface
3175 * is assigned a unique id as it is loaded). The number of interface classes
3176 * is high because of the many implicit interfaces implemented by arrays (we'll
3177 * need to lazy-load them in the future).
3178 * Most classes implement a very small number of interfaces, so the bitmap is
3179 * sparse. This bitmap needs to be checked by interface casts, so access to the
3180 * needed bit must be fast and doable with few jit instructions.
3182 * The current compression format is as follows:
3183 * *) it is a sequence of one or more two-byte elements
3184 * *) the first byte in the element is the count of empty bitmap bytes
3185 * at the current bitmap position
3186 * *) the second byte in the element is an actual bitmap byte at the current
3189 * As an example, the following compressed bitmap bytes:
3190 * 0x07 0x01 0x00 0x7
3191 * correspond to the following bitmap:
3192 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3194 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3195 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3196 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3200 * mono_compress_bitmap:
3201 * \param dest destination buffer
3202 * \param bitmap bitmap buffer
3203 * \param size size of \p bitmap in bytes
3205 * This is a mono internal function.
3206 * The \p bitmap data is compressed into a format that is small but
3207 * still searchable in few instructions by the JIT and runtime.
3208 * The compressed data is stored in the buffer pointed to by the
3209 * \p dest array. Passing a NULL value for \p dest allows to just compute
3210 * the size of the buffer.
3211 * This compression algorithm assumes the bits set in the bitmap are
3212 * few and far between, like in interface bitmaps.
3213 * \returns The size of the compressed bitmap in bytes.
3216 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3220 const uint8_t *end = bitmap + size;
3221 while (bitmap < end) {
3222 if (*bitmap || numz == 255) {
3246 * mono_class_interface_match:
3247 * \param bitmap a compressed bitmap buffer
3248 * \param id the index to check in the bitmap
3250 * This is a mono internal function.
3251 * Checks if a bit is set in a compressed interface bitmap. \p id must
3252 * be already checked for being smaller than the maximum id encoded in the
3255 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3259 mono_class_interface_match (const uint8_t *bitmap, int id)
3262 id -= bitmap [0] * 8;
3266 return bitmap [1] & (1 << id);
3275 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3276 * LOCKING: Acquires the loader lock.
3279 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3283 int i, j, num_ifaces;
3285 MonoClass **interfaces_full = NULL;
3286 int *interface_offsets_full = NULL;
3288 GPtrArray **ifaces_array = NULL;
3289 int interface_offsets_count;
3291 mono_loader_lock ();
3293 mono_class_setup_supertypes (klass);
3295 /* compute maximum number of slots and maximum interface id */
3297 num_ifaces = 0; /* this can include duplicated ones */
3298 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3299 for (j = 0; j < klass->idepth; j++) {
3300 k = klass->supertypes [j];
3302 num_ifaces += k->interface_count;
3303 for (i = 0; i < k->interface_count; i++) {
3304 ic = k->interfaces [i];
3306 mono_class_init (ic);
3308 if (max_iid < ic->interface_id)
3309 max_iid = ic->interface_id;
3311 ifaces = mono_class_get_implemented_interfaces (k, &error);
3312 if (!mono_error_ok (&error)) {
3313 char *name = mono_type_get_full_name (k);
3314 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3316 mono_error_cleanup (&error);
3321 num_ifaces += ifaces->len;
3322 for (i = 0; i < ifaces->len; ++i) {
3323 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3324 if (max_iid < ic->interface_id)
3325 max_iid = ic->interface_id;
3327 ifaces_array [j] = ifaces;
3331 if (MONO_CLASS_IS_INTERFACE (klass)) {
3333 if (max_iid < klass->interface_id)
3334 max_iid = klass->interface_id;
3337 /* compute vtable offset for interfaces */
3338 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3339 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3341 for (i = 0; i < num_ifaces; i++)
3342 interface_offsets_full [i] = -1;
3344 /* skip the current class */
3345 for (j = 0; j < klass->idepth - 1; j++) {
3346 k = klass->supertypes [j];
3347 ifaces = ifaces_array [j];
3350 for (i = 0; i < ifaces->len; ++i) {
3352 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3354 /*Force the sharing of interface offsets between parent and subtypes.*/
3355 io = mono_class_interface_offset (k, ic);
3357 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3362 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3363 ifaces = ifaces_array [klass->idepth - 1];
3365 for (i = 0; i < ifaces->len; ++i) {
3367 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3368 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3370 count = count_virtual_methods (ic);
3372 char *name = mono_type_get_full_name (ic);
3373 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3382 if (MONO_CLASS_IS_INTERFACE (klass))
3383 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3385 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3386 if (interface_offsets_full [i] != -1)
3387 interface_offsets_count ++;
3390 /* Publish the data */
3391 klass->max_interface_id = max_iid;
3393 * We might get called multiple times:
3394 * - mono_class_init ()
3395 * - mono_class_setup_vtable ().
3396 * - mono_class_setup_interface_offsets ().
3397 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3398 * means we have to overwrite those when called from other places (#4440).
3400 if (klass->interfaces_packed) {
3402 g_assert (klass->interface_offsets_count == interface_offsets_count);
3406 klass->interface_offsets_count = interface_offsets_count;
3407 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3408 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3409 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3410 #ifdef COMPRESSED_INTERFACE_BITMAP
3411 bitmap = g_malloc0 (bsize);
3413 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3415 for (i = 0; i < interface_offsets_count; i++) {
3416 guint32 id = interfaces_full [i]->interface_id;
3417 bitmap [id >> 3] |= (1 << (id & 7));
3418 klass->interfaces_packed [i] = interfaces_full [i];
3419 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3421 #ifdef COMPRESSED_INTERFACE_BITMAP
3422 i = mono_compress_bitmap (NULL, bitmap, bsize);
3423 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3424 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3427 klass->interface_bitmap = bitmap;
3431 mono_loader_unlock ();
3433 g_free (interfaces_full);
3434 g_free (interface_offsets_full);
3435 for (i = 0; i < klass->idepth; i++) {
3436 ifaces = ifaces_array [i];
3438 g_ptr_array_free (ifaces, TRUE);
3440 g_free (ifaces_array);
3442 //printf ("JUST DONE: ");
3443 //print_implemented_interfaces (klass);
3449 * Setup interface offsets for interfaces.
3451 * - klass->max_interface_id
3452 * - klass->interface_offsets_count
3453 * - klass->interfaces_packed
3454 * - klass->interface_offsets_packed
3455 * - klass->interface_bitmap
3457 * This function can fail @class.
3460 mono_class_setup_interface_offsets (MonoClass *klass)
3462 setup_interface_offsets (klass, 0, FALSE);
3465 /*Checks if @klass has @parent as one of it's parents type gtd
3469 * Bar<T> : Foo<Bar<Bar<T>>>
3473 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3475 klass = mono_class_get_generic_type_definition (klass);
3476 parent = mono_class_get_generic_type_definition (parent);
3477 mono_class_setup_supertypes (klass);
3478 mono_class_setup_supertypes (parent);
3480 return klass->idepth >= parent->idepth &&
3481 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3485 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3487 MonoGenericInst *ginst;
3490 if (!mono_class_is_ginst (klass)) {
3491 mono_class_setup_vtable_full (klass, in_setup);
3492 return !mono_class_has_failure (klass);
3495 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3496 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3499 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3500 for (i = 0; i < ginst->type_argc; ++i) {
3502 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3504 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3505 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3506 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3508 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3509 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3517 * mono_class_setup_vtable:
3519 * Creates the generic vtable of CLASS.
3520 * Initializes the following fields in MonoClass:
3523 * Plus all the fields initialized by setup_interface_offsets ().
3524 * If there is an error during vtable construction, klass->has_failure
3525 * is set and details are stored in a MonoErrorBoxed.
3527 * LOCKING: Acquires the loader lock.
3530 mono_class_setup_vtable (MonoClass *klass)
3532 mono_class_setup_vtable_full (klass, NULL);
3536 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3539 MonoMethod **overrides;
3540 MonoGenericContext *context;
3548 if (MONO_CLASS_IS_INTERFACE (klass)) {
3549 /* This sets method->slot for all methods if this is an interface */
3550 mono_class_setup_methods (klass);
3554 if (mono_class_has_failure (klass))
3557 if (g_list_find (in_setup, klass))
3560 mono_loader_lock ();
3562 if (klass->vtable) {
3563 mono_loader_unlock ();
3567 mono_stats.generic_vtable_count ++;
3568 in_setup = g_list_prepend (in_setup, klass);
3570 if (mono_class_is_ginst (klass)) {
3571 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3572 mono_loader_unlock ();
3573 g_list_remove (in_setup, klass);
3577 context = mono_class_get_context (klass);
3578 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3580 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3581 type_token = klass->type_token;
3584 if (image_is_dynamic (klass->image)) {
3585 /* Generic instances can have zero method overrides without causing any harm.
3586 * This is true since we don't do layout all over again for them, we simply inflate
3587 * the layout of the parent.
3589 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3590 if (!is_ok (&error)) {
3591 mono_loader_unlock ();
3592 g_list_remove (in_setup, klass);
3593 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3594 mono_error_cleanup (&error);
3598 /* The following call fails if there are missing methods in the type */
3599 /* FIXME it's probably a good idea to avoid this for generic instances. */
3600 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3604 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3606 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3610 mono_loader_unlock ();
3611 g_list_remove (in_setup, klass);
3616 #define DEBUG_INTERFACE_VTABLE_CODE 0
3617 #define TRACE_INTERFACE_VTABLE_CODE 0
3618 #define VERIFY_INTERFACE_VTABLE_CODE 0
3619 #define VTABLE_SELECTOR (1)
3621 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3622 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3623 if (!(VTABLE_SELECTOR)) break; \
3627 #define DEBUG_INTERFACE_VTABLE(stmt)
3630 #if TRACE_INTERFACE_VTABLE_CODE
3631 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3632 if (!(VTABLE_SELECTOR)) break; \
3636 #define TRACE_INTERFACE_VTABLE(stmt)
3639 #if VERIFY_INTERFACE_VTABLE_CODE
3640 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3641 if (!(VTABLE_SELECTOR)) break; \
3645 #define VERIFY_INTERFACE_VTABLE(stmt)
3649 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3651 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3655 GString *res = g_string_new ("");
3657 g_string_append_c (res, '(');
3658 for (i = 0; i < sig->param_count; ++i) {
3660 g_string_append_c (res, ',');
3661 mono_type_get_desc (res, sig->params [i], include_namespace);
3663 g_string_append (res, ")=>");
3664 if (sig->ret != NULL) {
3665 mono_type_get_desc (res, sig->ret, include_namespace);
3667 g_string_append (res, "NULL");
3670 g_string_free (res, FALSE);
3674 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3675 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3676 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3677 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3685 is_wcf_hack_disabled (void)
3687 static gboolean disabled;
3688 static gboolean inited = FALSE;
3690 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3697 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3699 MonoMethodSignature *cmsig, *imsig;
3700 if (strcmp (im->name, cm->name) == 0) {
3701 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3702 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3705 if (! slot_is_empty) {
3706 if (require_newslot) {
3707 if (! interface_is_explicitly_implemented_by_class) {
3708 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3711 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3712 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3716 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3719 cmsig = mono_method_signature (cm);
3720 imsig = mono_method_signature (im);
3721 if (!cmsig || !imsig) {
3722 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3726 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3727 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3728 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3729 TRACE_INTERFACE_VTABLE (printf ("]"));
3732 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3733 if (mono_security_core_clr_enabled ())
3734 mono_security_core_clr_check_override (klass, cm, im);
3736 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3737 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3738 char *body_name = mono_method_full_name (cm, TRUE);
3739 char *decl_name = mono_method_full_name (im, TRUE);
3740 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3748 MonoClass *ic = im->klass;
3749 const char *ic_name_space = ic->name_space;
3750 const char *ic_name = ic->name;
3753 if (! require_newslot) {
3754 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3757 if (cm->klass->rank == 0) {
3758 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3761 cmsig = mono_method_signature (cm);
3762 imsig = mono_method_signature (im);
3763 if (!cmsig || !imsig) {
3764 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3768 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3769 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3770 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3771 TRACE_INTERFACE_VTABLE (printf ("]"));
3774 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3775 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3778 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3779 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3782 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))) {
3783 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3787 subname = strstr (cm->name, ic_name_space);
3788 if (subname != cm->name) {
3789 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3792 subname += strlen (ic_name_space);
3793 if (subname [0] != '.') {
3794 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3798 if (strstr (subname, ic_name) != subname) {
3799 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3802 subname += strlen (ic_name);
3803 if (subname [0] != '.') {
3804 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3808 if (strcmp (subname, im->name) != 0) {
3809 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3813 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3814 if (mono_security_core_clr_enabled ())
3815 mono_security_core_clr_check_override (klass, cm, im);
3817 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3818 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3819 char *body_name = mono_method_full_name (cm, TRUE);
3820 char *decl_name = mono_method_full_name (im, TRUE);
3821 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3831 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3833 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3834 MonoMethod *method = key;
3835 MonoMethod *override = value;
3836 MonoClass *method_class = mono_method_get_class (method);
3837 MonoClass *override_class = mono_method_get_class (override);
3839 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3840 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3841 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3844 print_overrides (GHashTable *override_map, const char *message) {
3846 printf ("Override map \"%s\" START:\n", message);
3847 g_hash_table_foreach (override_map, foreach_override, NULL);
3848 printf ("Override map \"%s\" END.\n", message);
3850 printf ("Override map \"%s\" EMPTY.\n", message);
3854 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3855 char *full_name = mono_type_full_name (&klass->byval_arg);
3859 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3861 if (print_interfaces) {
3862 print_implemented_interfaces (klass);
3863 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3866 if (klass->parent) {
3867 parent_size = klass->parent->vtable_size;
3871 for (i = 0; i < size; ++i) {
3872 MonoMethod *cm = vtable [i];
3873 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3874 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3876 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3884 #if VERIFY_INTERFACE_VTABLE_CODE
3886 mono_method_try_get_vtable_index (MonoMethod *method)
3888 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3889 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3890 if (imethod->declaring->is_generic)
3891 return imethod->declaring->slot;
3893 return method->slot;
3897 mono_class_verify_vtable (MonoClass *klass)
3900 char *full_name = mono_type_full_name (&klass->byval_arg);
3902 printf ("*** Verifying VTable of class '%s' \n", full_name);
3906 if (!klass->methods)
3909 count = mono_class_method_count (klass);
3910 for (i = 0; i < count; ++i) {
3911 MonoMethod *cm = klass->methods [i];
3914 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3918 full_name = mono_method_full_name (cm, TRUE);
3920 slot = mono_method_try_get_vtable_index (cm);
3922 if (slot >= klass->vtable_size) {
3923 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3927 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3928 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3929 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3930 g_free (other_name);
3933 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3940 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3943 char *method_signature;
3946 for (index = 0; index < onum; ++index) {
3947 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3948 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3950 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3951 type_name = mono_type_full_name (&klass->byval_arg);
3952 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3953 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3954 g_free (method_signature);
3956 mono_class_setup_methods (klass);
3957 if (mono_class_has_failure (klass)) {
3958 char *name = mono_type_get_full_name (klass);
3959 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3963 mcount = mono_class_get_method_count (klass);
3964 for (index = 0; index < mcount; ++index) {
3965 MonoMethod *cm = klass->methods [index];
3966 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3968 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3969 g_free (method_signature);
3974 mono_method_get_method_definition (MonoMethod *method)
3976 while (method->is_inflated)
3977 method = ((MonoMethodInflated*)method)->declaring;
3982 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3986 for (i = 0; i < onum; ++i) {
3987 MonoMethod *decl = overrides [i * 2];
3988 MonoMethod *body = overrides [i * 2 + 1];
3990 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3991 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3995 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3996 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3997 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
3999 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4003 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4004 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4005 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4007 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4011 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4012 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4016 body = mono_method_get_method_definition (body);
4017 decl = mono_method_get_method_definition (decl);
4019 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4020 char *body_name = mono_method_full_name (body, TRUE);
4021 char *decl_name = mono_method_full_name (decl, TRUE);
4022 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4032 mono_class_need_stelemref_method (MonoClass *klass)
4034 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4038 * LOCKING: this is supposed to be called with the loader lock held.
4041 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4045 MonoMethod **vtable = NULL;
4046 int i, max_vtsize = 0, cur_slot = 0;
4048 GPtrArray *ifaces = NULL;
4049 GHashTable *override_map = NULL;
4051 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4052 int first_non_interface_slot;
4054 GSList *virt_methods = NULL, *l;
4055 int stelemref_slot = 0;
4060 if (overrides && !verify_class_overrides (klass, overrides, onum))
4063 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4064 if (!mono_error_ok (&error)) {
4065 char *name = mono_type_get_full_name (klass);
4066 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4068 mono_error_cleanup (&error);
4070 } else if (ifaces) {
4071 for (i = 0; i < ifaces->len; i++) {
4072 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4073 max_vtsize += mono_class_get_method_count (ic);
4075 g_ptr_array_free (ifaces, TRUE);
4079 if (klass->parent) {
4080 mono_class_init (klass->parent);
4081 mono_class_setup_vtable_full (klass->parent, in_setup);
4083 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4086 max_vtsize += klass->parent->vtable_size;
4087 cur_slot = klass->parent->vtable_size;
4090 max_vtsize += mono_class_get_method_count (klass);
4092 /*Array have a slot for stelemref*/
4093 if (mono_class_need_stelemref_method (klass)) {
4094 stelemref_slot = cur_slot;
4099 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4101 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4102 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4105 max_iid = klass->max_interface_id;
4106 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4108 /* Optimized version for generic instances */
4109 if (mono_class_is_ginst (klass)) {
4111 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4114 mono_class_setup_vtable_full (gklass, in_setup);
4115 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4118 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4119 klass->vtable_size = gklass->vtable_size;
4120 for (i = 0; i < gklass->vtable_size; ++i)
4121 if (gklass->vtable [i]) {
4122 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4123 if (!mono_error_ok (&error)) {
4124 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4125 mono_error_cleanup (&error);
4129 tmp [i]->slot = gklass->vtable [i]->slot;
4131 mono_memory_barrier ();
4132 klass->vtable = tmp;
4134 /* Have to set method->slot for abstract virtual methods */
4135 if (klass->methods && gklass->methods) {
4136 int mcount = mono_class_get_method_count (klass);
4137 for (i = 0; i < mcount; ++i)
4138 if (klass->methods [i]->slot == -1)
4139 klass->methods [i]->slot = gklass->methods [i]->slot;
4145 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4147 if (klass->parent && klass->parent->vtable_size) {
4148 MonoClass *parent = klass->parent;
4151 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4153 // Also inherit parent interface vtables, just as a starting point.
4154 // This is needed otherwise bug-77127.exe fails when the property methods
4155 // have different names in the iterface and the class, because for child
4156 // classes the ".override" information is not used anymore.
4157 for (i = 0; i < parent->interface_offsets_count; i++) {
4158 MonoClass *parent_interface = parent->interfaces_packed [i];
4159 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4160 /*FIXME this is now dead code as this condition will never hold true.
4161 Since interface offsets are inherited then the offset of an interface implemented
4162 by a parent will never be the out of it's vtable boundary.
4164 if (interface_offset >= parent->vtable_size) {
4165 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4168 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4169 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4170 int mcount = mono_class_get_method_count (parent_interface);
4171 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4172 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4173 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4174 parent_interface_offset + j, parent_interface_offset, j,
4175 interface_offset + j, interface_offset, j));
4182 /*Array have a slot for stelemref*/
4183 if (mono_class_need_stelemref_method (klass)) {
4184 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4186 method->slot = stelemref_slot;
4188 g_assert (method->slot == stelemref_slot);
4190 vtable [stelemref_slot] = method;
4193 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4194 /* override interface methods */
4195 for (i = 0; i < onum; i++) {
4196 MonoMethod *decl = overrides [i*2];
4197 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4199 dslot = mono_method_get_vtable_slot (decl);
4201 mono_class_set_type_load_failure (klass, "");
4205 dslot += mono_class_interface_offset (klass, decl->klass);
4206 vtable [dslot] = overrides [i*2 + 1];
4207 vtable [dslot]->slot = dslot;
4209 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4211 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4213 if (mono_security_core_clr_enabled ())
4214 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4217 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4218 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4221 * Create a list of virtual methods to avoid calling
4222 * mono_class_get_virtual_methods () which is slow because of the metadata
4226 gpointer iter = NULL;
4229 virt_methods = NULL;
4230 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4231 virt_methods = g_slist_prepend (virt_methods, cm);
4233 if (mono_class_has_failure (klass))
4237 // Loop on all implemented interfaces...
4238 for (i = 0; i < klass->interface_offsets_count; i++) {
4239 MonoClass *parent = klass->parent;
4241 gboolean interface_is_explicitly_implemented_by_class;
4244 ic = klass->interfaces_packed [i];
4245 ic_offset = mono_class_interface_offset (klass, ic);
4247 mono_class_setup_methods (ic);
4248 if (mono_class_has_failure (ic))
4251 // Check if this interface is explicitly implemented (instead of just inherited)
4252 if (parent != NULL) {
4253 int implemented_interfaces_index;
4254 interface_is_explicitly_implemented_by_class = FALSE;
4255 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4256 if (ic == klass->interfaces [implemented_interfaces_index]) {
4257 interface_is_explicitly_implemented_by_class = TRUE;
4262 interface_is_explicitly_implemented_by_class = TRUE;
4265 // Loop on all interface methods...
4266 int mcount = mono_class_get_method_count (ic);
4267 for (im_index = 0; im_index < mcount; im_index++) {
4268 MonoMethod *im = ic->methods [im_index];
4269 int im_slot = ic_offset + im->slot;
4270 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4272 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4275 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4277 // If there is an explicit implementation, just use it right away,
4278 // otherwise look for a matching method
4279 if (override_im == NULL) {
4283 // First look for a suitable method among the class methods
4284 for (l = virt_methods; l; l = l->next) {
4285 cm = (MonoMethod *)l->data;
4286 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)));
4287 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4288 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4289 vtable [im_slot] = cm;
4290 /* Why do we need this? */
4295 TRACE_INTERFACE_VTABLE (printf ("\n"));
4296 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4300 // If the slot is still empty, look in all the inherited virtual methods...
4301 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4302 MonoClass *parent = klass->parent;
4303 // Reverse order, so that last added methods are preferred
4304 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4305 MonoMethod *cm = parent->vtable [cm_index];
4307 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));
4308 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4309 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4310 vtable [im_slot] = cm;
4311 /* Why do we need this? */
4317 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4319 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4323 g_assert (vtable [im_slot] == override_im);
4328 // If the class is not abstract, check that all its interface slots are full.
4329 // The check is done here and not directly at the end of the loop above because
4330 // it can happen (for injected generic array interfaces) that the same slot is
4331 // processed multiple times (those interfaces have overlapping slots), and it
4332 // will not always be the first pass the one that fills the slot.
4333 if (!mono_class_is_abstract (klass)) {
4334 for (i = 0; i < klass->interface_offsets_count; i++) {
4338 ic = klass->interfaces_packed [i];
4339 ic_offset = mono_class_interface_offset (klass, ic);
4341 int mcount = mono_class_get_method_count (ic);
4342 for (im_index = 0; im_index < mcount; im_index++) {
4343 MonoMethod *im = ic->methods [im_index];
4344 int im_slot = ic_offset + im->slot;
4346 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4349 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4350 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4351 if (vtable [im_slot] == NULL) {
4352 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4359 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4360 for (l = virt_methods; l; l = l->next) {
4361 cm = (MonoMethod *)l->data;
4363 * If the method is REUSE_SLOT, we must check in the
4364 * base class for a method to override.
4366 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4368 for (k = klass->parent; k ; k = k->parent) {
4373 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4374 MonoMethodSignature *cmsig, *m1sig;
4376 cmsig = mono_method_signature (cm);
4377 m1sig = mono_method_signature (m1);
4379 if (!cmsig || !m1sig) {
4380 /* FIXME proper error message */
4381 mono_class_set_type_load_failure (klass, "");
4385 if (!strcmp(cm->name, m1->name) &&
4386 mono_metadata_signature_equal (cmsig, m1sig)) {
4388 if (mono_security_core_clr_enabled ())
4389 mono_security_core_clr_check_override (klass, cm, m1);
4391 slot = mono_method_get_vtable_slot (m1);
4395 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4396 char *body_name = mono_method_full_name (cm, TRUE);
4397 char *decl_name = mono_method_full_name (m1, TRUE);
4398 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4404 g_assert (cm->slot < max_vtsize);
4406 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4407 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4408 mono_method_full_name (m1, 1), m1,
4409 mono_method_full_name (cm, 1), cm));
4410 g_hash_table_insert (override_map, m1, cm);
4414 if (mono_class_has_failure (k))
4424 /*Non final newslot methods must be given a non-interface vtable slot*/
4425 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4429 cm->slot = cur_slot++;
4431 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4432 vtable [cm->slot] = cm;
4435 /* override non interface methods */
4436 for (i = 0; i < onum; i++) {
4437 MonoMethod *decl = overrides [i*2];
4438 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4439 g_assert (decl->slot != -1);
4440 vtable [decl->slot] = overrides [i*2 + 1];
4441 overrides [i * 2 + 1]->slot = decl->slot;
4443 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4444 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4445 mono_method_full_name (decl, 1), decl,
4446 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4447 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4449 if (mono_security_core_clr_enabled ())
4450 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4455 * If a method occupies more than one place in the vtable, and it is
4456 * overriden, then change the other occurances too.
4461 for (i = 0; i < max_vtsize; ++i)
4463 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4465 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4470 g_hash_table_destroy (override_map);
4471 override_map = NULL;
4474 g_slist_free (virt_methods);
4475 virt_methods = NULL;
4477 g_assert (cur_slot <= max_vtsize);
4479 /* Ensure that all vtable slots are filled with concrete instance methods */
4480 if (!mono_class_is_abstract (klass)) {
4481 for (i = 0; i < cur_slot; ++i) {
4482 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4483 char *type_name = mono_type_get_full_name (klass);
4484 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4485 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4487 g_free (method_name);
4494 if (mono_class_is_ginst (klass)) {
4495 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4497 mono_class_init (gklass);
4499 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4501 /* Check that the vtable_size value computed in mono_class_init () is correct */
4502 if (klass->vtable_size)
4503 g_assert (cur_slot == klass->vtable_size);
4504 klass->vtable_size = cur_slot;
4507 /* Try to share the vtable with our parent. */
4508 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4509 mono_memory_barrier ();
4510 klass->vtable = klass->parent->vtable;
4512 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4513 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4514 mono_memory_barrier ();
4515 klass->vtable = tmp;
4518 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4519 if (mono_print_vtable) {
4522 print_implemented_interfaces (klass);
4524 for (i = 0; i <= max_iid; i++)
4525 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4528 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4529 klass->vtable_size, icount);
4531 for (i = 0; i < cur_slot; ++i) {
4536 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4537 mono_method_full_name (cm, TRUE));
4543 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4544 klass->name, max_iid);
4546 for (i = 0; i < klass->interface_count; i++) {
4547 ic = klass->interfaces [i];
4548 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4549 mono_class_interface_offset (klass, ic),
4550 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4553 for (k = klass->parent; k ; k = k->parent) {
4554 for (i = 0; i < k->interface_count; i++) {
4555 ic = k->interfaces [i];
4556 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4557 mono_class_interface_offset (klass, ic),
4558 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4566 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4571 char *name = mono_type_get_full_name (klass);
4572 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4576 g_hash_table_destroy (override_map);
4578 g_slist_free (virt_methods);
4583 * mono_method_get_vtable_slot:
4585 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4586 * LOCKING: Acquires the loader lock.
4588 * FIXME Use proper MonoError machinery here.
4591 mono_method_get_vtable_slot (MonoMethod *method)
4593 if (method->slot == -1) {
4594 mono_class_setup_vtable (method->klass);
4595 if (mono_class_has_failure (method->klass))
4597 if (method->slot == -1) {
4601 if (!mono_class_is_ginst (method->klass)) {
4602 g_assert (method->is_inflated);
4603 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4606 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4607 g_assert (mono_class_is_ginst (method->klass));
4608 gklass = mono_class_get_generic_class (method->klass)->container_class;
4609 mono_class_setup_methods (method->klass);
4610 g_assert (method->klass->methods);
4611 mcount = mono_class_get_method_count (method->klass);
4612 for (i = 0; i < mcount; ++i) {
4613 if (method->klass->methods [i] == method)
4616 g_assert (i < mcount);
4617 g_assert (gklass->methods);
4618 method->slot = gklass->methods [i]->slot;
4620 g_assert (method->slot != -1);
4622 return method->slot;
4626 * mono_method_get_vtable_index:
4627 * \param method a method
4629 * Returns the index into the runtime vtable to access the method or,
4630 * in the case of a virtual generic method, the virtual generic method
4631 * thunk. Returns -1 on failure.
4633 * FIXME Use proper MonoError machinery here.
4636 mono_method_get_vtable_index (MonoMethod *method)
4638 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4639 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4640 if (imethod->declaring->is_generic)
4641 return mono_method_get_vtable_slot (imethod->declaring);
4643 return mono_method_get_vtable_slot (method);
4646 static MonoMethod *default_ghc = NULL;
4647 static MonoMethod *default_finalize = NULL;
4648 static int finalize_slot = -1;
4649 static int ghc_slot = -1;
4652 initialize_object_slots (MonoClass *klass)
4657 if (klass == mono_defaults.object_class) {
4658 mono_class_setup_vtable (klass);
4659 for (i = 0; i < klass->vtable_size; ++i) {
4660 MonoMethod *cm = klass->vtable [i];
4662 if (!strcmp (cm->name, "GetHashCode"))
4664 else if (!strcmp (cm->name, "Finalize"))
4668 g_assert (ghc_slot > 0);
4669 default_ghc = klass->vtable [ghc_slot];
4671 g_assert (finalize_slot > 0);
4672 default_finalize = klass->vtable [finalize_slot];
4677 MonoMethod *array_method;
4679 } GenericArrayMethodInfo;
4681 static int generic_array_method_num = 0;
4682 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4685 generic_array_methods (MonoClass *klass)
4687 int i, count_generic = 0, mcount;
4688 GList *list = NULL, *tmp;
4689 if (generic_array_method_num)
4690 return generic_array_method_num;
4691 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4692 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4693 mcount = mono_class_get_method_count (klass->parent);
4694 for (i = 0; i < mcount; i++) {
4695 MonoMethod *m = klass->parent->methods [i];
4696 if (!strncmp (m->name, "InternalArray__", 15)) {
4698 list = g_list_prepend (list, m);
4701 list = g_list_reverse (list);
4702 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4704 for (tmp = list; tmp; tmp = tmp->next) {
4705 const char *mname, *iname;
4707 MonoMethod *m = (MonoMethod *)tmp->data;
4708 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4709 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4711 generic_array_method_info [i].array_method = m;
4712 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4713 iname = "System.Collections.Generic.ICollection`1.";
4714 mname = m->name + 27;
4715 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4716 iname = "System.Collections.Generic.IEnumerable`1.";
4717 mname = m->name + 27;
4718 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4719 iname = "System.Collections.Generic.IReadOnlyList`1.";
4720 mname = m->name + strlen (ireadonlylist_prefix);
4721 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4722 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4723 mname = m->name + strlen (ireadonlycollection_prefix);
4724 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4725 iname = "System.Collections.Generic.IList`1.";
4726 mname = m->name + 15;
4728 g_assert_not_reached ();
4731 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4732 strcpy (name, iname);
4733 strcpy (name + strlen (iname), mname);
4734 generic_array_method_info [i].name = name;
4737 /*g_print ("array generic methods: %d\n", count_generic);*/
4739 generic_array_method_num = count_generic;
4741 return generic_array_method_num;
4745 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4747 MonoGenericContext tmp_context;
4750 tmp_context.class_inst = NULL;
4751 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4752 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4754 for (i = 0; i < generic_array_method_num; i++) {
4756 MonoMethod *m = generic_array_method_info [i].array_method;
4757 MonoMethod *inflated, *helper;
4759 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4760 mono_error_assert_ok (&error);
4761 helper = g_hash_table_lookup (cache, inflated);
4763 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4764 g_hash_table_insert (cache, inflated, helper);
4766 methods [pos ++] = helper;
4771 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4773 int null_length = strlen ("(null)");
4774 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4775 char *s = (char *)mono_image_alloc (image, len);
4778 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4779 g_assert (result == len - 1);
4786 * \param klass the class to initialize
4788 * Compute the \c instance_size, \c class_size and other infos that cannot be
4789 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4790 * Initializes the following fields in \p klass:
4791 * - all the fields initialized by \c mono_class_init_sizes
4796 * LOCKING: Acquires the loader lock.
4798 * \returns TRUE on success or FALSE if there was a problem in loading
4799 * the type (incorrect assemblies, missing assemblies, methods, etc).
4802 mono_class_init (MonoClass *klass)
4804 int i, vtable_size = 0, array_method_count = 0;
4805 MonoCachedClassInfo cached_info;
4806 gboolean has_cached_info;
4807 gboolean locked = FALSE;
4808 gboolean ghcimpl = FALSE;
4809 gboolean has_cctor = FALSE;
4810 int first_iface_slot = 0;
4814 /* Double-checking locking pattern */
4815 if (klass->inited || mono_class_has_failure (klass))
4816 return !mono_class_has_failure (klass);
4818 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4821 * This function can recursively call itself.
4823 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4824 if (g_slist_find (init_list, klass)) {
4825 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4828 init_list = g_slist_prepend (init_list, klass);
4829 mono_native_tls_set_value (init_pending_tls_id, init_list);
4832 * We want to avoid doing complicated work inside locks, so we compute all the required
4833 * information and write it to @klass inside a lock.
4836 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4837 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4841 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4842 MonoClass *element_class = klass->element_class;
4843 if (!element_class->inited)
4844 mono_class_init (element_class);
4845 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4849 mono_stats.initialized_class_count++;
4851 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4852 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4854 mono_class_init (gklass);
4855 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4858 mono_class_setup_interface_id (klass);
4861 if (klass->parent && !klass->parent->inited)
4862 mono_class_init (klass->parent);
4864 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4866 /* Compute instance size etc. */
4867 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4868 if (mono_class_has_failure (klass))
4871 mono_class_setup_supertypes (klass);
4874 initialize_object_slots (klass);
4877 * Initialize the rest of the data without creating a generic vtable if possible.
4878 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4879 * also avoid computing a generic vtable.
4881 if (has_cached_info) {
4883 vtable_size = cached_info.vtable_size;
4884 ghcimpl = cached_info.ghcimpl;
4885 has_cctor = cached_info.has_cctor;
4886 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4887 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4888 * The first slot if for array with.
4890 static int szarray_vtable_size[2] = { 0 };
4892 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4895 if (!szarray_vtable_size [slot]) {
4896 mono_class_setup_vtable (klass);
4897 szarray_vtable_size [slot] = klass->vtable_size;
4898 vtable_size = klass->vtable_size;
4900 vtable_size = szarray_vtable_size[slot];
4902 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4903 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4905 /* Generic instance case */
4906 ghcimpl = gklass->ghcimpl;
4907 has_cctor = gklass->has_cctor;
4909 mono_class_setup_vtable (gklass);
4910 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4913 vtable_size = gklass->vtable_size;
4917 /* ghcimpl is not currently used
4919 if (klass->parent) {
4920 MonoMethod *cmethod = klass->vtable [ghc_slot];
4921 if (cmethod->is_inflated)
4922 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4923 if (cmethod == default_ghc) {
4929 /* C# doesn't allow interfaces to have cctors */
4930 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4931 MonoMethod *cmethod = NULL;
4933 if (mono_class_is_ginst (klass)) {
4934 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4936 /* Generic instance case */
4937 ghcimpl = gklass->ghcimpl;
4938 has_cctor = gklass->has_cctor;
4939 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4940 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4941 /* The find_method function ignores the 'flags' argument */
4942 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4945 mono_class_setup_methods (klass);
4946 if (mono_class_has_failure (klass))
4949 int mcount = mono_class_get_method_count (klass);
4950 for (i = 0; i < mcount; ++i) {
4951 MonoMethod *method = klass->methods [i];
4952 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
4953 (strcmp (".cctor", method->name) == 0)) {
4963 array_method_count = 3 + (klass->rank > 1? 2: 1);
4965 if (klass->interface_count) {
4966 int count_generic = generic_array_methods (klass);
4967 array_method_count += klass->interface_count * count_generic;
4971 if (klass->parent) {
4972 if (!klass->parent->vtable_size)
4973 mono_class_setup_vtable (klass->parent);
4974 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
4976 g_assert (klass->parent->vtable_size);
4977 first_iface_slot = klass->parent->vtable_size;
4978 if (mono_class_need_stelemref_method (klass))
4983 * Do the actual changes to @klass inside the loader lock
4985 mono_loader_lock ();
4988 if (klass->inited || mono_class_has_failure (klass)) {
4989 mono_loader_unlock ();
4990 /* Somebody might have gotten in before us */
4991 return !mono_class_has_failure (klass);
4994 mono_stats.initialized_class_count++;
4996 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
4997 mono_stats.generic_class_count++;
4999 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5000 klass->nested_classes_inited = TRUE;
5001 klass->ghcimpl = ghcimpl;
5002 klass->has_cctor = has_cctor;
5004 klass->vtable_size = vtable_size;
5005 if (has_cached_info) {
5006 klass->has_finalize = cached_info.has_finalize;
5007 klass->has_finalize_inited = TRUE;
5010 mono_class_set_method_count (klass, array_method_count);
5012 mono_loader_unlock ();
5015 setup_interface_offsets (klass, first_iface_slot, TRUE);
5017 if (mono_security_core_clr_enabled ())
5018 mono_security_core_clr_check_inheritance (klass);
5020 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5021 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5026 init_list = g_slist_remove (init_list, klass);
5027 mono_native_tls_set_value (init_pending_tls_id, init_list);
5030 mono_loader_unlock ();
5032 /* Leave this for last */
5033 mono_loader_lock ();
5035 mono_loader_unlock ();
5037 return !mono_class_has_failure (klass);
5041 * mono_class_has_finalizer:
5043 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5047 mono_class_has_finalizer (MonoClass *klass)
5049 gboolean has_finalize = FALSE;
5051 if (klass->has_finalize_inited)
5052 return klass->has_finalize;
5054 /* Interfaces and valuetypes are not supposed to have finalizers */
5055 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5056 MonoMethod *cmethod = NULL;
5058 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5059 } else if (mono_class_is_ginst (klass)) {
5060 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5062 has_finalize = mono_class_has_finalizer (gklass);
5063 } else if (klass->parent && klass->parent->has_finalize) {
5064 has_finalize = TRUE;
5066 if (klass->parent) {
5068 * Can't search in metadata for a method named Finalize, because that
5069 * ignores overrides.
5071 mono_class_setup_vtable (klass);
5072 if (mono_class_has_failure (klass))
5075 cmethod = klass->vtable [finalize_slot];
5079 g_assert (klass->vtable_size > finalize_slot);
5081 if (klass->parent) {
5082 if (cmethod->is_inflated)
5083 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5084 if (cmethod != default_finalize)
5085 has_finalize = TRUE;
5091 mono_loader_lock ();
5092 if (!klass->has_finalize_inited) {
5093 klass->has_finalize = has_finalize ? 1 : 0;
5095 mono_memory_barrier ();
5096 klass->has_finalize_inited = TRUE;
5098 mono_loader_unlock ();
5100 return klass->has_finalize;
5104 mono_is_corlib_image (MonoImage *image)
5106 return image == mono_defaults.corlib;
5110 * LOCKING: this assumes the loader lock is held
5113 mono_class_setup_mono_type (MonoClass *klass)
5115 const char *name = klass->name;
5116 const char *nspace = klass->name_space;
5117 gboolean is_corlib = mono_is_corlib_image (klass->image);
5119 klass->this_arg.byref = 1;
5120 klass->this_arg.data.klass = klass;
5121 klass->this_arg.type = MONO_TYPE_CLASS;
5122 klass->byval_arg.data.klass = klass;
5123 klass->byval_arg.type = MONO_TYPE_CLASS;
5125 if (is_corlib && !strcmp (nspace, "System")) {
5126 if (!strcmp (name, "ValueType")) {
5128 * do not set the valuetype bit for System.ValueType.
5129 * klass->valuetype = 1;
5131 klass->blittable = TRUE;
5132 } else if (!strcmp (name, "Enum")) {
5134 * do not set the valuetype bit for System.Enum.
5135 * klass->valuetype = 1;
5137 klass->valuetype = 0;
5138 klass->enumtype = 0;
5139 } else if (!strcmp (name, "Object")) {
5140 klass->byval_arg.type = MONO_TYPE_OBJECT;
5141 klass->this_arg.type = MONO_TYPE_OBJECT;
5142 } else if (!strcmp (name, "String")) {
5143 klass->byval_arg.type = MONO_TYPE_STRING;
5144 klass->this_arg.type = MONO_TYPE_STRING;
5145 } else if (!strcmp (name, "TypedReference")) {
5146 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5147 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5151 if (klass->valuetype) {
5152 int t = MONO_TYPE_VALUETYPE;
5154 if (is_corlib && !strcmp (nspace, "System")) {
5157 if (!strcmp (name, "Boolean")) {
5158 t = MONO_TYPE_BOOLEAN;
5159 } else if (!strcmp(name, "Byte")) {
5161 klass->blittable = TRUE;
5165 if (!strcmp (name, "Char")) {
5170 if (!strcmp (name, "Double")) {
5172 klass->blittable = TRUE;
5176 if (!strcmp (name, "Int32")) {
5178 klass->blittable = TRUE;
5179 } else if (!strcmp(name, "Int16")) {
5181 klass->blittable = TRUE;
5182 } else if (!strcmp(name, "Int64")) {
5184 klass->blittable = TRUE;
5185 } else if (!strcmp(name, "IntPtr")) {
5187 klass->blittable = TRUE;
5191 if (!strcmp (name, "Single")) {
5193 klass->blittable = TRUE;
5194 } else if (!strcmp(name, "SByte")) {
5196 klass->blittable = TRUE;
5200 if (!strcmp (name, "UInt32")) {
5202 klass->blittable = TRUE;
5203 } else if (!strcmp(name, "UInt16")) {
5205 klass->blittable = TRUE;
5206 } else if (!strcmp(name, "UInt64")) {
5208 klass->blittable = TRUE;
5209 } else if (!strcmp(name, "UIntPtr")) {
5211 klass->blittable = TRUE;
5215 if (!strcmp (name, "TypedReference")) {
5216 t = MONO_TYPE_TYPEDBYREF;
5217 klass->blittable = TRUE;
5221 if (!strcmp (name, "Void")) {
5229 klass->byval_arg.type = (MonoTypeEnum)t;
5230 klass->this_arg.type = (MonoTypeEnum)t;
5233 if (MONO_CLASS_IS_INTERFACE (klass)) {
5234 klass->interface_id = mono_get_unique_iid (klass);
5236 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5237 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5238 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5239 * MS returns diferrent types based on which instance is called. For example:
5240 * object obj = new byte[10][];
5241 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5242 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5245 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5246 klass->is_array_special_interface = 1;
5253 * COM initialization is delayed until needed.
5254 * However when a [ComImport] attribute is present on a type it will trigger
5255 * the initialization. This is not a problem unless the BCL being executed
5256 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5259 init_com_from_comimport (MonoClass *klass)
5261 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5262 if (mono_security_core_clr_enabled ()) {
5263 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5264 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5265 /* but it can not be made available for application (i.e. user code) since all COM calls
5266 * are considered native calls. In this case we fail with a TypeLoadException (just like
5267 * Silverlight 2 does */
5268 mono_class_set_type_load_failure (klass, "");
5273 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5275 #endif /*DISABLE_COM*/
5278 * LOCKING: this assumes the loader lock is held
5281 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5283 gboolean system_namespace;
5284 gboolean is_corlib = mono_is_corlib_image (klass->image);
5286 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5288 /* if root of the hierarchy */
5289 if (system_namespace && !strcmp (klass->name, "Object")) {
5290 klass->parent = NULL;
5291 klass->instance_size = sizeof (MonoObject);
5294 if (!strcmp (klass->name, "<Module>")) {
5295 klass->parent = NULL;
5296 klass->instance_size = 0;
5300 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5301 /* Imported COM Objects always derive from __ComObject. */
5303 if (MONO_CLASS_IS_IMPORT (klass)) {
5304 init_com_from_comimport (klass);
5305 if (parent == mono_defaults.object_class)
5306 parent = mono_class_get_com_object_class ();
5310 /* set the parent to something useful and safe, but mark the type as broken */
5311 parent = mono_defaults.object_class;
5312 mono_class_set_type_load_failure (klass, "");
5316 klass->parent = parent;
5318 if (mono_class_is_ginst (parent) && !parent->name) {
5320 * If the parent is a generic instance, we may get
5321 * called before it is fully initialized, especially
5322 * before it has its name.
5327 #ifndef DISABLE_REMOTING
5328 klass->marshalbyref = parent->marshalbyref;
5329 klass->contextbound = parent->contextbound;
5332 klass->delegate = parent->delegate;
5334 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5335 mono_class_set_is_com_object (klass);
5337 if (system_namespace) {
5338 #ifndef DISABLE_REMOTING
5339 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5340 klass->marshalbyref = 1;
5342 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5343 klass->contextbound = 1;
5345 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5346 klass->delegate = 1;
5349 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5350 (strcmp (klass->parent->name_space, "System") == 0)))
5351 klass->valuetype = 1;
5352 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5353 klass->valuetype = klass->enumtype = 1;
5355 /*klass->enumtype = klass->parent->enumtype; */
5357 /* initialize com types if COM interfaces are present */
5359 if (MONO_CLASS_IS_IMPORT (klass))
5360 init_com_from_comimport (klass);
5362 klass->parent = NULL;
5368 * mono_class_setup_supertypes:
5371 * Build the data structure needed to make fast type checks work.
5372 * This currently sets two fields in @class:
5373 * - idepth: distance between @class and System.Object in the type
5375 * - supertypes: array of classes: each element has a class in the hierarchy
5376 * starting from @class up to System.Object
5378 * LOCKING: Acquires the loader lock.
5381 mono_class_setup_supertypes (MonoClass *klass)
5384 MonoClass **supertypes;
5386 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5390 if (klass->parent && !klass->parent->supertypes)
5391 mono_class_setup_supertypes (klass->parent);
5393 idepth = klass->parent->idepth + 1;
5397 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5398 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5400 if (klass->parent) {
5401 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5404 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5405 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5407 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5410 mono_memory_barrier ();
5412 mono_loader_lock ();
5413 klass->idepth = idepth;
5414 /* Needed so idepth is visible before supertypes is set */
5415 mono_memory_barrier ();
5416 klass->supertypes = supertypes;
5417 mono_loader_unlock ();
5421 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5423 return mono_class_get_generic_class (gclass)->container_class == user_data;
5427 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5429 MonoClass *gtd = (MonoClass*)user_data;
5430 /* Only try to fix generic instances of @gtd */
5431 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5434 /* Check if the generic instance has no parent. */
5435 if (gtd->parent && !gclass->parent)
5436 mono_generic_class_setup_parent (gclass, gtd);
5442 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5444 mono_class_set_type_load_failure (klass, "%s", msg);
5445 mono_error_set_type_load_class (error, klass, "%s", msg);
5449 * mono_class_create_from_typedef:
5450 * \param image: image where the token is valid
5451 * \param type_token: typedef token
5452 * \param error: used to return any error found while creating the type
5454 * Create the MonoClass* representing the specified type token.
5455 * \p type_token must be a TypeDef token.
5457 * FIXME: don't return NULL on failure, just the the caller figure it out.
5460 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5462 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5463 MonoClass *klass, *parent = NULL;
5464 guint32 cols [MONO_TYPEDEF_SIZE];
5465 guint32 cols_next [MONO_TYPEDEF_SIZE];
5466 guint tidx = mono_metadata_token_index (type_token);
5467 MonoGenericContext *context = NULL;
5468 const char *name, *nspace;
5470 MonoClass **interfaces;
5471 guint32 field_last, method_last;
5472 guint32 nesting_tokeen;
5476 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5477 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5481 mono_loader_lock ();
5483 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5484 mono_loader_unlock ();
5488 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5490 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5491 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5493 if (mono_metadata_has_generic_params (image, type_token)) {
5494 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5495 klass->class_kind = MONO_CLASS_GTD;
5496 classes_size += sizeof (MonoClassGtd);
5499 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5500 klass->class_kind = MONO_CLASS_DEF;
5501 classes_size += sizeof (MonoClassDef);
5506 klass->name_space = nspace;
5508 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5510 klass->image = image;
5511 klass->type_token = type_token;
5512 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5514 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5517 * Check whether we're a generic type definition.
5519 if (mono_class_is_gtd (klass)) {
5520 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5521 generic_container->owner.klass = klass;
5522 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5523 context = &generic_container->context;
5524 mono_class_set_generic_container (klass, generic_container);
5525 enable_gclass_recording ();
5528 if (cols [MONO_TYPEDEF_EXTENDS]) {
5530 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5532 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5533 /*WARNING: this must satisfy mono_metadata_type_hash*/
5534 klass->this_arg.byref = 1;
5535 klass->this_arg.data.klass = klass;
5536 klass->this_arg.type = MONO_TYPE_CLASS;
5537 klass->byval_arg.data.klass = klass;
5538 klass->byval_arg.type = MONO_TYPE_CLASS;
5540 parent = mono_class_get_checked (image, parent_token, error);
5541 if (parent && context) /* Always inflate */
5542 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5544 if (parent == NULL) {
5545 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5546 goto parent_failure;
5549 for (tmp = parent; tmp; tmp = tmp->parent) {
5551 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5552 goto parent_failure;
5554 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5555 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5556 goto parent_failure;
5561 mono_class_setup_parent (klass, parent);
5563 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5564 mono_class_setup_mono_type (klass);
5566 if (mono_class_is_gtd (klass))
5567 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5570 * This might access klass->byval_arg for recursion generated by generic constraints,
5571 * so it has to come after setup_mono_type ().
5573 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5574 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5575 if (!mono_error_ok (error)) {
5576 /*FIXME implement a mono_class_set_failure_from_mono_error */
5577 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5578 mono_loader_unlock ();
5579 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5584 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5588 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5592 klass->cast_class = klass->element_class = klass;
5593 if (mono_is_corlib_image (klass->image)) {
5594 switch (klass->byval_arg.type) {
5596 if (mono_defaults.byte_class)
5597 klass->cast_class = mono_defaults.byte_class;
5600 if (mono_defaults.sbyte_class)
5601 mono_defaults.sbyte_class = klass;
5604 if (mono_defaults.uint16_class)
5605 mono_defaults.uint16_class = klass;
5608 if (mono_defaults.int16_class)
5609 klass->cast_class = mono_defaults.int16_class;
5612 if (mono_defaults.uint32_class)
5613 mono_defaults.uint32_class = klass;
5616 if (mono_defaults.int32_class)
5617 klass->cast_class = mono_defaults.int32_class;
5620 if (mono_defaults.uint64_class)
5621 mono_defaults.uint64_class = klass;
5624 if (mono_defaults.int64_class)
5625 klass->cast_class = mono_defaults.int64_class;
5630 if (!klass->enumtype) {
5631 if (!mono_metadata_interfaces_from_typedef_full (
5632 image, type_token, &interfaces, &icount, FALSE, context, error)){
5634 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5635 mono_loader_unlock ();
5636 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5640 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5641 g_assert(icount <= 65535);
5643 klass->interfaces = interfaces;
5644 klass->interface_count = icount;
5645 klass->interfaces_inited = 1;
5648 /*g_print ("Load class %s\n", name);*/
5651 * Compute the field and method lists
5653 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5654 mono_class_set_first_field_idx (klass, first_field_idx);
5655 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5656 mono_class_set_first_method_idx (klass, first_method_idx);
5658 if (tt->rows > tidx){
5659 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5660 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5661 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5663 field_last = image->tables [MONO_TABLE_FIELD].rows;
5664 method_last = image->tables [MONO_TABLE_METHOD].rows;
5667 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5668 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5669 mono_class_set_field_count (klass, field_last - first_field_idx);
5670 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5671 mono_class_set_method_count (klass, method_last - first_method_idx);
5673 /* reserve space to store vector pointer in arrays */
5674 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5675 klass->instance_size += 2 * sizeof (gpointer);
5676 g_assert (mono_class_get_field_count (klass) == 0);
5679 if (klass->enumtype) {
5680 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5681 if (!enum_basetype) {
5682 /*set it to a default value as the whole runtime can't handle this to be null*/
5683 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5684 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5685 mono_loader_unlock ();
5686 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5689 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5693 * If we're a generic type definition, load the constraints.
5694 * We must do this after the class has been constructed to make certain recursive scenarios
5697 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5698 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5699 mono_loader_unlock ();
5700 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5704 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5705 if (!strncmp (name, "Vector", 6))
5706 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");
5707 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5708 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5709 klass->simd_type = 1;
5712 mono_loader_unlock ();
5714 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5719 if (mono_class_is_gtd (klass))
5720 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5722 mono_class_setup_mono_type (klass);
5723 mono_loader_unlock ();
5724 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5728 /** Is klass a Nullable<T> ginst? */
5730 mono_class_is_nullable (MonoClass *klass)
5732 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5733 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5737 /** if klass is T? return T */
5739 mono_class_get_nullable_param (MonoClass *klass)
5741 g_assert (mono_class_is_nullable (klass));
5742 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5746 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5750 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5752 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5753 if (!mono_error_ok (&error)) {
5754 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5755 klass->parent = mono_defaults.object_class;
5756 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5757 mono_error_cleanup (&error);
5760 mono_loader_lock ();
5762 mono_class_setup_parent (klass, klass->parent);
5764 if (klass->enumtype) {
5765 klass->cast_class = gtd->cast_class;
5766 klass->element_class = gtd->element_class;
5768 mono_loader_unlock ();
5772 mono_type_is_primitive (MonoType *type)
5774 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5775 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5779 * Create the `MonoClass' for an instantiation of a generic type.
5780 * We only do this if we actually need it.
5783 mono_generic_class_get_class (MonoGenericClass *gclass)
5785 MonoClass *klass, *gklass;
5787 if (gclass->cached_class)
5788 return gclass->cached_class;
5790 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5792 gklass = gclass->container_class;
5794 if (gklass->nested_in) {
5795 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5796 klass->nested_in = gklass->nested_in;
5799 klass->name = gklass->name;
5800 klass->name_space = gklass->name_space;
5802 klass->image = gklass->image;
5803 klass->type_token = gklass->type_token;
5805 klass->class_kind = MONO_CLASS_GINST;
5807 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5809 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5810 klass->this_arg.type = klass->byval_arg.type;
5811 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5812 klass->this_arg.byref = TRUE;
5813 klass->enumtype = gklass->enumtype;
5814 klass->valuetype = gklass->valuetype;
5817 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5818 g_assert (gclass->context.class_inst);
5819 g_assert (gclass->context.class_inst->type_argc > 0);
5820 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5821 klass->simd_type = 1;
5823 klass->is_array_special_interface = gklass->is_array_special_interface;
5825 klass->cast_class = klass->element_class = klass;
5827 if (gclass->is_dynamic) {
5829 * 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.
5830 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5831 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5833 if (!gklass->wastypebuilder)
5836 if (klass->enumtype) {
5838 * For enums, gklass->fields might not been set, but instance_size etc. is
5839 * already set in mono_reflection_create_internal_class (). For non-enums,
5840 * these will be computed normally in mono_class_layout_fields ().
5842 klass->instance_size = gklass->instance_size;
5843 klass->sizes.class_size = gklass->sizes.class_size;
5844 klass->size_inited = 1;
5848 mono_loader_lock ();
5850 if (gclass->cached_class) {
5851 mono_loader_unlock ();
5852 return gclass->cached_class;
5855 if (record_gclass_instantiation > 0)
5856 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5858 if (mono_class_is_nullable (klass))
5859 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5861 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5863 mono_generic_class_setup_parent (klass, gklass);
5865 if (gclass->is_dynamic)
5866 mono_class_setup_supertypes (klass);
5868 mono_memory_barrier ();
5869 gclass->cached_class = klass;
5871 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5873 ++class_ginst_count;
5874 inflated_classes_size += sizeof (MonoClassGenericInst);
5876 mono_loader_unlock ();
5882 get_image_for_container (MonoGenericContainer *container)
5885 if (container->is_anonymous) {
5886 result = container->owner.image;
5889 if (container->is_method) {
5890 MonoMethod *method = container->owner.method;
5891 g_assert_checked (method);
5892 klass = method->klass;
5894 klass = container->owner.klass;
5896 g_assert_checked (klass);
5897 result = klass->image;
5904 get_image_for_generic_param (MonoGenericParam *param)
5906 MonoGenericContainer *container = mono_generic_param_owner (param);
5907 g_assert_checked (container);
5908 return get_image_for_container (container);
5911 // Make a string in the designated image consisting of a single integer.
5912 #define INT_STRING_SIZE 16
5914 make_generic_name_string (MonoImage *image, int num)
5916 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5917 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5921 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5922 // pinfo is derived from param by the caller for us.
5924 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5926 MonoClass *klass, **ptr;
5928 MonoGenericContainer *container = mono_generic_param_owner (param);
5929 g_assert_checked (container);
5931 MonoImage *image = get_image_for_container (container);
5932 gboolean is_mvar = container->is_method;
5933 gboolean is_anonymous = container->is_anonymous;
5935 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5936 klass->class_kind = MONO_CLASS_GPARAM;
5937 classes_size += sizeof (MonoClassGenericParam);
5938 ++class_gparam_count;
5941 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5943 int n = mono_generic_param_num (param);
5944 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5948 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
5949 } else if (is_mvar) {
5950 MonoMethod *omethod = container->owner.method;
5951 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
5953 MonoClass *oklass = container->owner.klass;
5954 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
5957 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5959 // Count non-NULL items in pinfo->constraints
5962 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5966 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5967 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
5969 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
5970 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
5972 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
5975 if (count - pos > 0) {
5976 klass->interface_count = count - pos;
5977 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
5978 klass->interfaces_inited = TRUE;
5979 for (i = pos; i < count; i++)
5980 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
5983 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
5985 klass->inited = TRUE;
5986 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
5987 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
5989 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5990 klass->this_arg.type = klass->byval_arg.type;
5991 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
5992 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
5993 klass->this_arg.byref = TRUE;
5995 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5996 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5998 /*Init these fields to sane values*/
5999 klass->min_align = 1;
6001 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6002 * constrained to, the JIT depends on this.
6004 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6005 mono_memory_barrier ();
6006 klass->size_inited = 1;
6008 mono_class_setup_supertypes (klass);
6010 if (count - pos > 0) {
6011 mono_class_setup_vtable (klass->parent);
6012 if (mono_class_has_failure (klass->parent))
6013 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6015 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6021 #define FAST_CACHE_SIZE 16
6024 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6025 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6026 * we cache the MonoClasses.
6027 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6028 * LOCKING: Takes the image lock depending on @take_lock.
6031 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6033 int n = mono_generic_param_num (param);
6034 MonoImage *image = get_image_for_generic_param (param);
6035 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6036 MonoClass *klass = NULL;
6041 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6042 // For high numbers or constraints we have to use pointer hashes.
6043 if (param->gshared_constraint) {
6044 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6047 mono_image_lock (image);
6048 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6050 mono_image_unlock (image);
6055 if (n < FAST_CACHE_SIZE) {
6057 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6059 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6061 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6064 mono_image_lock (image);
6065 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6067 mono_image_unlock (image);
6074 * LOCKING: Image lock (param->image) must be held
6077 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6079 int n = mono_generic_param_num (param);
6080 MonoImage *image = get_image_for_generic_param (param);
6081 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6085 if (param->gshared_constraint) {
6086 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6088 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6089 mono_memory_barrier ();
6091 image->mvar_cache_constrained = ht;
6093 image->var_cache_constrained = ht;
6095 g_hash_table_insert (ht, param, klass);
6096 } else if (n < FAST_CACHE_SIZE) {
6098 /* Requires locking to avoid droping an already published class */
6099 if (!image->mvar_cache_fast)
6100 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6101 image->mvar_cache_fast [n] = klass;
6103 if (!image->var_cache_fast)
6104 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6105 image->var_cache_fast [n] = klass;
6108 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6110 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6112 ht = g_hash_table_new (NULL, NULL);
6113 mono_memory_barrier ();
6115 image->mvar_cache_slow = ht;
6117 image->var_cache_slow = ht;
6120 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6125 * LOCKING: Acquires the image lock (@image).
6128 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6130 MonoImage *image = get_image_for_generic_param (param);
6131 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6132 MonoClass *klass, *klass2;
6134 // If a klass already exists for this object and is cached, return it.
6135 if (pinfo) // Non-anonymous
6136 klass = pinfo->pklass;
6138 klass = get_anon_gparam_class (param, TRUE);
6143 // Create a new klass
6144 klass = make_generic_param_class (param, pinfo);
6146 // Now we need to cache the klass we created.
6147 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6148 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6149 // and allow our newly-created klass object to just leak.
6150 mono_memory_barrier ();
6152 mono_image_lock (image);
6154 // Here "klass2" refers to the klass potentially created by the other thread.
6155 if (pinfo) // Repeat check from above
6156 klass2 = pinfo->pklass;
6158 klass2 = get_anon_gparam_class (param, FALSE);
6165 pinfo->pklass = klass;
6167 set_anon_gparam_class (param, klass);
6169 mono_image_unlock (image);
6171 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6173 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6175 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6181 * mono_class_from_generic_parameter:
6182 * \param param Parameter to find/construct a class for.
6183 * \param arg2 Is ignored.
6184 * \param arg3 Is ignored.
6187 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6189 return mono_class_from_generic_parameter_internal (param);
6193 * mono_ptr_class_get:
6196 mono_ptr_class_get (MonoType *type)
6199 MonoClass *el_class;
6203 el_class = mono_class_from_mono_type (type);
6204 image = el_class->image;
6206 mono_image_lock (image);
6207 if (image->ptr_cache) {
6208 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6209 mono_image_unlock (image);
6213 mono_image_unlock (image);
6215 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6217 classes_size += sizeof (MonoClassPointer);
6218 ++class_pointer_count;
6220 result->parent = NULL; /* no parent for PTR types */
6221 result->name_space = el_class->name_space;
6222 name = g_strdup_printf ("%s*", el_class->name);
6223 result->name = mono_image_strdup (image, name);
6224 result->class_kind = MONO_CLASS_POINTER;
6227 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6229 result->image = el_class->image;
6230 result->inited = TRUE;
6231 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6232 result->cast_class = result->element_class = el_class;
6233 result->blittable = TRUE;
6235 result->byval_arg.type = MONO_TYPE_PTR;
6236 result->this_arg.type = result->byval_arg.type;
6237 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6238 result->this_arg.byref = TRUE;
6240 mono_class_setup_supertypes (result);
6242 mono_image_lock (image);
6243 if (image->ptr_cache) {
6245 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6246 mono_image_unlock (image);
6247 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6251 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6253 g_hash_table_insert (image->ptr_cache, el_class, result);
6254 mono_image_unlock (image);
6256 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6262 mono_fnptr_class_get (MonoMethodSignature *sig)
6264 MonoClass *result, *cached;
6265 static GHashTable *ptr_hash = NULL;
6267 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6269 mono_loader_lock ();
6271 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6272 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6273 mono_loader_unlock ();
6277 result = g_new0 (MonoClass, 1);
6279 result->parent = NULL; /* no parent for PTR types */
6280 result->name_space = "System";
6281 result->name = "MonoFNPtrFakeClass";
6282 result->class_kind = MONO_CLASS_POINTER;
6284 result->image = mono_defaults.corlib; /* need to fix... */
6285 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6286 result->cast_class = result->element_class = result;
6287 result->byval_arg.type = MONO_TYPE_FNPTR;
6288 result->this_arg.type = result->byval_arg.type;
6289 result->this_arg.data.method = result->byval_arg.data.method = sig;
6290 result->this_arg.byref = TRUE;
6291 result->blittable = TRUE;
6292 result->inited = TRUE;
6294 mono_class_setup_supertypes (result);
6296 mono_loader_lock ();
6298 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6301 mono_loader_unlock ();
6305 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6307 classes_size += sizeof (MonoClassPointer);
6308 ++class_pointer_count;
6310 g_hash_table_insert (ptr_hash, sig, result);
6312 mono_loader_unlock ();
6314 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6320 * mono_class_from_mono_type:
6321 * \param type describes the type to return
6322 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6325 mono_class_from_mono_type (MonoType *type)
6327 switch (type->type) {
6328 case MONO_TYPE_OBJECT:
6329 return type->data.klass? type->data.klass: mono_defaults.object_class;
6330 case MONO_TYPE_VOID:
6331 return type->data.klass? type->data.klass: mono_defaults.void_class;
6332 case MONO_TYPE_BOOLEAN:
6333 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6334 case MONO_TYPE_CHAR:
6335 return type->data.klass? type->data.klass: mono_defaults.char_class;
6337 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6339 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6341 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6343 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6345 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6347 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6349 return type->data.klass? type->data.klass: mono_defaults.int_class;
6351 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6353 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6355 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6357 return type->data.klass? type->data.klass: mono_defaults.single_class;
6359 return type->data.klass? type->data.klass: mono_defaults.double_class;
6360 case MONO_TYPE_STRING:
6361 return type->data.klass? type->data.klass: mono_defaults.string_class;
6362 case MONO_TYPE_TYPEDBYREF:
6363 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6364 case MONO_TYPE_ARRAY:
6365 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6367 return mono_ptr_class_get (type->data.type);
6368 case MONO_TYPE_FNPTR:
6369 return mono_fnptr_class_get (type->data.method);
6370 case MONO_TYPE_SZARRAY:
6371 return mono_array_class_get (type->data.klass, 1);
6372 case MONO_TYPE_CLASS:
6373 case MONO_TYPE_VALUETYPE:
6374 return type->data.klass;
6375 case MONO_TYPE_GENERICINST:
6376 return mono_generic_class_get_class (type->data.generic_class);
6377 case MONO_TYPE_MVAR:
6379 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6381 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6382 g_assert_not_reached ();
6385 // Yes, this returns NULL, even if it is documented as not doing so, but there
6386 // is no way for the code to make it this far, due to the assert above.
6391 * mono_type_retrieve_from_typespec
6392 * \param image context where the image is created
6393 * \param type_spec typespec token
6394 * \param context the generic context used to evaluate generic instantiations in
6397 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6399 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6401 *did_inflate = FALSE;
6406 if (context && (context->class_inst || context->method_inst)) {
6407 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6409 if (!mono_error_ok (error)) {
6415 *did_inflate = TRUE;
6422 * mono_class_create_from_typespec
6423 * \param image context where the image is created
6424 * \param type_spec typespec token
6425 * \param context the generic context used to evaluate generic instantiations in
6428 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6431 gboolean inflated = FALSE;
6432 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6433 return_val_if_nok (error, NULL);
6434 ret = mono_class_from_mono_type (t);
6436 mono_metadata_free_type (t);
6441 * mono_bounded_array_class_get:
6442 * \param element_class element class
6443 * \param rank the dimension of the array class
6444 * \param bounded whenever the array has non-zero bounds
6445 * \returns A class object describing the array with element type \p element_type and
6446 * dimension \p rank.
6449 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6452 MonoClass *klass, *cached, *k;
6453 MonoClass *parent = NULL;
6454 GSList *list, *rootlist = NULL;
6458 g_assert (rank <= 255);
6461 /* bounded only matters for one-dimensional arrays */
6464 image = eclass->image;
6468 if (rank == 1 && !bounded) {
6470 * This case is very frequent not just during compilation because of calls
6471 * from mono_class_from_mono_type (), mono_array_new (),
6472 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6474 mono_os_mutex_lock (&image->szarray_cache_lock);
6475 if (!image->szarray_cache)
6476 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6477 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6478 mono_os_mutex_unlock (&image->szarray_cache_lock);
6480 mono_loader_lock ();
6481 if (!image->array_cache)
6482 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6483 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6484 for (list = rootlist; list; list = list->next) {
6485 k = (MonoClass *)list->data;
6486 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6491 mono_loader_unlock ();
6496 parent = mono_defaults.array_class;
6497 if (!parent->inited)
6498 mono_class_init (parent);
6500 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6502 klass->image = image;
6503 klass->name_space = eclass->name_space;
6504 klass->class_kind = MONO_CLASS_ARRAY;
6506 nsize = strlen (eclass->name);
6507 name = (char *)g_malloc (nsize + 2 + rank + 1);
6508 memcpy (name, eclass->name, nsize);
6511 memset (name + nsize + 1, ',', rank - 1);
6513 name [nsize + rank] = '*';
6514 name [nsize + rank + bounded] = ']';
6515 name [nsize + rank + bounded + 1] = 0;
6516 klass->name = mono_image_strdup (image, name);
6519 klass->type_token = 0;
6520 klass->parent = parent;
6521 klass->instance_size = mono_class_instance_size (klass->parent);
6523 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6524 /*Arrays of those two types are invalid.*/
6525 MonoError prepared_error;
6526 error_init (&prepared_error);
6527 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6528 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6529 mono_error_cleanup (&prepared_error);
6530 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6531 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6532 if (!ref_info_handle || eclass->wastypebuilder) {
6533 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6534 g_assert (ref_info_handle && !eclass->wastypebuilder);
6536 /* element_size -1 is ok as this is not an instantitable type*/
6537 klass->sizes.element_size = -1;
6539 klass->sizes.element_size = mono_class_array_element_size (eclass);
6541 mono_class_setup_supertypes (klass);
6543 if (mono_class_is_ginst (eclass))
6544 mono_class_init (eclass);
6545 if (!eclass->size_inited)
6546 mono_class_setup_fields (eclass);
6547 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6548 /*FIXME we fail the array type, but we have to let other fields be set.*/
6550 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6554 if (eclass->enumtype)
6555 klass->cast_class = eclass->element_class;
6557 klass->cast_class = eclass;
6559 switch (klass->cast_class->byval_arg.type) {
6561 klass->cast_class = mono_defaults.byte_class;
6564 klass->cast_class = mono_defaults.int16_class;
6567 #if SIZEOF_VOID_P == 4
6571 klass->cast_class = mono_defaults.int32_class;
6574 #if SIZEOF_VOID_P == 8
6578 klass->cast_class = mono_defaults.int64_class;
6584 klass->element_class = eclass;
6586 if ((rank > 1) || bounded) {
6587 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6588 klass->byval_arg.type = MONO_TYPE_ARRAY;
6589 klass->byval_arg.data.array = at;
6590 at->eklass = eclass;
6592 /* FIXME: complete.... */
6594 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6595 klass->byval_arg.data.klass = eclass;
6597 klass->this_arg = klass->byval_arg;
6598 klass->this_arg.byref = 1;
6601 MonoError prepared_error;
6602 error_init (&prepared_error);
6603 name = mono_type_get_full_name (klass);
6604 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6605 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6606 mono_error_cleanup (&prepared_error);
6610 mono_loader_lock ();
6612 /* Check cache again */
6614 if (rank == 1 && !bounded) {
6615 mono_os_mutex_lock (&image->szarray_cache_lock);
6616 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6617 mono_os_mutex_unlock (&image->szarray_cache_lock);
6619 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6620 for (list = rootlist; list; list = list->next) {
6621 k = (MonoClass *)list->data;
6622 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6629 mono_loader_unlock ();
6633 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6635 classes_size += sizeof (MonoClassArray);
6636 ++class_array_count;
6638 if (rank == 1 && !bounded) {
6639 mono_os_mutex_lock (&image->szarray_cache_lock);
6640 g_hash_table_insert (image->szarray_cache, eclass, klass);
6641 mono_os_mutex_unlock (&image->szarray_cache_lock);
6643 list = g_slist_append (rootlist, klass);
6644 g_hash_table_insert (image->array_cache, eclass, list);
6647 mono_loader_unlock ();
6649 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6655 * mono_array_class_get:
6656 * \param element_class element class
6657 * \param rank the dimension of the array class
6658 * \returns A class object describing the array with element type \p element_type and
6659 * dimension \p rank.
6662 mono_array_class_get (MonoClass *eclass, guint32 rank)
6664 return mono_bounded_array_class_get (eclass, rank, FALSE);
6668 * mono_class_instance_size:
6669 * \param klass a class
6671 * Use to get the size of a class in bytes.
6673 * \returns The size of an object instance
6676 mono_class_instance_size (MonoClass *klass)
6678 if (!klass->size_inited)
6679 mono_class_init (klass);
6681 return klass->instance_size;
6685 * mono_class_min_align:
6686 * \param klass a class
6688 * Use to get the computed minimum alignment requirements for the specified class.
6690 * Returns: minimum alignment requirements
6693 mono_class_min_align (MonoClass *klass)
6695 if (!klass->size_inited)
6696 mono_class_init (klass);
6698 return klass->min_align;
6702 * mono_class_value_size:
6703 * \param klass a class
6705 * This function is used for value types, and return the
6706 * space and the alignment to store that kind of value object.
6708 * \returns the size of a value of kind \p klass
6711 mono_class_value_size (MonoClass *klass, guint32 *align)
6715 /* fixme: check disable, because we still have external revereces to
6716 * mscorlib and Dummy Objects
6718 /*g_assert (klass->valuetype);*/
6720 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6723 *align = klass->min_align;
6729 * mono_class_data_size:
6730 * \param klass a class
6732 * \returns The size of the static class data
6735 mono_class_data_size (MonoClass *klass)
6738 mono_class_init (klass);
6739 /* This can happen with dynamically created types */
6740 if (!klass->fields_inited)
6741 mono_class_setup_fields (klass);
6743 /* in arrays, sizes.class_size is unioned with element_size
6744 * and arrays have no static fields
6748 return klass->sizes.class_size;
6752 * Auxiliary routine to mono_class_get_field
6754 * Takes a field index instead of a field token.
6756 static MonoClassField *
6757 mono_class_get_field_idx (MonoClass *klass, int idx)
6759 mono_class_setup_fields (klass);
6760 if (mono_class_has_failure (klass))
6764 int first_field_idx = mono_class_get_first_field_idx (klass);
6765 int fcount = mono_class_get_field_count (klass);
6766 if (klass->image->uncompressed_metadata) {
6768 * first_field_idx points to the FieldPtr table, while idx points into the
6769 * Field table, so we have to do a search.
6771 /*FIXME this is broken for types with multiple fields with the same name.*/
6772 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6775 for (i = 0; i < fcount; ++i)
6776 if (mono_field_get_name (&klass->fields [i]) == name)
6777 return &klass->fields [i];
6778 g_assert_not_reached ();
6781 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6782 return &klass->fields [idx - first_field_idx];
6786 klass = klass->parent;
6792 * mono_class_get_field:
6793 * \param class the class to lookup the field.
6794 * \param field_token the field token
6796 * \returns A \c MonoClassField representing the type and offset of
6797 * the field, or a NULL value if the field does not belong to this
6801 mono_class_get_field (MonoClass *klass, guint32 field_token)
6803 int idx = mono_metadata_token_index (field_token);
6805 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6807 return mono_class_get_field_idx (klass, idx - 1);
6811 * mono_class_get_field_from_name:
6812 * \param klass the class to lookup the field.
6813 * \param name the field name
6815 * Search the class \p klass and its parents for a field with the name \p name.
6817 * \returns The \c MonoClassField pointer of the named field or NULL
6820 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6822 return mono_class_get_field_from_name_full (klass, name, NULL);
6826 * mono_class_get_field_from_name_full:
6827 * \param klass the class to lookup the field.
6828 * \param name the field name
6829 * \param type the type of the fields. This optional.
6831 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6833 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6834 * of its generic type definition.
6836 * \returns The MonoClassField pointer of the named field or NULL
6839 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6843 mono_class_setup_fields (klass);
6844 if (mono_class_has_failure (klass))
6848 int fcount = mono_class_get_field_count (klass);
6849 for (i = 0; i < fcount; ++i) {
6850 MonoClassField *field = &klass->fields [i];
6852 if (strcmp (name, mono_field_get_name (field)) != 0)
6856 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6857 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6862 klass = klass->parent;
6868 * mono_class_get_field_token:
6869 * \param field the field we need the token of
6871 * Get the token of a field. Note that the tokesn is only valid for the image
6872 * the field was loaded from. Don't use this function for fields in dynamic types.
6874 * \returns The token representing the field in the image it was loaded from.
6877 mono_class_get_field_token (MonoClassField *field)
6879 MonoClass *klass = field->parent;
6882 mono_class_setup_fields (klass);
6887 int first_field_idx = mono_class_get_first_field_idx (klass);
6888 int fcount = mono_class_get_field_count (klass);
6889 for (i = 0; i < fcount; ++i) {
6890 if (&klass->fields [i] == field) {
6891 int idx = first_field_idx + i + 1;
6893 if (klass->image->uncompressed_metadata)
6894 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6895 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6898 klass = klass->parent;
6901 g_assert_not_reached ();
6906 mono_field_get_index (MonoClassField *field)
6908 int index = field - field->parent->fields;
6909 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6915 * mono_class_get_field_default_value:
6917 * Return the default value of the field as a pointer into the metadata blob.
6920 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6923 guint32 constant_cols [MONO_CONSTANT_SIZE];
6925 MonoClass *klass = field->parent;
6926 MonoFieldDefaultValue *def_values;
6928 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6930 def_values = mono_class_get_field_def_values (klass);
6932 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6934 mono_class_set_field_def_values (klass, def_values);
6937 field_index = mono_field_get_index (field);
6939 if (!def_values [field_index].data) {
6940 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6944 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6946 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6947 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6948 mono_memory_barrier ();
6949 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6952 *def_type = def_values [field_index].def_type;
6953 return def_values [field_index].data;
6957 mono_property_get_index (MonoProperty *prop)
6959 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6960 int index = prop - info->properties;
6962 g_assert (index >= 0 && index < info->count);
6968 * mono_class_get_property_default_value:
6970 * Return the default value of the field as a pointer into the metadata blob.
6973 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6976 guint32 constant_cols [MONO_CONSTANT_SIZE];
6977 MonoClass *klass = property->parent;
6979 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6981 * We don't cache here because it is not used by C# so it's quite rare, but
6982 * we still do the lookup in klass->ext because that is where the data
6983 * is stored for dynamic assemblies.
6986 if (image_is_dynamic (klass->image)) {
6987 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
6988 int prop_index = mono_property_get_index (property);
6989 if (info->def_values && info->def_values [prop_index].data) {
6990 *def_type = info->def_values [prop_index].def_type;
6991 return info->def_values [prop_index].data;
6995 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6999 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7000 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7001 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7005 * mono_class_get_event_token:
7008 mono_class_get_event_token (MonoEvent *event)
7010 MonoClass *klass = event->parent;
7014 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7016 for (i = 0; i < info->count; ++i) {
7017 if (&info->events [i] == event)
7018 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7021 klass = klass->parent;
7024 g_assert_not_reached ();
7029 * mono_class_get_property_from_name:
7030 * \param klass a class
7031 * \param name name of the property to lookup in the specified class
7033 * Use this method to lookup a property in a class
7034 * \returns the \c MonoProperty with the given name, or NULL if the property
7035 * does not exist on the \p klass.
7038 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7042 gpointer iter = NULL;
7043 while ((p = mono_class_get_properties (klass, &iter))) {
7044 if (! strcmp (name, p->name))
7047 klass = klass->parent;
7053 * mono_class_get_property_token:
7054 * \param prop MonoProperty to query
7056 * \returns The ECMA token for the specified property.
7059 mono_class_get_property_token (MonoProperty *prop)
7061 MonoClass *klass = prop->parent;
7065 gpointer iter = NULL;
7066 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7067 while ((p = mono_class_get_properties (klass, &iter))) {
7068 if (&info->properties [i] == prop)
7069 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7073 klass = klass->parent;
7076 g_assert_not_reached ();
7081 * mono_class_name_from_token:
7084 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7086 const char *name, *nspace;
7087 if (image_is_dynamic (image))
7088 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7090 switch (type_token & 0xff000000){
7091 case MONO_TOKEN_TYPE_DEF: {
7092 guint32 cols [MONO_TYPEDEF_SIZE];
7093 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7094 guint tidx = mono_metadata_token_index (type_token);
7096 if (tidx > tt->rows)
7097 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7099 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7100 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7101 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7102 if (strlen (nspace) == 0)
7103 return g_strdup_printf ("%s", name);
7105 return g_strdup_printf ("%s.%s", nspace, name);
7108 case MONO_TOKEN_TYPE_REF: {
7110 guint32 cols [MONO_TYPEREF_SIZE];
7111 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7112 guint tidx = mono_metadata_token_index (type_token);
7115 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7117 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7118 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7119 mono_error_cleanup (&error);
7123 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7124 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7125 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7126 if (strlen (nspace) == 0)
7127 return g_strdup_printf ("%s", name);
7129 return g_strdup_printf ("%s.%s", nspace, name);
7132 case MONO_TOKEN_TYPE_SPEC:
7133 return g_strdup_printf ("Typespec 0x%08x", type_token);
7135 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7140 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7142 if (image_is_dynamic (image))
7143 return g_strdup_printf ("DynamicAssembly %s", image->name);
7145 switch (type_token & 0xff000000){
7146 case MONO_TOKEN_TYPE_DEF:
7147 if (image->assembly)
7148 return mono_stringify_assembly_name (&image->assembly->aname);
7149 else if (image->assembly_name)
7150 return g_strdup (image->assembly_name);
7151 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7152 case MONO_TOKEN_TYPE_REF: {
7154 MonoAssemblyName aname;
7155 guint32 cols [MONO_TYPEREF_SIZE];
7156 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7157 guint32 idx = mono_metadata_token_index (type_token);
7160 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7162 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7163 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7164 mono_error_cleanup (&error);
7167 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7169 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7170 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7171 case MONO_RESOLUTION_SCOPE_MODULE:
7173 return g_strdup ("");
7174 case MONO_RESOLUTION_SCOPE_MODULEREF:
7176 return g_strdup ("");
7177 case MONO_RESOLUTION_SCOPE_TYPEREF:
7179 return g_strdup ("");
7180 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7181 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7182 return mono_stringify_assembly_name (&aname);
7184 g_assert_not_reached ();
7188 case MONO_TOKEN_TYPE_SPEC:
7190 return g_strdup ("");
7192 g_assert_not_reached ();
7199 * mono_class_get_full:
7200 * \param image the image where the class resides
7201 * \param type_token the token for the class
7202 * \param context the generic context used to evaluate generic instantiations in
7203 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7204 * \returns The \c MonoClass that represents \p type_token in \p image
7207 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7211 klass = mono_class_get_checked (image, type_token, &error);
7213 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7214 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7216 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7222 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7227 klass = mono_class_get_checked (image, type_token, error);
7229 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7230 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7235 * mono_class_get_checked:
7236 * \param image the image where the class resides
7237 * \param type_token the token for the class
7238 * \param error error object to return any error
7240 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7243 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7245 MonoClass *klass = NULL;
7249 if (image_is_dynamic (image)) {
7250 int table = mono_metadata_token_table (type_token);
7252 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7253 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7256 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7260 switch (type_token & 0xff000000){
7261 case MONO_TOKEN_TYPE_DEF:
7262 klass = mono_class_create_from_typedef (image, type_token, error);
7264 case MONO_TOKEN_TYPE_REF:
7265 klass = mono_class_from_typeref_checked (image, type_token, error);
7267 case MONO_TOKEN_TYPE_SPEC:
7268 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7271 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7275 /* Generic case, should be avoided for when a better error is possible. */
7276 if (!klass && mono_error_ok (error)) {
7277 char *name = mono_class_name_from_token (image, type_token);
7278 char *assembly = mono_assembly_name_from_token (image, type_token);
7279 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7287 * mono_type_get_checked:
7288 * \param image the image where the type resides
7289 * \param type_token the token for the type
7290 * \param context the generic context used to evaluate generic instantiations in
7291 * \param error Error handling context
7293 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7295 * \returns The MonoType that represents \p type_token in \p image
7298 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7300 MonoType *type = NULL;
7301 gboolean inflated = FALSE;
7305 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7306 if (image_is_dynamic (image)) {
7307 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7308 return_val_if_nok (error, NULL);
7309 return mono_class_get_type (klass);
7312 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7313 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7320 return mono_class_get_type (klass);
7323 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7330 MonoType *tmp = type;
7331 type = mono_class_get_type (mono_class_from_mono_type (type));
7332 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7333 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7334 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7336 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7338 if (type->type != tmp->type)
7341 mono_metadata_free_type (tmp);
7348 * \param image image where the class token will be looked up.
7349 * \param type_token a type token from the image
7350 * \returns the \c MonoClass with the given \p type_token on the \p image
7353 mono_class_get (MonoImage *image, guint32 type_token)
7355 return mono_class_get_full (image, type_token, NULL);
7359 * mono_image_init_name_cache:
7361 * Initializes the class name cache stored in image->name_cache.
7363 * LOCKING: Acquires the corresponding image lock.
7366 mono_image_init_name_cache (MonoImage *image)
7368 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7369 guint32 cols [MONO_TYPEDEF_SIZE];
7372 guint32 i, visib, nspace_index;
7373 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7375 if (image->name_cache)
7378 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7380 if (image_is_dynamic (image)) {
7381 mono_image_lock (image);
7382 if (image->name_cache) {
7383 /* Somebody initialized it before us */
7384 g_hash_table_destroy (the_name_cache);
7386 mono_atomic_store_release (&image->name_cache, the_name_cache);
7388 mono_image_unlock (image);
7392 /* Temporary hash table to avoid lookups in the nspace_table */
7393 name_cache2 = g_hash_table_new (NULL, NULL);
7395 for (i = 1; i <= t->rows; ++i) {
7396 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7397 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7399 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7400 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7402 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7404 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7405 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7407 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7408 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7409 if (!nspace_table) {
7410 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7411 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7412 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7415 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7418 /* Load type names from EXPORTEDTYPES table */
7420 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7421 guint32 cols [MONO_EXP_TYPE_SIZE];
7424 for (i = 0; i < t->rows; ++i) {
7425 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7427 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7428 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7432 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7433 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7435 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7436 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7437 if (!nspace_table) {
7438 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7439 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7440 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7443 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7447 g_hash_table_destroy (name_cache2);
7449 mono_image_lock (image);
7450 if (image->name_cache) {
7451 /* Somebody initialized it before us */
7452 g_hash_table_destroy (the_name_cache);
7454 mono_atomic_store_release (&image->name_cache, the_name_cache);
7456 mono_image_unlock (image);
7459 /*FIXME Only dynamic assemblies should allow this operation.*/
7461 * mono_image_add_to_name_cache:
7464 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7465 const char *name, guint32 index)
7467 GHashTable *nspace_table;
7468 GHashTable *name_cache;
7471 mono_image_init_name_cache (image);
7472 mono_image_lock (image);
7474 name_cache = image->name_cache;
7475 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7476 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7477 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7480 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7481 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7483 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7485 mono_image_unlock (image);
7494 find_nocase (gpointer key, gpointer value, gpointer user_data)
7496 char *name = (char*)key;
7497 FindUserData *data = (FindUserData*)user_data;
7499 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7500 data->value = value;
7504 * mono_class_from_name_case:
7505 * \param image The MonoImage where the type is looked up in
7506 * \param name_space the type namespace
7507 * \param name the type short name.
7508 * \deprecated use the mono_class_from_name_case_checked variant instead.
7510 * Obtains a \c MonoClass with a given namespace and a given name which
7511 * is located in the given \c MonoImage. The namespace and name
7512 * lookups are case insensitive.
7515 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7518 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7519 mono_error_cleanup (&error);
7525 * mono_class_from_name_case_checked:
7526 * \param image The MonoImage where the type is looked up in
7527 * \param name_space the type namespace
7528 * \param name the type short name.
7531 * Obtains a MonoClass with a given namespace and a given name which
7532 * is located in the given MonoImage. The namespace and name
7533 * lookups are case insensitive.
7535 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7536 * was not found. The \p error object will contain information about the problem
7540 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7542 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7543 guint32 cols [MONO_TYPEDEF_SIZE];
7550 if (image_is_dynamic (image)) {
7552 FindUserData user_data;
7554 mono_image_init_name_cache (image);
7555 mono_image_lock (image);
7557 user_data.key = name_space;
7558 user_data.value = NULL;
7559 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7561 if (user_data.value) {
7562 GHashTable *nspace_table = (GHashTable*)user_data.value;
7564 user_data.key = name;
7565 user_data.value = NULL;
7567 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7569 if (user_data.value)
7570 token = GPOINTER_TO_UINT (user_data.value);
7573 mono_image_unlock (image);
7576 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7582 /* add a cache if needed */
7583 for (i = 1; i <= t->rows; ++i) {
7584 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7585 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7587 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7588 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7590 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7592 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7593 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7594 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7595 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7601 return_nested_in (MonoClass *klass, char *nested)
7604 char *s = strchr (nested, '/');
7605 gpointer iter = NULL;
7612 while ((found = mono_class_get_nested_types (klass, &iter))) {
7613 if (strcmp (found->name, nested) == 0) {
7615 return return_nested_in (found, s);
7623 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7625 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7626 MonoImage *file_image;
7633 * The EXPORTEDTYPES table only contains public types, so have to search the
7635 * Note: image->modules contains the contents of the MODULEREF table, while
7636 * the real module list is in the FILE table.
7638 for (i = 0; i < file_table->rows; i++) {
7639 guint32 cols [MONO_FILE_SIZE];
7640 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7641 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7644 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7646 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7647 if (klass || !is_ok (error))
7656 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7658 GHashTable *nspace_table;
7659 MonoImage *loaded_image;
7668 // Checking visited images avoids stack overflows when cyclic references exist.
7669 if (g_hash_table_lookup (visited_images, image))
7672 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7674 if ((nested = strchr (name, '/'))) {
7675 int pos = nested - name;
7676 int len = strlen (name);
7679 memcpy (buf, name, len + 1);
7681 nested = buf + pos + 1;
7685 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7686 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7687 gboolean res = get_class_from_name (image, name_space, name, &klass);
7690 klass = search_modules (image, name_space, name, error);
7695 return klass ? return_nested_in (klass, nested) : NULL;
7701 mono_image_init_name_cache (image);
7702 mono_image_lock (image);
7704 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7707 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7709 mono_image_unlock (image);
7711 if (!token && image_is_dynamic (image) && image->modules) {
7712 /* Search modules as well */
7713 for (i = 0; i < image->module_count; ++i) {
7714 MonoImage *module = image->modules [i];
7716 klass = mono_class_from_name_checked (module, name_space, name, error);
7717 if (klass || !is_ok (error))
7723 klass = search_modules (image, name_space, name, error);
7724 if (klass || !is_ok (error))
7729 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7730 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7731 guint32 cols [MONO_EXP_TYPE_SIZE];
7734 idx = mono_metadata_token_index (token);
7736 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7738 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7739 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7740 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7743 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7745 return klass ? return_nested_in (klass, nested) : NULL;
7747 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7748 guint32 assembly_idx;
7750 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7752 mono_assembly_load_reference (image, assembly_idx - 1);
7753 g_assert (image->references [assembly_idx - 1]);
7754 if (image->references [assembly_idx - 1] == (gpointer)-1)
7756 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7758 return klass ? return_nested_in (klass, nested) : NULL;
7761 g_assert_not_reached ();
7765 token = MONO_TOKEN_TYPE_DEF | token;
7767 klass = mono_class_get_checked (image, token, error);
7769 return return_nested_in (klass, nested);
7774 * mono_class_from_name_checked:
7775 * \param image The MonoImage where the type is looked up in
7776 * \param name_space the type namespace
7777 * \param name the type short name.
7779 * Obtains a MonoClass with a given namespace and a given name which
7780 * is located in the given MonoImage.
7782 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7783 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7786 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7789 GHashTable *visited_images;
7791 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7793 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7795 g_hash_table_destroy (visited_images);
7801 * mono_class_from_name:
7802 * \param image The \c MonoImage where the type is looked up in
7803 * \param name_space the type namespace
7804 * \param name the type short name.
7806 * Obtains a \c MonoClass with a given namespace and a given name which
7807 * is located in the given \c MonoImage.
7809 * To reference nested classes, use the "/" character as a separator.
7810 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7811 * inside \c Foo, like this: "class Foo { class Bar {} }".
7814 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7819 klass = mono_class_from_name_checked (image, name_space, name, &error);
7820 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7826 * mono_class_load_from_name:
7827 * \param image The MonoImage where the type is looked up in
7828 * \param name_space the type namespace
7829 * \param name the type short name.
7831 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7832 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7833 * If they are missing. Thing of System.Object or System.String.
7836 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7841 klass = mono_class_from_name_checked (image, name_space, name, &error);
7843 g_error ("Runtime critical type %s.%s not found", name_space, name);
7844 if (!mono_error_ok (&error))
7845 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7850 * mono_class_try_load_from_name:
7851 * \param image The MonoImage where the type is looked up in
7852 * \param name_space the type namespace
7853 * \param name the type short name.
7855 * This function tries to load a type, returning the class was found or NULL otherwise.
7856 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7858 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7859 * a type that we would otherwise assume to be available but was not due some error.
7863 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7868 klass = mono_class_from_name_checked (image, name_space, name, &error);
7869 if (!mono_error_ok (&error))
7870 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7876 * mono_class_is_subclass_of:
7877 * \param klass class to probe if it is a subclass of another one
7878 * \param klassc the class we suspect is the base class
7879 * \param check_interfaces whether we should perform interface checks
7881 * This method determines whether \p klass is a subclass of \p klassc.
7883 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7884 * this method return TRUE if the \p klass implements the interface or
7885 * if \p klass is an interface, if one of its base classes is \p klass.
7887 * If \p check_interfaces is false, then if \p klass is not an interface,
7888 * it returns TRUE if the \p klass is a subclass of \p klassc.
7890 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7895 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7896 gboolean check_interfaces)
7898 /* FIXME test for interfaces with variant generic arguments */
7899 mono_class_init (klass);
7900 mono_class_init (klassc);
7902 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7903 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7905 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7908 for (i = 0; i < klass->interface_count; i ++) {
7909 MonoClass *ic = klass->interfaces [i];
7914 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7919 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7922 if (klassc == mono_defaults.object_class)
7929 mono_type_is_generic_argument (MonoType *type)
7931 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7935 mono_class_has_variant_generic_params (MonoClass *klass)
7938 MonoGenericContainer *container;
7940 if (!mono_class_is_ginst (klass))
7943 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7945 for (i = 0; i < container->type_argc; ++i)
7946 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7953 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7955 if (target == candidate)
7958 if (check_for_reference_conv &&
7959 mono_type_is_generic_argument (&target->byval_arg) &&
7960 mono_type_is_generic_argument (&candidate->byval_arg)) {
7961 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7962 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7964 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7967 if (!mono_class_is_assignable_from (target, candidate))
7973 * @container the generic container from the GTD
7974 * @klass: the class to be assigned to
7975 * @oklass: the source class
7977 * Both @klass and @oklass must be instances of the same generic interface.
7979 * Returns: TRUE if @klass can be assigned to a @klass variable
7982 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7985 MonoType **klass_argv, **oklass_argv;
7986 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7987 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
7989 if (klass == oklass)
7992 /*Viable candidates are instances of the same generic interface*/
7993 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7996 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
7997 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
7999 for (j = 0; j < container->type_argc; ++j) {
8000 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8001 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8003 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8007 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8008 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8010 if (param1_class != param2_class) {
8011 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8012 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8014 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8015 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8025 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8027 MonoGenericParam *gparam, *ogparam;
8028 MonoGenericParamInfo *tinfo, *cinfo;
8029 MonoClass **candidate_class;
8030 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8033 if (target == candidate)
8035 if (target->byval_arg.type != candidate->byval_arg.type)
8038 gparam = target->byval_arg.data.generic_param;
8039 ogparam = candidate->byval_arg.data.generic_param;
8040 tinfo = mono_generic_param_info (gparam);
8041 cinfo = mono_generic_param_info (ogparam);
8043 class_constraint_satisfied = FALSE;
8044 valuetype_constraint_satisfied = FALSE;
8046 /*candidate must have a super set of target's special constraints*/
8047 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8048 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8050 if (cinfo->constraints) {
8051 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8052 MonoClass *cc = *candidate_class;
8054 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8055 class_constraint_satisfied = TRUE;
8056 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8057 valuetype_constraint_satisfied = TRUE;
8060 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8061 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8063 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8065 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8067 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8068 valuetype_constraint_satisfied)) {
8073 /*candidate type constraints must be a superset of target's*/
8074 if (tinfo->constraints) {
8075 MonoClass **target_class;
8076 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8077 MonoClass *tc = *target_class;
8080 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8081 * check it's constraints since it satisfy the constraint by itself.
8083 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8086 if (!cinfo->constraints)
8089 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8090 MonoClass *cc = *candidate_class;
8092 if (mono_class_is_assignable_from (tc, cc))
8096 * This happens when we have the following:
8098 * Bar<K> where K : IFace
8099 * Foo<T, U> where T : U where U : IFace
8101 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8104 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8105 if (mono_gparam_is_assignable_from (target, cc))
8109 if (!*candidate_class)
8114 /*candidate itself must have a constraint that satisfy target*/
8115 if (cinfo->constraints) {
8116 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8117 MonoClass *cc = *candidate_class;
8118 if (mono_class_is_assignable_from (target, cc))
8126 * mono_class_is_assignable_from:
8127 * \param klass the class to be assigned to
8128 * \param oklass the source class
8130 * \returns TRUE if an instance of class \p oklass can be assigned to an
8131 * instance of class \p klass
8134 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8137 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8139 mono_class_init (klass);
8141 if (!oklass->inited)
8142 mono_class_init (oklass);
8144 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8147 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8148 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8150 return mono_gparam_is_assignable_from (klass, oklass);
8153 if (MONO_CLASS_IS_INTERFACE (klass)) {
8154 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8155 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8156 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8160 for (i = 0; constraints [i]; ++i) {
8161 if (mono_class_is_assignable_from (klass, constraints [i]))
8169 /* interface_offsets might not be set for dynamic classes */
8170 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8172 * oklass might be a generic type parameter but they have
8173 * interface_offsets set.
8175 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8176 if (!is_ok (&error)) {
8177 mono_error_cleanup (&error);
8182 if (!oklass->interface_bitmap)
8183 /* Happens with generic instances of not-yet created dynamic types */
8185 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8188 if (klass->is_array_special_interface && oklass->rank == 1) {
8189 //XXX we could offset this by having the cast target computed at JIT time
8190 //XXX we could go even further and emit a wrapper that would do the extra type check
8191 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8192 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8194 // 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
8195 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8196 if (iface_klass->valuetype)
8197 iface_klass = iface_klass->cast_class;
8199 //array covariant casts only operates on scalar to scalar
8200 //This is so int[] can't be casted to IComparable<int>[]
8201 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8205 if (mono_class_has_variant_generic_params (klass)) {
8207 mono_class_setup_interfaces (oklass, &error);
8208 if (!mono_error_ok (&error)) {
8209 mono_error_cleanup (&error);
8213 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8214 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8215 MonoClass *iface = oklass->interfaces_packed [i];
8217 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8222 } else if (klass->delegate) {
8223 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8225 }else if (klass->rank) {
8226 MonoClass *eclass, *eoclass;
8228 if (oklass->rank != klass->rank)
8231 /* vectors vs. one dimensional arrays */
8232 if (oklass->byval_arg.type != klass->byval_arg.type)
8235 eclass = klass->cast_class;
8236 eoclass = oklass->cast_class;
8239 * a is b does not imply a[] is b[] when a is a valuetype, and
8240 * b is a reference type.
8243 if (eoclass->valuetype) {
8244 if ((eclass == mono_defaults.enum_class) ||
8245 (eclass == mono_defaults.enum_class->parent) ||
8246 (eclass == mono_defaults.object_class))
8250 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8251 } else if (mono_class_is_nullable (klass)) {
8252 if (mono_class_is_nullable (oklass))
8253 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8255 return mono_class_is_assignable_from (klass->cast_class, oklass);
8256 } else if (klass == mono_defaults.object_class)
8259 return mono_class_has_parent (oklass, klass);
8262 /*Check if @oklass is variant compatible with @klass.*/
8264 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8267 MonoType **klass_argv, **oklass_argv;
8268 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8269 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8271 /*Viable candidates are instances of the same generic interface*/
8272 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8275 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8276 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8278 for (j = 0; j < container->type_argc; ++j) {
8279 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8280 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8282 if (param1_class->valuetype != param2_class->valuetype)
8286 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8287 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8289 if (param1_class != param2_class) {
8290 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8291 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8293 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8294 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8302 /*Check if @candidate implements the interface @target*/
8304 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8308 gboolean is_variant = mono_class_has_variant_generic_params (target);
8310 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8311 if (mono_class_is_variant_compatible_slow (target, candidate))
8316 if (candidate == target)
8319 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8320 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8321 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8323 if (tb && tb->interfaces) {
8324 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8325 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8326 MonoClass *iface_class;
8328 /* we can't realize the type here since it can do pretty much anything. */
8331 iface_class = mono_class_from_mono_type (iface->type);
8332 if (iface_class == target)
8334 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8336 if (mono_class_implement_interface_slow (target, iface_class))
8341 /*setup_interfaces don't mono_class_init anything*/
8342 /*FIXME this doesn't handle primitive type arrays.
8343 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8344 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8346 mono_class_setup_interfaces (candidate, &error);
8347 if (!mono_error_ok (&error)) {
8348 mono_error_cleanup (&error);
8352 for (i = 0; i < candidate->interface_count; ++i) {
8353 if (candidate->interfaces [i] == target)
8356 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8359 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8363 candidate = candidate->parent;
8364 } while (candidate);
8370 * Check if @oklass can be assigned to @klass.
8371 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8374 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8376 if (candidate == target)
8378 if (target == mono_defaults.object_class)
8381 if (mono_class_has_parent (candidate, target))
8384 /*If target is not an interface there is no need to check them.*/
8385 if (MONO_CLASS_IS_INTERFACE (target))
8386 return mono_class_implement_interface_slow (target, candidate);
8388 if (target->delegate && mono_class_has_variant_generic_params (target))
8389 return mono_class_is_variant_compatible (target, candidate, FALSE);
8392 MonoClass *eclass, *eoclass;
8394 if (target->rank != candidate->rank)
8397 /* vectors vs. one dimensional arrays */
8398 if (target->byval_arg.type != candidate->byval_arg.type)
8401 eclass = target->cast_class;
8402 eoclass = candidate->cast_class;
8405 * a is b does not imply a[] is b[] when a is a valuetype, and
8406 * b is a reference type.
8409 if (eoclass->valuetype) {
8410 if ((eclass == mono_defaults.enum_class) ||
8411 (eclass == mono_defaults.enum_class->parent) ||
8412 (eclass == mono_defaults.object_class))
8416 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8418 /*FIXME properly handle nullables */
8419 /*FIXME properly handle (M)VAR */
8424 * mono_class_get_cctor:
8425 * \param klass A MonoClass pointer
8427 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8430 mono_class_get_cctor (MonoClass *klass)
8432 MonoCachedClassInfo cached_info;
8434 if (image_is_dynamic (klass->image)) {
8436 * has_cctor is not set for these classes because mono_class_init () is
8439 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8442 mono_class_init (klass);
8444 if (!klass->has_cctor)
8447 if (mono_class_is_ginst (klass) && !klass->methods)
8448 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8450 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8452 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8453 if (!mono_error_ok (&error))
8454 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8458 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8462 * mono_class_get_finalizer:
8463 * \param klass: The MonoClass pointer
8465 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8468 mono_class_get_finalizer (MonoClass *klass)
8470 MonoCachedClassInfo cached_info;
8473 mono_class_init (klass);
8474 if (!mono_class_has_finalizer (klass))
8477 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8479 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8480 if (!mono_error_ok (&error))
8481 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8484 mono_class_setup_vtable (klass);
8485 return klass->vtable [finalize_slot];
8490 * mono_class_needs_cctor_run:
8491 * \param klass the MonoClass pointer
8492 * \param caller a MonoMethod describing the caller
8494 * Determines whenever the class has a static constructor and whenever it
8495 * needs to be called when executing CALLER.
8498 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8502 method = mono_class_get_cctor (klass);
8504 return (method == caller) ? FALSE : TRUE;
8510 * mono_class_array_element_size:
8513 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8516 mono_class_array_element_size (MonoClass *klass)
8518 MonoType *type = &klass->byval_arg;
8521 switch (type->type) {
8524 case MONO_TYPE_BOOLEAN:
8528 case MONO_TYPE_CHAR:
8537 case MONO_TYPE_CLASS:
8538 case MONO_TYPE_STRING:
8539 case MONO_TYPE_OBJECT:
8540 case MONO_TYPE_SZARRAY:
8541 case MONO_TYPE_ARRAY:
8542 return sizeof (gpointer);
8547 case MONO_TYPE_VALUETYPE:
8548 if (type->data.klass->enumtype) {
8549 type = mono_class_enum_basetype (type->data.klass);
8550 klass = klass->element_class;
8553 return mono_class_instance_size (klass) - sizeof (MonoObject);
8554 case MONO_TYPE_GENERICINST:
8555 type = &type->data.generic_class->container_class->byval_arg;
8558 case MONO_TYPE_MVAR: {
8561 return mono_type_size (type, &align);
8563 case MONO_TYPE_VOID:
8567 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8573 * mono_array_element_size:
8574 * \param ac pointer to a \c MonoArrayClass
8576 * \returns The size of single array element.
8579 mono_array_element_size (MonoClass *ac)
8581 g_assert (ac->rank);
8582 return ac->sizes.element_size;
8589 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8590 MonoGenericContext *context)
8593 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8594 g_assert (mono_error_ok (&error));
8599 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8600 MonoGenericContext *context, MonoError *error)
8604 if (image_is_dynamic (image)) {
8605 MonoClass *tmp_handle_class;
8606 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8608 mono_error_assert_ok (error);
8609 g_assert (tmp_handle_class);
8611 *handle_class = tmp_handle_class;
8613 if (tmp_handle_class == mono_defaults.typehandle_class)
8614 return &((MonoClass*)obj)->byval_arg;
8619 switch (token & 0xff000000) {
8620 case MONO_TOKEN_TYPE_DEF:
8621 case MONO_TOKEN_TYPE_REF:
8622 case MONO_TOKEN_TYPE_SPEC: {
8625 *handle_class = mono_defaults.typehandle_class;
8626 type = mono_type_get_checked (image, token, context, error);
8630 mono_class_init (mono_class_from_mono_type (type));
8631 /* We return a MonoType* as handle */
8634 case MONO_TOKEN_FIELD_DEF: {
8636 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8638 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8642 *handle_class = mono_defaults.fieldhandle_class;
8643 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8647 mono_class_init (klass);
8648 return mono_class_get_field (klass, token);
8650 case MONO_TOKEN_METHOD_DEF:
8651 case MONO_TOKEN_METHOD_SPEC: {
8653 meth = mono_get_method_checked (image, token, NULL, context, error);
8655 *handle_class = mono_defaults.methodhandle_class;
8661 case MONO_TOKEN_MEMBER_REF: {
8662 guint32 cols [MONO_MEMBERREF_SIZE];
8664 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8665 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8666 mono_metadata_decode_blob_size (sig, &sig);
8667 if (*sig == 0x6) { /* it's a field */
8669 MonoClassField *field;
8670 field = mono_field_from_token_checked (image, token, &klass, context, error);
8672 *handle_class = mono_defaults.fieldhandle_class;
8676 meth = mono_get_method_checked (image, token, NULL, context, error);
8678 *handle_class = mono_defaults.methodhandle_class;
8683 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8689 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8691 MonoClass *handle_class;
8693 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8697 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8699 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8702 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8705 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8707 get_cached_class_info = func;
8711 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8713 if (!get_cached_class_info)
8716 return get_cached_class_info (klass, res);
8720 mono_install_get_class_from_name (MonoGetClassFromName func)
8722 get_class_from_name = func;
8726 * mono_class_get_image:
8728 * Use this method to get the \c MonoImage* where this class came from.
8730 * \returns The image where this class is defined.
8733 mono_class_get_image (MonoClass *klass)
8735 return klass->image;
8739 * mono_class_get_element_class:
8740 * \param klass the \c MonoClass to act on
8742 * Use this function to get the element class of an array.
8744 * \returns The element class of an array.
8747 mono_class_get_element_class (MonoClass *klass)
8749 return klass->element_class;
8753 * mono_class_is_valuetype:
8754 * \param klass the \c MonoClass to act on
8756 * Use this method to determine if the provided \c MonoClass* represents a value type,
8757 * or a reference type.
8759 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8762 mono_class_is_valuetype (MonoClass *klass)
8764 return klass->valuetype;
8768 * mono_class_is_enum:
8769 * \param klass the \c MonoClass to act on
8771 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8773 * \returns TRUE if the \c MonoClass represents an enumeration.
8776 mono_class_is_enum (MonoClass *klass)
8778 return klass->enumtype;
8782 * mono_class_enum_basetype:
8783 * \param klass the \c MonoClass to act on
8785 * Use this function to get the underlying type for an enumeration value.
8787 * \returns The underlying type representation for an enumeration.
8790 mono_class_enum_basetype (MonoClass *klass)
8792 if (klass->element_class == klass)
8793 /* SRE or broken types */
8796 return &klass->element_class->byval_arg;
8800 * mono_class_get_parent
8801 * \param klass the \c MonoClass to act on
8803 * \returns The parent class for this class.
8806 mono_class_get_parent (MonoClass *klass)
8808 return klass->parent;
8812 * mono_class_get_nesting_type:
8813 * \param klass the \c MonoClass to act on
8815 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8817 * If the return is NULL, this indicates that this class is not nested.
8819 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8822 mono_class_get_nesting_type (MonoClass *klass)
8824 return klass->nested_in;
8828 * mono_class_get_rank:
8829 * \param klass the MonoClass to act on
8831 * \returns The rank for the array (the number of dimensions).
8834 mono_class_get_rank (MonoClass *klass)
8840 * mono_class_get_name
8841 * \param klass the \c MonoClass to act on
8843 * \returns The name of the class.
8846 mono_class_get_name (MonoClass *klass)
8852 * mono_class_get_namespace:
8853 * \param klass the \c MonoClass to act on
8855 * \returns The namespace of the class.
8858 mono_class_get_namespace (MonoClass *klass)
8860 return klass->name_space;
8864 * mono_class_get_type:
8865 * \param klass the \c MonoClass to act on
8867 * This method returns the internal \c MonoType representation for the class.
8869 * \returns The \c MonoType from the class.
8872 mono_class_get_type (MonoClass *klass)
8874 return &klass->byval_arg;
8878 * mono_class_get_type_token:
8879 * \param klass the \c MonoClass to act on
8881 * This method returns type token for the class.
8883 * \returns The type token for the class.
8886 mono_class_get_type_token (MonoClass *klass)
8888 return klass->type_token;
8892 * mono_class_get_byref_type:
8893 * \param klass the \c MonoClass to act on
8898 mono_class_get_byref_type (MonoClass *klass)
8900 return &klass->this_arg;
8904 * mono_class_num_fields:
8905 * \param klass the \c MonoClass to act on
8907 * \returns The number of static and instance fields in the class.
8910 mono_class_num_fields (MonoClass *klass)
8912 return mono_class_get_field_count (klass);
8916 * mono_class_num_methods:
8917 * \param klass the \c MonoClass to act on
8919 * \returns The number of methods in the class.
8922 mono_class_num_methods (MonoClass *klass)
8924 return mono_class_get_method_count (klass);
8928 * mono_class_num_properties
8929 * \param klass the \c MonoClass to act on
8931 * \returns The number of properties in the class.
8934 mono_class_num_properties (MonoClass *klass)
8936 mono_class_setup_properties (klass);
8938 return mono_class_get_property_info (klass)->count;
8942 * mono_class_num_events:
8943 * \param klass the \c MonoClass to act on
8945 * \returns The number of events in the class.
8948 mono_class_num_events (MonoClass *klass)
8950 mono_class_setup_events (klass);
8952 return mono_class_get_event_info (klass)->count;
8956 * mono_class_get_fields:
8957 * \param klass the \c MonoClass to act on
8959 * This routine is an iterator routine for retrieving the fields in a class.
8961 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
8962 * iterate over all of the elements. When no more values are
8963 * available, the return value is NULL.
8965 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
8968 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8970 MonoClassField* field;
8974 mono_class_setup_fields (klass);
8975 if (mono_class_has_failure (klass))
8977 /* start from the first */
8978 if (mono_class_get_field_count (klass)) {
8979 *iter = &klass->fields [0];
8980 return &klass->fields [0];
8986 field = (MonoClassField *)*iter;
8988 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
8996 * mono_class_get_methods:
8997 * \param klass the \c MonoClass to act on
8999 * This routine is an iterator routine for retrieving the fields in a class.
9001 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9002 * iterate over all of the elements. When no more values are
9003 * available, the return value is NULL.
9005 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9008 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9010 MonoMethod** method;
9014 mono_class_setup_methods (klass);
9017 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9018 * FIXME we should better report this error to the caller
9020 if (!klass->methods)
9022 /* start from the first */
9023 if (mono_class_get_method_count (klass)) {
9024 *iter = &klass->methods [0];
9025 return klass->methods [0];
9031 method = (MonoMethod **)*iter;
9033 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9041 * mono_class_get_virtual_methods:
9043 * Iterate over the virtual methods of KLASS.
9045 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9048 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9050 MonoMethod** method;
9053 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9055 mono_class_setup_methods (klass);
9057 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9058 * FIXME we should better report this error to the caller
9060 if (!klass->methods)
9062 /* start from the first */
9063 method = &klass->methods [0];
9065 method = (MonoMethod **)*iter;
9068 int mcount = mono_class_get_method_count (klass);
9069 while (method < &klass->methods [mcount]) {
9070 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9074 if (method < &klass->methods [mcount]) {
9081 /* Search directly in metadata to avoid calling setup_methods () */
9082 MonoMethod *res = NULL;
9088 start_index = GPOINTER_TO_UINT (*iter);
9091 int first_idx = mono_class_get_first_method_idx (klass);
9092 int mcount = mono_class_get_method_count (klass);
9093 for (i = start_index; i < mcount; ++i) {
9096 /* first_idx points into the methodptr table */
9097 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9099 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9105 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9106 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9108 /* Add 1 here so the if (*iter) check fails */
9109 *iter = GUINT_TO_POINTER (i + 1);
9118 * mono_class_get_properties:
9119 * \param klass the \c MonoClass to act on
9121 * This routine is an iterator routine for retrieving the properties in a class.
9123 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9124 * iterate over all of the elements. When no more values are
9125 * available, the return value is NULL.
9127 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9130 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9132 MonoProperty* property;
9136 mono_class_setup_properties (klass);
9137 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9138 /* start from the first */
9140 *iter = &info->properties [0];
9141 return (MonoProperty *)*iter;
9147 property = (MonoProperty *)*iter;
9149 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9150 if (property < &info->properties [info->count]) {
9152 return (MonoProperty *)*iter;
9158 * mono_class_get_events:
9159 * \param klass the \c MonoClass to act on
9161 * This routine is an iterator routine for retrieving the properties in a class.
9163 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9164 * iterate over all of the elements. When no more values are
9165 * available, the return value is NULL.
9167 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9170 mono_class_get_events (MonoClass* klass, gpointer *iter)
9176 mono_class_setup_events (klass);
9177 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9178 /* start from the first */
9180 *iter = &info->events [0];
9181 return (MonoEvent *)*iter;
9187 event = (MonoEvent *)*iter;
9189 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9190 if (event < &info->events [info->count]) {
9192 return (MonoEvent *)*iter;
9198 * mono_class_get_interfaces
9199 * \param klass the \c MonoClass to act on
9201 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9203 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9204 * iterate over all of the elements. When no more values are
9205 * available, the return value is NULL.
9207 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9210 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9218 mono_class_init (klass);
9219 if (!klass->interfaces_inited) {
9220 mono_class_setup_interfaces (klass, &error);
9221 if (!mono_error_ok (&error)) {
9222 mono_error_cleanup (&error);
9226 /* start from the first */
9227 if (klass->interface_count) {
9228 *iter = &klass->interfaces [0];
9229 return klass->interfaces [0];
9235 iface = (MonoClass **)*iter;
9237 if (iface < &klass->interfaces [klass->interface_count]) {
9245 setup_nested_types (MonoClass *klass)
9248 GList *classes, *nested_classes, *l;
9251 if (klass->nested_classes_inited)
9254 if (!klass->type_token) {
9255 mono_loader_lock ();
9256 klass->nested_classes_inited = TRUE;
9257 mono_loader_unlock ();
9261 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9265 guint32 cols [MONO_NESTED_CLASS_SIZE];
9266 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9267 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9268 if (!mono_error_ok (&error)) {
9269 /*FIXME don't swallow the error message*/
9270 mono_error_cleanup (&error);
9272 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9276 classes = g_list_prepend (classes, nclass);
9278 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9281 nested_classes = NULL;
9282 for (l = classes; l; l = l->next)
9283 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9284 g_list_free (classes);
9286 mono_loader_lock ();
9287 if (!klass->nested_classes_inited) {
9288 mono_class_set_nested_classes_property (klass, nested_classes);
9289 mono_memory_barrier ();
9290 klass->nested_classes_inited = TRUE;
9292 mono_loader_unlock ();
9296 * mono_class_get_nested_types
9297 * \param klass the \c MonoClass to act on
9299 * This routine is an iterator routine for retrieving the nested types of a class.
9300 * This works only if \p klass is non-generic, or a generic type definition.
9302 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9303 * iterate over all of the elements. When no more values are
9304 * available, the return value is NULL.
9306 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9309 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9315 if (!klass->nested_classes_inited)
9316 setup_nested_types (klass);
9319 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9320 /* start from the first */
9321 if (nested_classes) {
9322 *iter = nested_classes;
9323 return (MonoClass *)nested_classes->data;
9325 /* no nested types */
9329 item = (GList *)*iter;
9333 return (MonoClass *)item->data;
9340 * mono_class_is_delegate
9341 * \param klass the \c MonoClass to act on
9343 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9346 mono_class_is_delegate (MonoClass *klass)
9348 return klass->delegate;
9352 * mono_class_implements_interface
9353 * \param klass The MonoClass to act on
9354 * \param interface The interface to check if \p klass implements.
9356 * \returns TRUE if \p klass implements \p interface.
9359 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9361 return mono_class_is_assignable_from (iface, klass);
9365 * mono_field_get_name:
9366 * \param field the \c MonoClassField to act on
9368 * \returns The name of the field.
9371 mono_field_get_name (MonoClassField *field)
9377 * mono_field_get_type:
9378 * \param field the \c MonoClassField to act on
9379 * \returns \c MonoType of the field.
9382 mono_field_get_type (MonoClassField *field)
9385 MonoType *type = mono_field_get_type_checked (field, &error);
9386 if (!mono_error_ok (&error)) {
9387 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9388 mono_error_cleanup (&error);
9395 * mono_field_get_type_checked:
9396 * \param field the \c MonoClassField to act on
9397 * \param error used to return any error found while retrieving \p field type
9399 * \returns \c MonoType of the field.
9402 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9406 mono_field_resolve_type (field, error);
9411 * mono_field_get_parent:
9412 * \param field the \c MonoClassField to act on
9414 * \returns \c MonoClass where the field was defined.
9417 mono_field_get_parent (MonoClassField *field)
9419 return field->parent;
9423 * mono_field_get_flags;
9424 * \param field the \c MonoClassField to act on
9426 * The metadata flags for a field are encoded using the
9427 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9429 * \returns The flags for the field.
9432 mono_field_get_flags (MonoClassField *field)
9435 return mono_field_resolve_flags (field);
9436 return field->type->attrs;
9440 * mono_field_get_offset:
9441 * \param field the \c MonoClassField to act on
9443 * \returns The field offset.
9446 mono_field_get_offset (MonoClassField *field)
9448 return field->offset;
9452 mono_field_get_rva (MonoClassField *field)
9456 MonoClass *klass = field->parent;
9457 MonoFieldDefaultValue *def_values;
9459 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9461 def_values = mono_class_get_field_def_values (klass);
9463 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9465 mono_class_set_field_def_values (klass, def_values);
9468 field_index = mono_field_get_index (field);
9470 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9471 int first_field_idx = mono_class_get_first_field_idx (klass);
9472 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9474 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9475 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9478 return def_values [field_index].data;
9482 * mono_field_get_data:
9483 * \param field the \c MonoClassField to act on
9485 * \returns A pointer to the metadata constant value or to the field
9486 * data if it has an RVA flag.
9489 mono_field_get_data (MonoClassField *field)
9491 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9492 MonoTypeEnum def_type;
9494 return mono_class_get_field_default_value (field, &def_type);
9495 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9496 return mono_field_get_rva (field);
9503 * mono_property_get_name:
9504 * \param prop the \c MonoProperty to act on
9505 * \returns The name of the property
9508 mono_property_get_name (MonoProperty *prop)
9514 * mono_property_get_set_method
9515 * \param prop the \c MonoProperty to act on.
9516 * \returns The setter method of the property, a \c MonoMethod.
9519 mono_property_get_set_method (MonoProperty *prop)
9525 * mono_property_get_get_method
9526 * \param prop the MonoProperty to act on.
9527 * \returns The getter method of the property (A \c MonoMethod)
9530 mono_property_get_get_method (MonoProperty *prop)
9536 * mono_property_get_parent:
9537 * \param prop the \c MonoProperty to act on.
9538 * \returns The \c MonoClass where the property was defined.
9541 mono_property_get_parent (MonoProperty *prop)
9543 return prop->parent;
9547 * mono_property_get_flags:
9548 * \param prop the \c MonoProperty to act on.
9550 * The metadata flags for a property are encoded using the
9551 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9553 * \returns The flags for the property.
9556 mono_property_get_flags (MonoProperty *prop)
9562 * mono_event_get_name:
9563 * \param event the MonoEvent to act on
9564 * \returns The name of the event.
9567 mono_event_get_name (MonoEvent *event)
9573 * mono_event_get_add_method:
9574 * \param event The \c MonoEvent to act on.
9575 * \returns The \c add method for the event, a \c MonoMethod.
9578 mono_event_get_add_method (MonoEvent *event)
9584 * mono_event_get_remove_method:
9585 * \param event The \c MonoEvent to act on.
9586 * \returns The \c remove method for the event, a \c MonoMethod.
9589 mono_event_get_remove_method (MonoEvent *event)
9591 return event->remove;
9595 * mono_event_get_raise_method:
9596 * \param event The \c MonoEvent to act on.
9597 * \returns The \c raise method for the event, a \c MonoMethod.
9600 mono_event_get_raise_method (MonoEvent *event)
9602 return event->raise;
9606 * mono_event_get_parent:
9607 * \param event the MonoEvent to act on.
9608 * \returns The \c MonoClass where the event is defined.
9611 mono_event_get_parent (MonoEvent *event)
9613 return event->parent;
9617 * mono_event_get_flags
9618 * \param event the \c MonoEvent to act on.
9620 * The metadata flags for an event are encoded using the
9621 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9623 * \returns The flags for the event.
9626 mono_event_get_flags (MonoEvent *event)
9628 return event->attrs;
9632 * mono_class_get_method_from_name:
9633 * \param klass where to look for the method
9634 * \param name name of the method
9635 * \param param_count number of parameters. -1 for any number.
9637 * Obtains a \c MonoMethod with a given name and number of parameters.
9638 * It only works if there are no multiple signatures for any given method name.
9641 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9643 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9647 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9649 MonoMethod *res = NULL;
9652 /* Search directly in the metadata to avoid calling setup_methods () */
9653 int first_idx = mono_class_get_first_method_idx (klass);
9654 int mcount = mono_class_get_method_count (klass);
9655 for (i = 0; i < mcount; ++i) {
9657 guint32 cols [MONO_METHOD_SIZE];
9659 MonoMethodSignature *sig;
9661 /* first_idx points into the methodptr table */
9662 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9664 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9665 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9667 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9670 if (param_count == -1) {
9674 sig = mono_method_signature_checked (method, &error);
9676 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9679 if (sig->param_count == param_count) {
9690 * mono_class_get_method_from_name_flags:
9691 * \param klass where to look for the method
9692 * \param name_space name of the method
9693 * \param param_count number of parameters. -1 for any number.
9694 * \param flags flags which must be set in the method
9696 * Obtains a \c MonoMethod with a given name and number of parameters.
9697 * It only works if there are no multiple signatures for any given method name.
9700 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9702 MonoMethod *res = NULL;
9705 mono_class_init (klass);
9707 if (mono_class_is_ginst (klass) && !klass->methods) {
9708 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9711 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9712 if (!mono_error_ok (&error))
9713 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9718 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9719 mono_class_setup_methods (klass);
9721 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9722 See mono/tests/array_load_exception.il
9723 FIXME we should better report this error to the caller
9725 if (!klass->methods)
9727 int mcount = mono_class_get_method_count (klass);
9728 for (i = 0; i < mcount; ++i) {
9729 MonoMethod *method = klass->methods [i];
9731 if (method->name[0] == name [0] &&
9732 !strcmp (name, method->name) &&
9733 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9734 ((method->flags & flags) == flags)) {
9741 res = find_method_in_metadata (klass, name, param_count, flags);
9748 * mono_class_set_failure:
9749 * \param klass class in which the failure was detected
9750 * \param ex_type the kind of exception/error to be thrown (later)
9751 * \param ex_data exception data (specific to each type of exception/error)
9753 * Keep a detected failure informations in the class for later processing.
9754 * Note that only the first failure is kept.
9756 * LOCKING: Acquires the loader lock.
9759 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9761 g_assert (boxed_error != NULL);
9763 if (mono_class_has_failure (klass))
9766 mono_loader_lock ();
9767 klass->has_failure = 1;
9768 mono_class_set_exception_data (klass, boxed_error);
9769 mono_loader_unlock ();
9775 mono_class_has_failure (const MonoClass *klass)
9777 g_assert (klass != NULL);
9778 return klass->has_failure != 0;
9783 * mono_class_set_type_load_failure:
9784 * \param klass class in which the failure was detected
9785 * \param fmt \c printf -style error message string.
9787 * Collect detected failure informaion in the class for later processing.
9788 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9789 * Note that only the first failure is kept.
9791 * LOCKING: Acquires the loader lock.
9793 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9796 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9798 MonoError prepare_error;
9801 if (mono_class_has_failure (klass))
9804 error_init (&prepare_error);
9806 va_start (args, fmt);
9807 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9810 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9811 mono_error_cleanup (&prepare_error);
9812 return mono_class_set_failure (klass, box);
9816 * mono_classes_init:
9818 * Initialize the resources used by this module.
9821 mono_classes_init (void)
9823 mono_os_mutex_init (&classes_mutex);
9825 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9826 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9828 mono_counters_register ("MonoClassDef count",
9829 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9830 mono_counters_register ("MonoClassGtd count",
9831 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9832 mono_counters_register ("MonoClassGenericInst count",
9833 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9834 mono_counters_register ("MonoClassGenericParam count",
9835 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9836 mono_counters_register ("MonoClassArray count",
9837 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9838 mono_counters_register ("MonoClassPointer count",
9839 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9840 mono_counters_register ("Inflated methods size",
9841 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9842 mono_counters_register ("Inflated classes size",
9843 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9844 mono_counters_register ("MonoClass size",
9845 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9849 * mono_classes_cleanup:
9851 * Free the resources used by this module.
9854 mono_classes_cleanup (void)
9856 mono_native_tls_free (setup_fields_tls_id);
9857 mono_native_tls_free (init_pending_tls_id);
9859 if (global_interface_bitset)
9860 mono_bitset_free (global_interface_bitset);
9861 global_interface_bitset = NULL;
9862 mono_os_mutex_destroy (&classes_mutex);
9866 * mono_class_get_exception_for_failure:
9867 * \param klass class in which the failure was detected
9869 * \returns a constructed MonoException than the caller can then throw
9870 * using mono_raise_exception - or NULL if no failure is present (or
9871 * doesn't result in an exception).
9874 mono_class_get_exception_for_failure (MonoClass *klass)
9876 if (!mono_class_has_failure (klass))
9878 MonoError unboxed_error;
9879 error_init (&unboxed_error);
9880 mono_error_set_for_class_failure (&unboxed_error, klass);
9881 return mono_error_convert_to_exception (&unboxed_error);
9885 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9887 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9888 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9890 if (outer_klass == inner_klass)
9892 inner_klass = inner_klass->nested_in;
9893 } while (inner_klass);
9898 mono_class_get_generic_type_definition (MonoClass *klass)
9900 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9901 return gklass ? gklass->container_class : klass;
9905 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9907 * Generic instantiations are ignored for all super types of @klass.
9909 * Visibility checks ignoring generic instantiations.
9912 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9915 klass = mono_class_get_generic_type_definition (klass);
9916 parent = mono_class_get_generic_type_definition (parent);
9917 mono_class_setup_supertypes (klass);
9919 for (i = 0; i < klass->idepth; ++i) {
9920 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9926 * Subtype can only access parent members with family protection if the site object
9927 * is subclass of Subtype. For example:
9928 * class A { protected int x; }
9930 * void valid_access () {
9934 * void invalid_access () {
9941 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9943 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9946 if (context_klass == NULL)
9948 /*if access_klass is not member_klass context_klass must be type compat*/
9949 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9955 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9958 if (accessing == accessed)
9960 if (!accessed || !accessing)
9963 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9964 * anywhere so untrusted friends are not safe to access platform's code internals */
9965 if (mono_security_core_clr_enabled ()) {
9966 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9970 mono_assembly_load_friends (accessed);
9971 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9972 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
9973 /* Be conservative with checks */
9976 if (strcmp (accessing->aname.name, friend_->name))
9978 if (friend_->public_key_token [0]) {
9979 if (!accessing->aname.public_key_token [0])
9981 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
9990 * If klass is a generic type or if it is derived from a generic type, return the
9991 * MonoClass of the generic definition
9992 * Returns NULL if not found
9995 get_generic_definition_class (MonoClass *klass)
9998 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9999 if (gklass && gklass->container_class)
10000 return gklass->container_class;
10001 klass = klass->parent;
10007 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10010 for (i = 0; i < ginst->type_argc; ++i) {
10011 MonoType *type = ginst->type_argv[i];
10012 switch (type->type) {
10013 case MONO_TYPE_SZARRAY:
10014 if (!can_access_type (access_klass, type->data.klass))
10017 case MONO_TYPE_ARRAY:
10018 if (!can_access_type (access_klass, type->data.array->eklass))
10021 case MONO_TYPE_PTR:
10022 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10025 case MONO_TYPE_CLASS:
10026 case MONO_TYPE_VALUETYPE:
10027 case MONO_TYPE_GENERICINST:
10028 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10038 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10042 if (access_klass == member_klass)
10045 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10048 if (access_klass->element_class && !access_klass->enumtype)
10049 access_klass = access_klass->element_class;
10051 if (member_klass->element_class && !member_klass->enumtype)
10052 member_klass = member_klass->element_class;
10054 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10056 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10059 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10062 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10065 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10068 /*Non nested type with nested visibility. We just fail it.*/
10069 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10072 switch (access_level) {
10073 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10074 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10076 case TYPE_ATTRIBUTE_PUBLIC:
10079 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10082 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10083 return is_nesting_type (member_klass, access_klass);
10085 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10086 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10088 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10089 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10091 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10092 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10093 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10095 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10096 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10097 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10102 /* FIXME: check visibility of type, too */
10104 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10106 MonoClass *member_generic_def;
10107 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10110 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10111 if (((access_gklass && access_gklass->container_class) ||
10112 mono_class_is_gtd (access_klass)) &&
10113 (member_generic_def = get_generic_definition_class (member_klass))) {
10114 MonoClass *access_container;
10116 if (mono_class_is_gtd (access_klass))
10117 access_container = access_klass;
10119 access_container = access_gklass->container_class;
10121 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10125 /* Partition I 8.5.3.2 */
10126 /* the access level values are the same for fields and methods */
10127 switch (access_level) {
10128 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10129 /* same compilation unit */
10130 return access_klass->image == member_klass->image;
10131 case FIELD_ATTRIBUTE_PRIVATE:
10132 return access_klass == member_klass;
10133 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10134 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10135 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10138 case FIELD_ATTRIBUTE_ASSEMBLY:
10139 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10140 case FIELD_ATTRIBUTE_FAMILY:
10141 if (is_valid_family_access (access_klass, member_klass, context_klass))
10144 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10145 if (is_valid_family_access (access_klass, member_klass, context_klass))
10147 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10148 case FIELD_ATTRIBUTE_PUBLIC:
10155 * mono_method_can_access_field:
10156 * \param method Method that will attempt to access the field
10157 * \param field the field to access
10159 * Used to determine if a method is allowed to access the specified field.
10161 * \returns TRUE if the given \p method is allowed to access the \p field while following
10162 * the accessibility rules of the CLI.
10165 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10167 /* FIXME: check all overlapping fields */
10168 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10170 MonoClass *nested = method->klass->nested_in;
10172 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10175 nested = nested->nested_in;
10182 * mono_method_can_access_method:
10183 * \param method Method that will attempt to access the other method
10184 * \param called the method that we want to probe for accessibility.
10186 * Used to determine if the \p method is allowed to access the specified \p called method.
10188 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10189 * the accessibility rules of the CLI.
10192 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10194 method = mono_method_get_method_definition (method);
10195 called = mono_method_get_method_definition (called);
10196 return mono_method_can_access_method_full (method, called, NULL);
10200 * mono_method_can_access_method_full:
10201 * @method: The caller method
10202 * @called: The called method
10203 * @context_klass: The static type on stack of the owner @called object used
10205 * This function must be used with instance calls, as they have more strict family accessibility.
10206 * It can be used with static methods, but context_klass should be NULL.
10208 * Returns: TRUE if caller have proper visibility and acessibility to @called
10211 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10213 /* Wrappers are except from access checks */
10214 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10217 MonoClass *access_class = method->klass;
10218 MonoClass *member_class = called->klass;
10219 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10221 MonoClass *nested = access_class->nested_in;
10223 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10226 nested = nested->nested_in;
10233 can = can_access_type (access_class, member_class);
10235 MonoClass *nested = access_class->nested_in;
10237 can = can_access_type (nested, member_class);
10240 nested = nested->nested_in;
10247 if (called->is_inflated) {
10248 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10249 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10258 * mono_method_can_access_field_full:
10259 * @method: The caller method
10260 * @field: The accessed field
10261 * @context_klass: The static type on stack of the owner @field object used
10263 * This function must be used with instance fields, as they have more strict family accessibility.
10264 * It can be used with static fields, but context_klass should be NULL.
10266 * Returns: TRUE if caller have proper visibility and acessibility to @field
10269 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10271 MonoClass *access_class = method->klass;
10272 MonoClass *member_class = field->parent;
10273 /* FIXME: check all overlapping fields */
10274 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10276 MonoClass *nested = access_class->nested_in;
10278 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10281 nested = nested->nested_in;
10288 can = can_access_type (access_class, member_class);
10290 MonoClass *nested = access_class->nested_in;
10292 can = can_access_type (nested, member_class);
10295 nested = nested->nested_in;
10305 * mono_class_can_access_class:
10306 * @source_class: The source class
10307 * @target_class: The accessed class
10309 * This function returns is @target_class is visible to @source_class
10311 * Returns: TRUE if source have proper visibility and acessibility to target
10314 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10316 return can_access_type (source_class, target_class);
10320 * mono_type_is_valid_enum_basetype:
10321 * \param type The MonoType to check
10322 * \returns TRUE if the type can be used as the basetype of an enum
10324 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10325 switch (type->type) {
10328 case MONO_TYPE_BOOLEAN:
10331 case MONO_TYPE_CHAR:
10345 * mono_class_is_valid_enum:
10346 * \param klass An enum class to be validated
10348 * This method verify the required properties an enum should have.
10350 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10351 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10352 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10354 * \returns TRUE if the informed enum class is valid
10357 mono_class_is_valid_enum (MonoClass *klass)
10359 MonoClassField * field;
10360 gpointer iter = NULL;
10361 gboolean found_base_field = FALSE;
10363 g_assert (klass->enumtype);
10364 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10365 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10369 if (!mono_class_is_auto_layout (klass))
10372 while ((field = mono_class_get_fields (klass, &iter))) {
10373 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10374 if (found_base_field)
10376 found_base_field = TRUE;
10377 if (!mono_type_is_valid_enum_basetype (field->type))
10382 if (!found_base_field)
10385 if (mono_class_get_method_count (klass) > 0)
10392 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10394 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10398 * mono_class_setup_interface_id:
10400 * Initializes MonoClass::interface_id if required.
10402 * LOCKING: Acquires the loader lock.
10405 mono_class_setup_interface_id (MonoClass *klass)
10407 mono_loader_lock ();
10408 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10409 klass->interface_id = mono_get_unique_iid (klass);
10410 mono_loader_unlock ();
10414 * mono_class_setup_interfaces:
10416 * Initialize klass->interfaces/interfaces_count.
10417 * LOCKING: Acquires the loader lock.
10418 * This function can fail the type.
10421 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10423 int i, interface_count;
10424 MonoClass **interfaces;
10426 error_init (error);
10428 if (klass->interfaces_inited)
10431 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10432 MonoType *args [1];
10434 /* generic IList, ICollection, IEnumerable */
10435 interface_count = 2;
10436 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10438 args [0] = &klass->element_class->byval_arg;
10439 interfaces [0] = mono_class_bind_generic_parameters (
10440 mono_defaults.generic_ilist_class, 1, args, FALSE);
10441 interfaces [1] = mono_class_bind_generic_parameters (
10442 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10443 } else if (mono_class_is_ginst (klass)) {
10444 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10446 mono_class_setup_interfaces (gklass, error);
10447 if (!mono_error_ok (error)) {
10448 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10452 interface_count = gklass->interface_count;
10453 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10454 for (i = 0; i < interface_count; i++) {
10455 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10456 if (!mono_error_ok (error)) {
10457 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10462 interface_count = 0;
10466 mono_loader_lock ();
10467 if (!klass->interfaces_inited) {
10468 klass->interface_count = interface_count;
10469 klass->interfaces = interfaces;
10471 mono_memory_barrier ();
10473 klass->interfaces_inited = TRUE;
10475 mono_loader_unlock ();
10479 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10481 MonoClass *klass = field->parent;
10482 MonoImage *image = klass->image;
10483 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10485 int field_idx = field - klass->fields;
10487 error_init (error);
10490 MonoClassField *gfield = >d->fields [field_idx];
10491 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10492 if (!mono_error_ok (error)) {
10493 char *full_name = mono_type_get_full_name (gtd);
10494 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));
10495 g_free (full_name);
10498 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10499 if (!mono_error_ok (error)) {
10500 char *full_name = mono_type_get_full_name (klass);
10501 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));
10502 g_free (full_name);
10506 guint32 cols [MONO_FIELD_SIZE];
10507 MonoGenericContainer *container = NULL;
10508 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10510 /*FIXME, in theory we do not lazy load SRE fields*/
10511 g_assert (!image_is_dynamic (image));
10513 if (mono_class_is_gtd (klass)) {
10514 container = mono_class_get_generic_container (klass);
10516 container = mono_class_get_generic_container (gtd);
10517 g_assert (container);
10520 /* first_field_idx and idx points into the fieldptr table */
10521 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10523 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10524 char *full_name = mono_type_get_full_name (klass);
10525 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10526 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10527 g_free (full_name);
10531 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10533 mono_metadata_decode_value (sig, &sig);
10534 /* FIELD signature == 0x06 */
10535 g_assert (*sig == 0x06);
10537 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10539 char *full_name = mono_type_get_full_name (klass);
10540 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));
10541 g_free (full_name);
10544 mono_memory_barrier ();
10545 field->type = ftype;
10549 mono_field_resolve_flags (MonoClassField *field)
10551 MonoClass *klass = field->parent;
10552 MonoImage *image = klass->image;
10553 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10554 int field_idx = field - klass->fields;
10557 MonoClassField *gfield = >d->fields [field_idx];
10558 return mono_field_get_flags (gfield);
10560 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10562 /*FIXME, in theory we do not lazy load SRE fields*/
10563 g_assert (!image_is_dynamic (image));
10565 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10570 * mono_class_get_fields_lazy:
10571 * \param klass the MonoClass to act on
10573 * This routine is an iterator routine for retrieving the fields in a class.
10574 * Only minimal information about fields are loaded. Accessors must be used
10575 * for all MonoClassField returned.
10577 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10578 * iterate over all of the elements. When no more values are
10579 * available, the return value is NULL.
10581 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10584 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10586 MonoClassField* field;
10590 mono_class_setup_basic_field_info (klass);
10591 if (!klass->fields)
10593 /* start from the first */
10594 if (mono_class_get_field_count (klass)) {
10595 *iter = &klass->fields [0];
10596 return (MonoClassField *)*iter;
10602 field = (MonoClassField *)*iter;
10604 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10606 return (MonoClassField *)*iter;
10612 mono_class_full_name (MonoClass *klass)
10614 return mono_type_full_name (&klass->byval_arg);
10617 /* Declare all shared lazy type lookup functions */
10618 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10621 * mono_method_get_base_method:
10622 * \param method a method
10623 * \param definition if true, get the definition
10624 * \param error set on failure
10626 * Given a virtual method associated with a subclass, return the corresponding
10627 * method from an ancestor. If \p definition is FALSE, returns the method in the
10628 * superclass of the given method. If \p definition is TRUE, return the method
10629 * in the ancestor class where it was first declared. The type arguments will
10630 * be inflated in the ancestor classes. If the method is not associated with a
10631 * class, or isn't virtual, returns the method itself. On failure returns NULL
10632 * and sets \p error.
10635 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10637 MonoClass *klass, *parent;
10638 MonoGenericContext *generic_inst = NULL;
10639 MonoMethod *result = NULL;
10642 if (method->klass == NULL)
10645 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10646 MONO_CLASS_IS_INTERFACE (method->klass) ||
10647 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10650 slot = mono_method_get_vtable_slot (method);
10654 klass = method->klass;
10655 if (mono_class_is_ginst (klass)) {
10656 generic_inst = mono_class_get_context (klass);
10657 klass = mono_class_get_generic_class (klass)->container_class;
10662 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10663 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10664 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10665 or klass is the generic container class and generic_inst is the instantiation.
10667 when we go to the parent, if the parent is an open constructed type, we need to
10668 replace the type parameters by the definitions from the generic_inst, and then take it
10669 apart again into the klass and the generic_inst.
10671 For cases like this:
10672 class C<T> : B<T, int> {
10673 public override void Foo () { ... }
10675 class B<U,V> : A<HashMap<U,V>> {
10676 public override void Foo () { ... }
10679 public virtual void Foo () { ... }
10682 if at each iteration the parent isn't open, we can skip inflating it. if at some
10683 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10686 MonoGenericContext *parent_inst = NULL;
10687 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10688 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10689 return_val_if_nok (error, NULL);
10691 if (mono_class_is_ginst (parent)) {
10692 parent_inst = mono_class_get_context (parent);
10693 parent = mono_class_get_generic_class (parent)->container_class;
10696 mono_class_setup_vtable (parent);
10697 if (parent->vtable_size <= slot)
10700 generic_inst = parent_inst;
10703 klass = klass->parent;
10706 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10707 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10708 return_val_if_nok (error, NULL);
10710 generic_inst = NULL;
10712 if (mono_class_is_ginst (klass)) {
10713 generic_inst = mono_class_get_context (klass);
10714 klass = mono_class_get_generic_class (klass)->container_class;
10719 if (generic_inst) {
10720 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10721 return_val_if_nok (error, NULL);
10724 if (klass == method->klass)
10727 /*This is possible if definition == FALSE.
10728 * Do it here to be really sure we don't read invalid memory.
10730 if (slot >= klass->vtable_size)
10733 mono_class_setup_vtable (klass);
10735 result = klass->vtable [slot];
10736 if (result == NULL) {
10737 /* It is an abstract method */
10738 gboolean found = FALSE;
10739 gpointer iter = NULL;
10740 while ((result = mono_class_get_methods (klass, &iter))) {
10741 if (result->slot == slot) {
10746 /* found might be FALSE if we looked in an abstract class
10747 * that doesn't override an abstract method of its
10749 * abstract class Base {
10750 * public abstract void Foo ();
10752 * abstract class Derived : Base { }
10753 * class Child : Derived {
10754 * public override void Foo () { }
10757 * if m was Child.Foo and we ask for the base method,
10758 * then we get here with klass == Derived and found == FALSE
10760 /* but it shouldn't be the case that if we're looking
10761 * for the definition and didn't find a result; the
10762 * loop above should've taken us as far as we could
10764 g_assert (!(definition && !found));
10769 g_assert (result != NULL);