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 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4041 dslot = mono_method_get_vtable_slot (decl);
4043 mono_class_set_type_load_failure (klass, "");
4047 dslot += mono_class_interface_offset (klass, decl->klass);
4048 vtable [dslot] = override;
4049 if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4051 * If override from an interface, then it is an override of a default interface method,
4052 * don't override its slot.
4054 vtable [dslot]->slot = dslot;
4057 if (mono_security_core_clr_enabled ())
4058 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4064 * LOCKING: this is supposed to be called with the loader lock held.
4067 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4071 MonoMethod **vtable = NULL;
4072 int i, max_vtsize = 0, cur_slot = 0;
4074 GPtrArray *ifaces = NULL;
4075 GHashTable *override_map = NULL;
4077 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4078 int first_non_interface_slot;
4080 GSList *virt_methods = NULL, *l;
4081 int stelemref_slot = 0;
4086 if (overrides && !verify_class_overrides (klass, overrides, onum))
4089 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4090 if (!mono_error_ok (&error)) {
4091 char *name = mono_type_get_full_name (klass);
4092 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4094 mono_error_cleanup (&error);
4096 } else if (ifaces) {
4097 for (i = 0; i < ifaces->len; i++) {
4098 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4099 max_vtsize += mono_class_get_method_count (ic);
4101 g_ptr_array_free (ifaces, TRUE);
4105 if (klass->parent) {
4106 mono_class_init (klass->parent);
4107 mono_class_setup_vtable_full (klass->parent, in_setup);
4109 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4112 max_vtsize += klass->parent->vtable_size;
4113 cur_slot = klass->parent->vtable_size;
4116 max_vtsize += mono_class_get_method_count (klass);
4118 /*Array have a slot for stelemref*/
4119 if (mono_class_need_stelemref_method (klass)) {
4120 stelemref_slot = cur_slot;
4125 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4127 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4128 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4131 max_iid = klass->max_interface_id;
4132 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4134 /* Optimized version for generic instances */
4135 if (mono_class_is_ginst (klass)) {
4137 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4140 mono_class_setup_vtable_full (gklass, in_setup);
4141 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4144 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4145 klass->vtable_size = gklass->vtable_size;
4146 for (i = 0; i < gklass->vtable_size; ++i)
4147 if (gklass->vtable [i]) {
4148 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4149 if (!mono_error_ok (&error)) {
4150 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4151 mono_error_cleanup (&error);
4155 tmp [i]->slot = gklass->vtable [i]->slot;
4157 mono_memory_barrier ();
4158 klass->vtable = tmp;
4160 /* Have to set method->slot for abstract virtual methods */
4161 if (klass->methods && gklass->methods) {
4162 int mcount = mono_class_get_method_count (klass);
4163 for (i = 0; i < mcount; ++i)
4164 if (klass->methods [i]->slot == -1)
4165 klass->methods [i]->slot = gklass->methods [i]->slot;
4171 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4173 if (klass->parent && klass->parent->vtable_size) {
4174 MonoClass *parent = klass->parent;
4177 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4179 // Also inherit parent interface vtables, just as a starting point.
4180 // This is needed otherwise bug-77127.exe fails when the property methods
4181 // have different names in the iterface and the class, because for child
4182 // classes the ".override" information is not used anymore.
4183 for (i = 0; i < parent->interface_offsets_count; i++) {
4184 MonoClass *parent_interface = parent->interfaces_packed [i];
4185 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4186 /*FIXME this is now dead code as this condition will never hold true.
4187 Since interface offsets are inherited then the offset of an interface implemented
4188 by a parent will never be the out of it's vtable boundary.
4190 if (interface_offset >= parent->vtable_size) {
4191 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4194 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4195 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4196 int mcount = mono_class_get_method_count (parent_interface);
4197 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4198 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4199 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4200 parent_interface_offset + j, parent_interface_offset, j,
4201 interface_offset + j, interface_offset, j));
4208 /*Array have a slot for stelemref*/
4209 if (mono_class_need_stelemref_method (klass)) {
4210 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4212 method->slot = stelemref_slot;
4214 g_assert (method->slot == stelemref_slot);
4216 vtable [stelemref_slot] = method;
4219 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4221 /* Process overrides from interface default methods */
4222 // FIXME: Ordering between interfaces
4223 for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4224 ic = klass->interfaces_packed [ifindex];
4226 mono_class_setup_methods (ic);
4227 if (mono_class_has_failure (ic))
4230 MonoMethod **iface_overrides;
4232 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4234 for (int i = 0; i < iface_onum; i++) {
4235 MonoMethod *decl = iface_overrides [i*2];
4236 MonoMethod *override = iface_overrides [i*2 + 1];
4237 if (!apply_override (klass, vtable, decl, override))
4241 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4242 g_hash_table_insert (override_map, decl, override);
4244 g_free (iface_overrides);
4248 /* override interface methods */
4249 for (i = 0; i < onum; i++) {
4250 MonoMethod *decl = overrides [i*2];
4251 MonoMethod *override = overrides [i*2 + 1];
4252 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4253 if (!apply_override (klass, vtable, decl, override))
4257 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4258 g_hash_table_insert (override_map, decl, override);
4262 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4263 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4266 * Create a list of virtual methods to avoid calling
4267 * mono_class_get_virtual_methods () which is slow because of the metadata
4271 gpointer iter = NULL;
4274 virt_methods = NULL;
4275 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4276 virt_methods = g_slist_prepend (virt_methods, cm);
4278 if (mono_class_has_failure (klass))
4282 // Loop on all implemented interfaces...
4283 for (i = 0; i < klass->interface_offsets_count; i++) {
4284 MonoClass *parent = klass->parent;
4286 gboolean interface_is_explicitly_implemented_by_class;
4289 ic = klass->interfaces_packed [i];
4290 ic_offset = mono_class_interface_offset (klass, ic);
4292 mono_class_setup_methods (ic);
4293 if (mono_class_has_failure (ic))
4296 // Check if this interface is explicitly implemented (instead of just inherited)
4297 if (parent != NULL) {
4298 int implemented_interfaces_index;
4299 interface_is_explicitly_implemented_by_class = FALSE;
4300 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4301 if (ic == klass->interfaces [implemented_interfaces_index]) {
4302 interface_is_explicitly_implemented_by_class = TRUE;
4307 interface_is_explicitly_implemented_by_class = TRUE;
4310 // Loop on all interface methods...
4311 int mcount = mono_class_get_method_count (ic);
4312 for (im_index = 0; im_index < mcount; im_index++) {
4313 MonoMethod *im = ic->methods [im_index];
4314 int im_slot = ic_offset + im->slot;
4315 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4317 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4320 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4322 // If there is an explicit implementation, just use it right away,
4323 // otherwise look for a matching method
4324 if (override_im == NULL) {
4328 // First look for a suitable method among the class methods
4329 for (l = virt_methods; l; l = l->next) {
4330 cm = (MonoMethod *)l->data;
4331 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)));
4332 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4333 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4334 vtable [im_slot] = cm;
4335 /* Why do we need this? */
4340 TRACE_INTERFACE_VTABLE (printf ("\n"));
4341 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4345 // If the slot is still empty, look in all the inherited virtual methods...
4346 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4347 MonoClass *parent = klass->parent;
4348 // Reverse order, so that last added methods are preferred
4349 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4350 MonoMethod *cm = parent->vtable [cm_index];
4352 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));
4353 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4354 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4355 vtable [im_slot] = cm;
4356 /* Why do we need this? */
4362 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4364 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4368 if (vtable [im_slot] == NULL) {
4369 if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4370 TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
4371 vtable [im_slot] = im;
4375 g_assert (vtable [im_slot] == override_im);
4380 // If the class is not abstract, check that all its interface slots are full.
4381 // The check is done here and not directly at the end of the loop above because
4382 // it can happen (for injected generic array interfaces) that the same slot is
4383 // processed multiple times (those interfaces have overlapping slots), and it
4384 // will not always be the first pass the one that fills the slot.
4385 if (!mono_class_is_abstract (klass)) {
4386 for (i = 0; i < klass->interface_offsets_count; i++) {
4390 ic = klass->interfaces_packed [i];
4391 ic_offset = mono_class_interface_offset (klass, ic);
4393 int mcount = mono_class_get_method_count (ic);
4394 for (im_index = 0; im_index < mcount; im_index++) {
4395 MonoMethod *im = ic->methods [im_index];
4396 int im_slot = ic_offset + im->slot;
4398 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4401 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4402 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4403 if (vtable [im_slot] == NULL) {
4404 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4411 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4412 for (l = virt_methods; l; l = l->next) {
4413 cm = (MonoMethod *)l->data;
4415 * If the method is REUSE_SLOT, we must check in the
4416 * base class for a method to override.
4418 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4420 for (k = klass->parent; k ; k = k->parent) {
4425 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4426 MonoMethodSignature *cmsig, *m1sig;
4428 cmsig = mono_method_signature (cm);
4429 m1sig = mono_method_signature (m1);
4431 if (!cmsig || !m1sig) {
4432 /* FIXME proper error message */
4433 mono_class_set_type_load_failure (klass, "");
4437 if (!strcmp(cm->name, m1->name) &&
4438 mono_metadata_signature_equal (cmsig, m1sig)) {
4440 if (mono_security_core_clr_enabled ())
4441 mono_security_core_clr_check_override (klass, cm, m1);
4443 slot = mono_method_get_vtable_slot (m1);
4447 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4448 char *body_name = mono_method_full_name (cm, TRUE);
4449 char *decl_name = mono_method_full_name (m1, TRUE);
4450 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4456 g_assert (cm->slot < max_vtsize);
4458 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4459 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4460 mono_method_full_name (m1, 1), m1,
4461 mono_method_full_name (cm, 1), cm));
4462 g_hash_table_insert (override_map, m1, cm);
4466 if (mono_class_has_failure (k))
4476 /*Non final newslot methods must be given a non-interface vtable slot*/
4477 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4481 cm->slot = cur_slot++;
4483 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4484 vtable [cm->slot] = cm;
4487 /* override non interface methods */
4488 for (i = 0; i < onum; i++) {
4489 MonoMethod *decl = overrides [i*2];
4490 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4491 g_assert (decl->slot != -1);
4492 vtable [decl->slot] = overrides [i*2 + 1];
4493 overrides [i * 2 + 1]->slot = decl->slot;
4495 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4496 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4497 mono_method_full_name (decl, 1), decl,
4498 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4499 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4501 if (mono_security_core_clr_enabled ())
4502 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4507 * If a method occupies more than one place in the vtable, and it is
4508 * overriden, then change the other occurances too.
4513 for (i = 0; i < max_vtsize; ++i)
4515 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4517 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4522 g_hash_table_destroy (override_map);
4523 override_map = NULL;
4526 g_slist_free (virt_methods);
4527 virt_methods = NULL;
4529 g_assert (cur_slot <= max_vtsize);
4531 /* Ensure that all vtable slots are filled with concrete instance methods */
4532 if (!mono_class_is_abstract (klass)) {
4533 for (i = 0; i < cur_slot; ++i) {
4534 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4535 char *type_name = mono_type_get_full_name (klass);
4536 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4537 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4539 g_free (method_name);
4546 if (mono_class_is_ginst (klass)) {
4547 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4549 mono_class_init (gklass);
4551 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4553 /* Check that the vtable_size value computed in mono_class_init () is correct */
4554 if (klass->vtable_size)
4555 g_assert (cur_slot == klass->vtable_size);
4556 klass->vtable_size = cur_slot;
4559 /* Try to share the vtable with our parent. */
4560 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4561 mono_memory_barrier ();
4562 klass->vtable = klass->parent->vtable;
4564 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4565 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4566 mono_memory_barrier ();
4567 klass->vtable = tmp;
4570 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4571 if (mono_print_vtable) {
4574 print_implemented_interfaces (klass);
4576 for (i = 0; i <= max_iid; i++)
4577 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4580 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4581 klass->vtable_size, icount);
4583 for (i = 0; i < cur_slot; ++i) {
4588 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4589 mono_method_full_name (cm, TRUE));
4595 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4596 klass->name, max_iid);
4598 for (i = 0; i < klass->interface_count; i++) {
4599 ic = klass->interfaces [i];
4600 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4601 mono_class_interface_offset (klass, ic),
4602 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4605 for (k = klass->parent; k ; k = k->parent) {
4606 for (i = 0; i < k->interface_count; i++) {
4607 ic = k->interfaces [i];
4608 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4609 mono_class_interface_offset (klass, ic),
4610 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4618 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4623 char *name = mono_type_get_full_name (klass);
4624 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4628 g_hash_table_destroy (override_map);
4630 g_slist_free (virt_methods);
4635 * mono_method_get_vtable_slot:
4637 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4638 * LOCKING: Acquires the loader lock.
4640 * FIXME Use proper MonoError machinery here.
4643 mono_method_get_vtable_slot (MonoMethod *method)
4645 if (method->slot == -1) {
4646 mono_class_setup_vtable (method->klass);
4647 if (mono_class_has_failure (method->klass))
4649 if (method->slot == -1) {
4653 if (!mono_class_is_ginst (method->klass)) {
4654 g_assert (method->is_inflated);
4655 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4658 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4659 g_assert (mono_class_is_ginst (method->klass));
4660 gklass = mono_class_get_generic_class (method->klass)->container_class;
4661 mono_class_setup_methods (method->klass);
4662 g_assert (method->klass->methods);
4663 mcount = mono_class_get_method_count (method->klass);
4664 for (i = 0; i < mcount; ++i) {
4665 if (method->klass->methods [i] == method)
4668 g_assert (i < mcount);
4669 g_assert (gklass->methods);
4670 method->slot = gklass->methods [i]->slot;
4672 g_assert (method->slot != -1);
4674 return method->slot;
4678 * mono_method_get_vtable_index:
4679 * \param method a method
4681 * Returns the index into the runtime vtable to access the method or,
4682 * in the case of a virtual generic method, the virtual generic method
4683 * thunk. Returns -1 on failure.
4685 * FIXME Use proper MonoError machinery here.
4688 mono_method_get_vtable_index (MonoMethod *method)
4690 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4691 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4692 if (imethod->declaring->is_generic)
4693 return mono_method_get_vtable_slot (imethod->declaring);
4695 return mono_method_get_vtable_slot (method);
4698 static MonoMethod *default_ghc = NULL;
4699 static MonoMethod *default_finalize = NULL;
4700 static int finalize_slot = -1;
4701 static int ghc_slot = -1;
4704 initialize_object_slots (MonoClass *klass)
4709 if (klass == mono_defaults.object_class) {
4710 mono_class_setup_vtable (klass);
4711 for (i = 0; i < klass->vtable_size; ++i) {
4712 MonoMethod *cm = klass->vtable [i];
4714 if (!strcmp (cm->name, "GetHashCode"))
4716 else if (!strcmp (cm->name, "Finalize"))
4720 g_assert (ghc_slot > 0);
4721 default_ghc = klass->vtable [ghc_slot];
4723 g_assert (finalize_slot > 0);
4724 default_finalize = klass->vtable [finalize_slot];
4729 MonoMethod *array_method;
4731 } GenericArrayMethodInfo;
4733 static int generic_array_method_num = 0;
4734 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4737 generic_array_methods (MonoClass *klass)
4739 int i, count_generic = 0, mcount;
4740 GList *list = NULL, *tmp;
4741 if (generic_array_method_num)
4742 return generic_array_method_num;
4743 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4744 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4745 mcount = mono_class_get_method_count (klass->parent);
4746 for (i = 0; i < mcount; i++) {
4747 MonoMethod *m = klass->parent->methods [i];
4748 if (!strncmp (m->name, "InternalArray__", 15)) {
4750 list = g_list_prepend (list, m);
4753 list = g_list_reverse (list);
4754 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4756 for (tmp = list; tmp; tmp = tmp->next) {
4757 const char *mname, *iname;
4759 MonoMethod *m = (MonoMethod *)tmp->data;
4760 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4761 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4763 generic_array_method_info [i].array_method = m;
4764 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4765 iname = "System.Collections.Generic.ICollection`1.";
4766 mname = m->name + 27;
4767 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4768 iname = "System.Collections.Generic.IEnumerable`1.";
4769 mname = m->name + 27;
4770 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4771 iname = "System.Collections.Generic.IReadOnlyList`1.";
4772 mname = m->name + strlen (ireadonlylist_prefix);
4773 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4774 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4775 mname = m->name + strlen (ireadonlycollection_prefix);
4776 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4777 iname = "System.Collections.Generic.IList`1.";
4778 mname = m->name + 15;
4780 g_assert_not_reached ();
4783 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4784 strcpy (name, iname);
4785 strcpy (name + strlen (iname), mname);
4786 generic_array_method_info [i].name = name;
4789 /*g_print ("array generic methods: %d\n", count_generic);*/
4791 generic_array_method_num = count_generic;
4793 return generic_array_method_num;
4797 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4799 MonoGenericContext tmp_context;
4802 tmp_context.class_inst = NULL;
4803 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4804 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4806 for (i = 0; i < generic_array_method_num; i++) {
4808 MonoMethod *m = generic_array_method_info [i].array_method;
4809 MonoMethod *inflated, *helper;
4811 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4812 mono_error_assert_ok (&error);
4813 helper = g_hash_table_lookup (cache, inflated);
4815 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4816 g_hash_table_insert (cache, inflated, helper);
4818 methods [pos ++] = helper;
4823 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4825 int null_length = strlen ("(null)");
4826 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4827 char *s = (char *)mono_image_alloc (image, len);
4830 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4831 g_assert (result == len - 1);
4838 * \param klass the class to initialize
4840 * Compute the \c instance_size, \c class_size and other infos that cannot be
4841 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4842 * Initializes the following fields in \p klass:
4843 * - all the fields initialized by \c mono_class_init_sizes
4848 * LOCKING: Acquires the loader lock.
4850 * \returns TRUE on success or FALSE if there was a problem in loading
4851 * the type (incorrect assemblies, missing assemblies, methods, etc).
4854 mono_class_init (MonoClass *klass)
4856 int i, vtable_size = 0, array_method_count = 0;
4857 MonoCachedClassInfo cached_info;
4858 gboolean has_cached_info;
4859 gboolean locked = FALSE;
4860 gboolean ghcimpl = FALSE;
4861 gboolean has_cctor = FALSE;
4862 int first_iface_slot = 0;
4866 /* Double-checking locking pattern */
4867 if (klass->inited || mono_class_has_failure (klass))
4868 return !mono_class_has_failure (klass);
4870 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4873 * This function can recursively call itself.
4875 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4876 if (g_slist_find (init_list, klass)) {
4877 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4880 init_list = g_slist_prepend (init_list, klass);
4881 mono_native_tls_set_value (init_pending_tls_id, init_list);
4884 * We want to avoid doing complicated work inside locks, so we compute all the required
4885 * information and write it to @klass inside a lock.
4888 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4889 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4893 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4894 MonoClass *element_class = klass->element_class;
4895 if (!element_class->inited)
4896 mono_class_init (element_class);
4897 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4901 mono_stats.initialized_class_count++;
4903 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4904 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4906 mono_class_init (gklass);
4907 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4910 mono_class_setup_interface_id (klass);
4913 if (klass->parent && !klass->parent->inited)
4914 mono_class_init (klass->parent);
4916 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4918 /* Compute instance size etc. */
4919 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4920 if (mono_class_has_failure (klass))
4923 mono_class_setup_supertypes (klass);
4926 initialize_object_slots (klass);
4929 * Initialize the rest of the data without creating a generic vtable if possible.
4930 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4931 * also avoid computing a generic vtable.
4933 if (has_cached_info) {
4935 vtable_size = cached_info.vtable_size;
4936 ghcimpl = cached_info.ghcimpl;
4937 has_cctor = cached_info.has_cctor;
4938 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4939 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4940 * The first slot if for array with.
4942 static int szarray_vtable_size[2] = { 0 };
4944 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4947 if (!szarray_vtable_size [slot]) {
4948 mono_class_setup_vtable (klass);
4949 szarray_vtable_size [slot] = klass->vtable_size;
4950 vtable_size = klass->vtable_size;
4952 vtable_size = szarray_vtable_size[slot];
4954 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4955 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4957 /* Generic instance case */
4958 ghcimpl = gklass->ghcimpl;
4959 has_cctor = gklass->has_cctor;
4961 mono_class_setup_vtable (gklass);
4962 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4965 vtable_size = gklass->vtable_size;
4969 /* ghcimpl is not currently used
4971 if (klass->parent) {
4972 MonoMethod *cmethod = klass->vtable [ghc_slot];
4973 if (cmethod->is_inflated)
4974 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4975 if (cmethod == default_ghc) {
4981 /* C# doesn't allow interfaces to have cctors */
4982 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4983 MonoMethod *cmethod = NULL;
4985 if (mono_class_is_ginst (klass)) {
4986 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4988 /* Generic instance case */
4989 ghcimpl = gklass->ghcimpl;
4990 has_cctor = gklass->has_cctor;
4991 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4992 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4993 /* The find_method function ignores the 'flags' argument */
4994 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4997 mono_class_setup_methods (klass);
4998 if (mono_class_has_failure (klass))
5001 int mcount = mono_class_get_method_count (klass);
5002 for (i = 0; i < mcount; ++i) {
5003 MonoMethod *method = klass->methods [i];
5004 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5005 (strcmp (".cctor", method->name) == 0)) {
5015 array_method_count = 3 + (klass->rank > 1? 2: 1);
5017 if (klass->interface_count) {
5018 int count_generic = generic_array_methods (klass);
5019 array_method_count += klass->interface_count * count_generic;
5023 if (klass->parent) {
5024 if (!klass->parent->vtable_size)
5025 mono_class_setup_vtable (klass->parent);
5026 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5028 g_assert (klass->parent->vtable_size);
5029 first_iface_slot = klass->parent->vtable_size;
5030 if (mono_class_need_stelemref_method (klass))
5035 * Do the actual changes to @klass inside the loader lock
5037 mono_loader_lock ();
5040 if (klass->inited || mono_class_has_failure (klass)) {
5041 mono_loader_unlock ();
5042 /* Somebody might have gotten in before us */
5043 return !mono_class_has_failure (klass);
5046 mono_stats.initialized_class_count++;
5048 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5049 mono_stats.generic_class_count++;
5051 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5052 klass->nested_classes_inited = TRUE;
5053 klass->ghcimpl = ghcimpl;
5054 klass->has_cctor = has_cctor;
5056 klass->vtable_size = vtable_size;
5057 if (has_cached_info) {
5058 klass->has_finalize = cached_info.has_finalize;
5059 klass->has_finalize_inited = TRUE;
5062 mono_class_set_method_count (klass, array_method_count);
5064 mono_loader_unlock ();
5067 setup_interface_offsets (klass, first_iface_slot, TRUE);
5069 if (mono_security_core_clr_enabled ())
5070 mono_security_core_clr_check_inheritance (klass);
5072 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5073 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5078 init_list = g_slist_remove (init_list, klass);
5079 mono_native_tls_set_value (init_pending_tls_id, init_list);
5082 mono_loader_unlock ();
5084 /* Leave this for last */
5085 mono_loader_lock ();
5087 mono_loader_unlock ();
5089 return !mono_class_has_failure (klass);
5093 * mono_class_has_finalizer:
5095 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5099 mono_class_has_finalizer (MonoClass *klass)
5101 gboolean has_finalize = FALSE;
5103 if (klass->has_finalize_inited)
5104 return klass->has_finalize;
5106 /* Interfaces and valuetypes are not supposed to have finalizers */
5107 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5108 MonoMethod *cmethod = NULL;
5110 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5111 } else if (mono_class_is_ginst (klass)) {
5112 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5114 has_finalize = mono_class_has_finalizer (gklass);
5115 } else if (klass->parent && klass->parent->has_finalize) {
5116 has_finalize = TRUE;
5118 if (klass->parent) {
5120 * Can't search in metadata for a method named Finalize, because that
5121 * ignores overrides.
5123 mono_class_setup_vtable (klass);
5124 if (mono_class_has_failure (klass))
5127 cmethod = klass->vtable [finalize_slot];
5131 g_assert (klass->vtable_size > finalize_slot);
5133 if (klass->parent) {
5134 if (cmethod->is_inflated)
5135 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5136 if (cmethod != default_finalize)
5137 has_finalize = TRUE;
5143 mono_loader_lock ();
5144 if (!klass->has_finalize_inited) {
5145 klass->has_finalize = has_finalize ? 1 : 0;
5147 mono_memory_barrier ();
5148 klass->has_finalize_inited = TRUE;
5150 mono_loader_unlock ();
5152 return klass->has_finalize;
5156 mono_is_corlib_image (MonoImage *image)
5158 return image == mono_defaults.corlib;
5162 * LOCKING: this assumes the loader lock is held
5165 mono_class_setup_mono_type (MonoClass *klass)
5167 const char *name = klass->name;
5168 const char *nspace = klass->name_space;
5169 gboolean is_corlib = mono_is_corlib_image (klass->image);
5171 klass->this_arg.byref = 1;
5172 klass->this_arg.data.klass = klass;
5173 klass->this_arg.type = MONO_TYPE_CLASS;
5174 klass->byval_arg.data.klass = klass;
5175 klass->byval_arg.type = MONO_TYPE_CLASS;
5177 if (is_corlib && !strcmp (nspace, "System")) {
5178 if (!strcmp (name, "ValueType")) {
5180 * do not set the valuetype bit for System.ValueType.
5181 * klass->valuetype = 1;
5183 klass->blittable = TRUE;
5184 } else if (!strcmp (name, "Enum")) {
5186 * do not set the valuetype bit for System.Enum.
5187 * klass->valuetype = 1;
5189 klass->valuetype = 0;
5190 klass->enumtype = 0;
5191 } else if (!strcmp (name, "Object")) {
5192 klass->byval_arg.type = MONO_TYPE_OBJECT;
5193 klass->this_arg.type = MONO_TYPE_OBJECT;
5194 } else if (!strcmp (name, "String")) {
5195 klass->byval_arg.type = MONO_TYPE_STRING;
5196 klass->this_arg.type = MONO_TYPE_STRING;
5197 } else if (!strcmp (name, "TypedReference")) {
5198 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5199 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5203 if (klass->valuetype) {
5204 int t = MONO_TYPE_VALUETYPE;
5206 if (is_corlib && !strcmp (nspace, "System")) {
5209 if (!strcmp (name, "Boolean")) {
5210 t = MONO_TYPE_BOOLEAN;
5211 } else if (!strcmp(name, "Byte")) {
5213 klass->blittable = TRUE;
5217 if (!strcmp (name, "Char")) {
5222 if (!strcmp (name, "Double")) {
5224 klass->blittable = TRUE;
5228 if (!strcmp (name, "Int32")) {
5230 klass->blittable = TRUE;
5231 } else if (!strcmp(name, "Int16")) {
5233 klass->blittable = TRUE;
5234 } else if (!strcmp(name, "Int64")) {
5236 klass->blittable = TRUE;
5237 } else if (!strcmp(name, "IntPtr")) {
5239 klass->blittable = TRUE;
5243 if (!strcmp (name, "Single")) {
5245 klass->blittable = TRUE;
5246 } else if (!strcmp(name, "SByte")) {
5248 klass->blittable = TRUE;
5252 if (!strcmp (name, "UInt32")) {
5254 klass->blittable = TRUE;
5255 } else if (!strcmp(name, "UInt16")) {
5257 klass->blittable = TRUE;
5258 } else if (!strcmp(name, "UInt64")) {
5260 klass->blittable = TRUE;
5261 } else if (!strcmp(name, "UIntPtr")) {
5263 klass->blittable = TRUE;
5267 if (!strcmp (name, "TypedReference")) {
5268 t = MONO_TYPE_TYPEDBYREF;
5269 klass->blittable = TRUE;
5273 if (!strcmp (name, "Void")) {
5281 klass->byval_arg.type = (MonoTypeEnum)t;
5282 klass->this_arg.type = (MonoTypeEnum)t;
5285 if (MONO_CLASS_IS_INTERFACE (klass)) {
5286 klass->interface_id = mono_get_unique_iid (klass);
5288 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5289 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5290 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5291 * MS returns diferrent types based on which instance is called. For example:
5292 * object obj = new byte[10][];
5293 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5294 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5297 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5298 klass->is_array_special_interface = 1;
5305 * COM initialization is delayed until needed.
5306 * However when a [ComImport] attribute is present on a type it will trigger
5307 * the initialization. This is not a problem unless the BCL being executed
5308 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5311 init_com_from_comimport (MonoClass *klass)
5313 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5314 if (mono_security_core_clr_enabled ()) {
5315 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5316 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5317 /* but it can not be made available for application (i.e. user code) since all COM calls
5318 * are considered native calls. In this case we fail with a TypeLoadException (just like
5319 * Silverlight 2 does */
5320 mono_class_set_type_load_failure (klass, "");
5325 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5327 #endif /*DISABLE_COM*/
5330 * LOCKING: this assumes the loader lock is held
5333 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5335 gboolean system_namespace;
5336 gboolean is_corlib = mono_is_corlib_image (klass->image);
5338 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5340 /* if root of the hierarchy */
5341 if (system_namespace && !strcmp (klass->name, "Object")) {
5342 klass->parent = NULL;
5343 klass->instance_size = sizeof (MonoObject);
5346 if (!strcmp (klass->name, "<Module>")) {
5347 klass->parent = NULL;
5348 klass->instance_size = 0;
5352 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5353 /* Imported COM Objects always derive from __ComObject. */
5355 if (MONO_CLASS_IS_IMPORT (klass)) {
5356 init_com_from_comimport (klass);
5357 if (parent == mono_defaults.object_class)
5358 parent = mono_class_get_com_object_class ();
5362 /* set the parent to something useful and safe, but mark the type as broken */
5363 parent = mono_defaults.object_class;
5364 mono_class_set_type_load_failure (klass, "");
5368 klass->parent = parent;
5370 if (mono_class_is_ginst (parent) && !parent->name) {
5372 * If the parent is a generic instance, we may get
5373 * called before it is fully initialized, especially
5374 * before it has its name.
5379 #ifndef DISABLE_REMOTING
5380 klass->marshalbyref = parent->marshalbyref;
5381 klass->contextbound = parent->contextbound;
5384 klass->delegate = parent->delegate;
5386 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5387 mono_class_set_is_com_object (klass);
5389 if (system_namespace) {
5390 #ifndef DISABLE_REMOTING
5391 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5392 klass->marshalbyref = 1;
5394 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5395 klass->contextbound = 1;
5397 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5398 klass->delegate = 1;
5401 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5402 (strcmp (klass->parent->name_space, "System") == 0)))
5403 klass->valuetype = 1;
5404 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5405 klass->valuetype = klass->enumtype = 1;
5407 /*klass->enumtype = klass->parent->enumtype; */
5409 /* initialize com types if COM interfaces are present */
5411 if (MONO_CLASS_IS_IMPORT (klass))
5412 init_com_from_comimport (klass);
5414 klass->parent = NULL;
5420 * mono_class_setup_supertypes:
5423 * Build the data structure needed to make fast type checks work.
5424 * This currently sets two fields in @class:
5425 * - idepth: distance between @class and System.Object in the type
5427 * - supertypes: array of classes: each element has a class in the hierarchy
5428 * starting from @class up to System.Object
5430 * LOCKING: Acquires the loader lock.
5433 mono_class_setup_supertypes (MonoClass *klass)
5436 MonoClass **supertypes;
5438 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5442 if (klass->parent && !klass->parent->supertypes)
5443 mono_class_setup_supertypes (klass->parent);
5445 idepth = klass->parent->idepth + 1;
5449 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5450 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5452 if (klass->parent) {
5453 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5456 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5457 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5459 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5462 mono_memory_barrier ();
5464 mono_loader_lock ();
5465 klass->idepth = idepth;
5466 /* Needed so idepth is visible before supertypes is set */
5467 mono_memory_barrier ();
5468 klass->supertypes = supertypes;
5469 mono_loader_unlock ();
5473 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5475 return mono_class_get_generic_class (gclass)->container_class == user_data;
5479 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5481 MonoClass *gtd = (MonoClass*)user_data;
5482 /* Only try to fix generic instances of @gtd */
5483 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5486 /* Check if the generic instance has no parent. */
5487 if (gtd->parent && !gclass->parent)
5488 mono_generic_class_setup_parent (gclass, gtd);
5494 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5496 mono_class_set_type_load_failure (klass, "%s", msg);
5497 mono_error_set_type_load_class (error, klass, "%s", msg);
5501 * mono_class_create_from_typedef:
5502 * \param image: image where the token is valid
5503 * \param type_token: typedef token
5504 * \param error: used to return any error found while creating the type
5506 * Create the MonoClass* representing the specified type token.
5507 * \p type_token must be a TypeDef token.
5509 * FIXME: don't return NULL on failure, just the the caller figure it out.
5512 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5514 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5515 MonoClass *klass, *parent = NULL;
5516 guint32 cols [MONO_TYPEDEF_SIZE];
5517 guint32 cols_next [MONO_TYPEDEF_SIZE];
5518 guint tidx = mono_metadata_token_index (type_token);
5519 MonoGenericContext *context = NULL;
5520 const char *name, *nspace;
5522 MonoClass **interfaces;
5523 guint32 field_last, method_last;
5524 guint32 nesting_tokeen;
5528 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5529 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5533 mono_loader_lock ();
5535 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5536 mono_loader_unlock ();
5540 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5542 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5543 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5545 if (mono_metadata_has_generic_params (image, type_token)) {
5546 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5547 klass->class_kind = MONO_CLASS_GTD;
5548 classes_size += sizeof (MonoClassGtd);
5551 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5552 klass->class_kind = MONO_CLASS_DEF;
5553 classes_size += sizeof (MonoClassDef);
5558 klass->name_space = nspace;
5560 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5562 klass->image = image;
5563 klass->type_token = type_token;
5564 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5566 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5569 * Check whether we're a generic type definition.
5571 if (mono_class_is_gtd (klass)) {
5572 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5573 generic_container->owner.klass = klass;
5574 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5575 context = &generic_container->context;
5576 mono_class_set_generic_container (klass, generic_container);
5577 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5578 canonical_inst->type = MONO_TYPE_GENERICINST;
5579 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5580 enable_gclass_recording ();
5583 if (cols [MONO_TYPEDEF_EXTENDS]) {
5585 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5587 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5588 /*WARNING: this must satisfy mono_metadata_type_hash*/
5589 klass->this_arg.byref = 1;
5590 klass->this_arg.data.klass = klass;
5591 klass->this_arg.type = MONO_TYPE_CLASS;
5592 klass->byval_arg.data.klass = klass;
5593 klass->byval_arg.type = MONO_TYPE_CLASS;
5595 parent = mono_class_get_checked (image, parent_token, error);
5596 if (parent && context) /* Always inflate */
5597 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5599 if (parent == NULL) {
5600 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5601 goto parent_failure;
5604 for (tmp = parent; tmp; tmp = tmp->parent) {
5606 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5607 goto parent_failure;
5609 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5610 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5611 goto parent_failure;
5616 mono_class_setup_parent (klass, parent);
5618 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5619 mono_class_setup_mono_type (klass);
5621 if (mono_class_is_gtd (klass))
5622 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5625 * This might access klass->byval_arg for recursion generated by generic constraints,
5626 * so it has to come after setup_mono_type ().
5628 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5629 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5630 if (!mono_error_ok (error)) {
5631 /*FIXME implement a mono_class_set_failure_from_mono_error */
5632 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5633 mono_loader_unlock ();
5634 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5639 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5643 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5647 klass->cast_class = klass->element_class = klass;
5648 if (mono_is_corlib_image (klass->image)) {
5649 switch (klass->byval_arg.type) {
5651 if (mono_defaults.byte_class)
5652 klass->cast_class = mono_defaults.byte_class;
5655 if (mono_defaults.sbyte_class)
5656 mono_defaults.sbyte_class = klass;
5659 if (mono_defaults.uint16_class)
5660 mono_defaults.uint16_class = klass;
5663 if (mono_defaults.int16_class)
5664 klass->cast_class = mono_defaults.int16_class;
5667 if (mono_defaults.uint32_class)
5668 mono_defaults.uint32_class = klass;
5671 if (mono_defaults.int32_class)
5672 klass->cast_class = mono_defaults.int32_class;
5675 if (mono_defaults.uint64_class)
5676 mono_defaults.uint64_class = klass;
5679 if (mono_defaults.int64_class)
5680 klass->cast_class = mono_defaults.int64_class;
5685 if (!klass->enumtype) {
5686 if (!mono_metadata_interfaces_from_typedef_full (
5687 image, type_token, &interfaces, &icount, FALSE, context, error)){
5689 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5690 mono_loader_unlock ();
5691 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5695 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5696 g_assert(icount <= 65535);
5698 klass->interfaces = interfaces;
5699 klass->interface_count = icount;
5700 klass->interfaces_inited = 1;
5703 /*g_print ("Load class %s\n", name);*/
5706 * Compute the field and method lists
5708 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5709 mono_class_set_first_field_idx (klass, first_field_idx);
5710 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5711 mono_class_set_first_method_idx (klass, first_method_idx);
5713 if (tt->rows > tidx){
5714 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5715 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5716 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5718 field_last = image->tables [MONO_TABLE_FIELD].rows;
5719 method_last = image->tables [MONO_TABLE_METHOD].rows;
5722 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5723 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5724 mono_class_set_field_count (klass, field_last - first_field_idx);
5725 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5726 mono_class_set_method_count (klass, method_last - first_method_idx);
5728 /* reserve space to store vector pointer in arrays */
5729 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5730 klass->instance_size += 2 * sizeof (gpointer);
5731 g_assert (mono_class_get_field_count (klass) == 0);
5734 if (klass->enumtype) {
5735 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5736 if (!enum_basetype) {
5737 /*set it to a default value as the whole runtime can't handle this to be null*/
5738 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5739 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5740 mono_loader_unlock ();
5741 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5744 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5748 * If we're a generic type definition, load the constraints.
5749 * We must do this after the class has been constructed to make certain recursive scenarios
5752 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5753 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5754 mono_loader_unlock ();
5755 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5759 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5760 if (!strncmp (name, "Vector", 6))
5761 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");
5762 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5763 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5764 klass->simd_type = 1;
5767 mono_loader_unlock ();
5769 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5774 if (mono_class_is_gtd (klass))
5775 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5777 mono_class_setup_mono_type (klass);
5778 mono_loader_unlock ();
5779 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5783 /** Is klass a Nullable<T> ginst? */
5785 mono_class_is_nullable (MonoClass *klass)
5787 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5788 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5792 /** if klass is T? return T */
5794 mono_class_get_nullable_param (MonoClass *klass)
5796 g_assert (mono_class_is_nullable (klass));
5797 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5801 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5805 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5807 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5808 if (!mono_error_ok (&error)) {
5809 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5810 klass->parent = mono_defaults.object_class;
5811 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5812 mono_error_cleanup (&error);
5815 mono_loader_lock ();
5817 mono_class_setup_parent (klass, klass->parent);
5819 if (klass->enumtype) {
5820 klass->cast_class = gtd->cast_class;
5821 klass->element_class = gtd->element_class;
5823 mono_loader_unlock ();
5827 mono_type_is_primitive (MonoType *type)
5829 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5830 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5834 * Create the `MonoClass' for an instantiation of a generic type.
5835 * We only do this if we actually need it.
5838 mono_generic_class_get_class (MonoGenericClass *gclass)
5840 MonoClass *klass, *gklass;
5842 if (gclass->cached_class)
5843 return gclass->cached_class;
5845 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5847 gklass = gclass->container_class;
5849 if (gklass->nested_in) {
5850 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5851 klass->nested_in = gklass->nested_in;
5854 klass->name = gklass->name;
5855 klass->name_space = gklass->name_space;
5857 klass->image = gklass->image;
5858 klass->type_token = gklass->type_token;
5860 klass->class_kind = MONO_CLASS_GINST;
5862 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5864 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5865 klass->this_arg.type = klass->byval_arg.type;
5866 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5867 klass->this_arg.byref = TRUE;
5868 klass->enumtype = gklass->enumtype;
5869 klass->valuetype = gklass->valuetype;
5872 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5873 g_assert (gclass->context.class_inst);
5874 g_assert (gclass->context.class_inst->type_argc > 0);
5875 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5876 klass->simd_type = 1;
5878 klass->is_array_special_interface = gklass->is_array_special_interface;
5880 klass->cast_class = klass->element_class = klass;
5882 if (gclass->is_dynamic) {
5884 * 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.
5885 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5886 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5888 if (!gklass->wastypebuilder)
5891 if (klass->enumtype) {
5893 * For enums, gklass->fields might not been set, but instance_size etc. is
5894 * already set in mono_reflection_create_internal_class (). For non-enums,
5895 * these will be computed normally in mono_class_layout_fields ().
5897 klass->instance_size = gklass->instance_size;
5898 klass->sizes.class_size = gklass->sizes.class_size;
5899 klass->size_inited = 1;
5903 mono_loader_lock ();
5905 if (gclass->cached_class) {
5906 mono_loader_unlock ();
5907 return gclass->cached_class;
5910 if (record_gclass_instantiation > 0)
5911 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5913 if (mono_class_is_nullable (klass))
5914 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5916 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5918 mono_generic_class_setup_parent (klass, gklass);
5920 if (gclass->is_dynamic)
5921 mono_class_setup_supertypes (klass);
5923 mono_memory_barrier ();
5924 gclass->cached_class = klass;
5926 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5928 ++class_ginst_count;
5929 inflated_classes_size += sizeof (MonoClassGenericInst);
5931 mono_loader_unlock ();
5937 get_image_for_container (MonoGenericContainer *container)
5940 if (container->is_anonymous) {
5941 result = container->owner.image;
5944 if (container->is_method) {
5945 MonoMethod *method = container->owner.method;
5946 g_assert_checked (method);
5947 klass = method->klass;
5949 klass = container->owner.klass;
5951 g_assert_checked (klass);
5952 result = klass->image;
5959 get_image_for_generic_param (MonoGenericParam *param)
5961 MonoGenericContainer *container = mono_generic_param_owner (param);
5962 g_assert_checked (container);
5963 return get_image_for_container (container);
5966 // Make a string in the designated image consisting of a single integer.
5967 #define INT_STRING_SIZE 16
5969 make_generic_name_string (MonoImage *image, int num)
5971 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5972 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5976 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5977 // pinfo is derived from param by the caller for us.
5979 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5981 MonoClass *klass, **ptr;
5983 MonoGenericContainer *container = mono_generic_param_owner (param);
5984 g_assert_checked (container);
5986 MonoImage *image = get_image_for_container (container);
5987 gboolean is_mvar = container->is_method;
5988 gboolean is_anonymous = container->is_anonymous;
5990 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5991 klass->class_kind = MONO_CLASS_GPARAM;
5992 classes_size += sizeof (MonoClassGenericParam);
5993 ++class_gparam_count;
5996 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5998 int n = mono_generic_param_num (param);
5999 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6003 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6004 } else if (is_mvar) {
6005 MonoMethod *omethod = container->owner.method;
6006 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6008 MonoClass *oklass = container->owner.klass;
6009 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6012 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6014 // Count non-NULL items in pinfo->constraints
6017 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6021 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6022 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6024 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6025 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6027 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6030 if (count - pos > 0) {
6031 klass->interface_count = count - pos;
6032 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6033 klass->interfaces_inited = TRUE;
6034 for (i = pos; i < count; i++)
6035 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6038 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6040 klass->inited = TRUE;
6041 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6042 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6044 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6045 klass->this_arg.type = klass->byval_arg.type;
6046 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6047 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6048 klass->this_arg.byref = TRUE;
6050 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6051 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6053 /*Init these fields to sane values*/
6054 klass->min_align = 1;
6056 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6057 * constrained to, the JIT depends on this.
6059 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6060 mono_memory_barrier ();
6061 klass->size_inited = 1;
6063 mono_class_setup_supertypes (klass);
6065 if (count - pos > 0) {
6066 mono_class_setup_vtable (klass->parent);
6067 if (mono_class_has_failure (klass->parent))
6068 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6070 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6076 #define FAST_CACHE_SIZE 16
6079 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6080 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6081 * we cache the MonoClasses.
6082 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6083 * LOCKING: Takes the image lock depending on @take_lock.
6086 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6088 int n = mono_generic_param_num (param);
6089 MonoImage *image = get_image_for_generic_param (param);
6090 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6091 MonoClass *klass = NULL;
6096 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6097 // For high numbers or constraints we have to use pointer hashes.
6098 if (param->gshared_constraint) {
6099 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6102 mono_image_lock (image);
6103 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6105 mono_image_unlock (image);
6110 if (n < FAST_CACHE_SIZE) {
6112 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6114 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6116 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6119 mono_image_lock (image);
6120 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6122 mono_image_unlock (image);
6129 * LOCKING: Image lock (param->image) must be held
6132 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6134 int n = mono_generic_param_num (param);
6135 MonoImage *image = get_image_for_generic_param (param);
6136 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6140 if (param->gshared_constraint) {
6141 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6143 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6144 mono_memory_barrier ();
6146 image->mvar_cache_constrained = ht;
6148 image->var_cache_constrained = ht;
6150 g_hash_table_insert (ht, param, klass);
6151 } else if (n < FAST_CACHE_SIZE) {
6153 /* Requires locking to avoid droping an already published class */
6154 if (!image->mvar_cache_fast)
6155 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6156 image->mvar_cache_fast [n] = klass;
6158 if (!image->var_cache_fast)
6159 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6160 image->var_cache_fast [n] = klass;
6163 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6165 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6167 ht = g_hash_table_new (NULL, NULL);
6168 mono_memory_barrier ();
6170 image->mvar_cache_slow = ht;
6172 image->var_cache_slow = ht;
6175 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6180 * LOCKING: Acquires the image lock (@image).
6183 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6185 MonoImage *image = get_image_for_generic_param (param);
6186 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6187 MonoClass *klass, *klass2;
6189 // If a klass already exists for this object and is cached, return it.
6190 if (pinfo) // Non-anonymous
6191 klass = pinfo->pklass;
6193 klass = get_anon_gparam_class (param, TRUE);
6198 // Create a new klass
6199 klass = make_generic_param_class (param, pinfo);
6201 // Now we need to cache the klass we created.
6202 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6203 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6204 // and allow our newly-created klass object to just leak.
6205 mono_memory_barrier ();
6207 mono_image_lock (image);
6209 // Here "klass2" refers to the klass potentially created by the other thread.
6210 if (pinfo) // Repeat check from above
6211 klass2 = pinfo->pklass;
6213 klass2 = get_anon_gparam_class (param, FALSE);
6220 pinfo->pklass = klass;
6222 set_anon_gparam_class (param, klass);
6224 mono_image_unlock (image);
6226 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6228 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6230 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6236 * mono_class_from_generic_parameter:
6237 * \param param Parameter to find/construct a class for.
6238 * \param arg2 Is ignored.
6239 * \param arg3 Is ignored.
6242 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6244 return mono_class_from_generic_parameter_internal (param);
6248 * mono_ptr_class_get:
6251 mono_ptr_class_get (MonoType *type)
6254 MonoClass *el_class;
6258 el_class = mono_class_from_mono_type (type);
6259 image = el_class->image;
6261 mono_image_lock (image);
6262 if (image->ptr_cache) {
6263 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6264 mono_image_unlock (image);
6268 mono_image_unlock (image);
6270 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6272 classes_size += sizeof (MonoClassPointer);
6273 ++class_pointer_count;
6275 result->parent = NULL; /* no parent for PTR types */
6276 result->name_space = el_class->name_space;
6277 name = g_strdup_printf ("%s*", el_class->name);
6278 result->name = mono_image_strdup (image, name);
6279 result->class_kind = MONO_CLASS_POINTER;
6282 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6284 result->image = el_class->image;
6285 result->inited = TRUE;
6286 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6287 result->cast_class = result->element_class = el_class;
6288 result->blittable = TRUE;
6290 result->byval_arg.type = MONO_TYPE_PTR;
6291 result->this_arg.type = result->byval_arg.type;
6292 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6293 result->this_arg.byref = TRUE;
6295 mono_class_setup_supertypes (result);
6297 mono_image_lock (image);
6298 if (image->ptr_cache) {
6300 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6301 mono_image_unlock (image);
6302 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6306 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6308 g_hash_table_insert (image->ptr_cache, el_class, result);
6309 mono_image_unlock (image);
6311 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6317 mono_fnptr_class_get (MonoMethodSignature *sig)
6319 MonoClass *result, *cached;
6320 static GHashTable *ptr_hash = NULL;
6322 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6324 mono_loader_lock ();
6326 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6327 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6328 mono_loader_unlock ();
6332 result = g_new0 (MonoClass, 1);
6334 result->parent = NULL; /* no parent for PTR types */
6335 result->name_space = "System";
6336 result->name = "MonoFNPtrFakeClass";
6337 result->class_kind = MONO_CLASS_POINTER;
6339 result->image = mono_defaults.corlib; /* need to fix... */
6340 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6341 result->cast_class = result->element_class = result;
6342 result->byval_arg.type = MONO_TYPE_FNPTR;
6343 result->this_arg.type = result->byval_arg.type;
6344 result->this_arg.data.method = result->byval_arg.data.method = sig;
6345 result->this_arg.byref = TRUE;
6346 result->blittable = TRUE;
6347 result->inited = TRUE;
6349 mono_class_setup_supertypes (result);
6351 mono_loader_lock ();
6353 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6356 mono_loader_unlock ();
6360 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6362 classes_size += sizeof (MonoClassPointer);
6363 ++class_pointer_count;
6365 g_hash_table_insert (ptr_hash, sig, result);
6367 mono_loader_unlock ();
6369 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6375 * mono_class_from_mono_type:
6376 * \param type describes the type to return
6377 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6380 mono_class_from_mono_type (MonoType *type)
6382 switch (type->type) {
6383 case MONO_TYPE_OBJECT:
6384 return type->data.klass? type->data.klass: mono_defaults.object_class;
6385 case MONO_TYPE_VOID:
6386 return type->data.klass? type->data.klass: mono_defaults.void_class;
6387 case MONO_TYPE_BOOLEAN:
6388 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6389 case MONO_TYPE_CHAR:
6390 return type->data.klass? type->data.klass: mono_defaults.char_class;
6392 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6394 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6396 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6398 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6400 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6402 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6404 return type->data.klass? type->data.klass: mono_defaults.int_class;
6406 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6408 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6410 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6412 return type->data.klass? type->data.klass: mono_defaults.single_class;
6414 return type->data.klass? type->data.klass: mono_defaults.double_class;
6415 case MONO_TYPE_STRING:
6416 return type->data.klass? type->data.klass: mono_defaults.string_class;
6417 case MONO_TYPE_TYPEDBYREF:
6418 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6419 case MONO_TYPE_ARRAY:
6420 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6422 return mono_ptr_class_get (type->data.type);
6423 case MONO_TYPE_FNPTR:
6424 return mono_fnptr_class_get (type->data.method);
6425 case MONO_TYPE_SZARRAY:
6426 return mono_array_class_get (type->data.klass, 1);
6427 case MONO_TYPE_CLASS:
6428 case MONO_TYPE_VALUETYPE:
6429 return type->data.klass;
6430 case MONO_TYPE_GENERICINST:
6431 return mono_generic_class_get_class (type->data.generic_class);
6432 case MONO_TYPE_MVAR:
6434 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6436 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6437 g_assert_not_reached ();
6440 // Yes, this returns NULL, even if it is documented as not doing so, but there
6441 // is no way for the code to make it this far, due to the assert above.
6446 * mono_type_retrieve_from_typespec
6447 * \param image context where the image is created
6448 * \param type_spec typespec token
6449 * \param context the generic context used to evaluate generic instantiations in
6452 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6454 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6456 *did_inflate = FALSE;
6461 if (context && (context->class_inst || context->method_inst)) {
6462 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6464 if (!mono_error_ok (error)) {
6470 *did_inflate = TRUE;
6477 * mono_class_create_from_typespec
6478 * \param image context where the image is created
6479 * \param type_spec typespec token
6480 * \param context the generic context used to evaluate generic instantiations in
6483 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6486 gboolean inflated = FALSE;
6487 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6488 return_val_if_nok (error, NULL);
6489 ret = mono_class_from_mono_type (t);
6491 mono_metadata_free_type (t);
6496 * mono_bounded_array_class_get:
6497 * \param element_class element class
6498 * \param rank the dimension of the array class
6499 * \param bounded whenever the array has non-zero bounds
6500 * \returns A class object describing the array with element type \p element_type and
6501 * dimension \p rank.
6504 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6507 MonoClass *klass, *cached, *k;
6508 MonoClass *parent = NULL;
6509 GSList *list, *rootlist = NULL;
6513 g_assert (rank <= 255);
6516 /* bounded only matters for one-dimensional arrays */
6519 image = eclass->image;
6523 if (rank == 1 && !bounded) {
6525 * This case is very frequent not just during compilation because of calls
6526 * from mono_class_from_mono_type (), mono_array_new (),
6527 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6529 mono_os_mutex_lock (&image->szarray_cache_lock);
6530 if (!image->szarray_cache)
6531 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6532 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6533 mono_os_mutex_unlock (&image->szarray_cache_lock);
6535 mono_loader_lock ();
6536 if (!image->array_cache)
6537 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6538 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6539 for (list = rootlist; list; list = list->next) {
6540 k = (MonoClass *)list->data;
6541 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6546 mono_loader_unlock ();
6551 parent = mono_defaults.array_class;
6552 if (!parent->inited)
6553 mono_class_init (parent);
6555 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6557 klass->image = image;
6558 klass->name_space = eclass->name_space;
6559 klass->class_kind = MONO_CLASS_ARRAY;
6561 nsize = strlen (eclass->name);
6562 name = (char *)g_malloc (nsize + 2 + rank + 1);
6563 memcpy (name, eclass->name, nsize);
6566 memset (name + nsize + 1, ',', rank - 1);
6568 name [nsize + rank] = '*';
6569 name [nsize + rank + bounded] = ']';
6570 name [nsize + rank + bounded + 1] = 0;
6571 klass->name = mono_image_strdup (image, name);
6574 klass->type_token = 0;
6575 klass->parent = parent;
6576 klass->instance_size = mono_class_instance_size (klass->parent);
6578 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6579 /*Arrays of those two types are invalid.*/
6580 MonoError prepared_error;
6581 error_init (&prepared_error);
6582 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6583 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6584 mono_error_cleanup (&prepared_error);
6585 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6586 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6587 if (!ref_info_handle || eclass->wastypebuilder) {
6588 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6589 g_assert (ref_info_handle && !eclass->wastypebuilder);
6591 /* element_size -1 is ok as this is not an instantitable type*/
6592 klass->sizes.element_size = -1;
6594 klass->sizes.element_size = mono_class_array_element_size (eclass);
6596 mono_class_setup_supertypes (klass);
6598 if (mono_class_is_ginst (eclass))
6599 mono_class_init (eclass);
6600 if (!eclass->size_inited)
6601 mono_class_setup_fields (eclass);
6602 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6603 /*FIXME we fail the array type, but we have to let other fields be set.*/
6605 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6609 if (eclass->enumtype)
6610 klass->cast_class = eclass->element_class;
6612 klass->cast_class = eclass;
6614 switch (klass->cast_class->byval_arg.type) {
6616 klass->cast_class = mono_defaults.byte_class;
6619 klass->cast_class = mono_defaults.int16_class;
6622 #if SIZEOF_VOID_P == 4
6626 klass->cast_class = mono_defaults.int32_class;
6629 #if SIZEOF_VOID_P == 8
6633 klass->cast_class = mono_defaults.int64_class;
6639 klass->element_class = eclass;
6641 if ((rank > 1) || bounded) {
6642 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6643 klass->byval_arg.type = MONO_TYPE_ARRAY;
6644 klass->byval_arg.data.array = at;
6645 at->eklass = eclass;
6647 /* FIXME: complete.... */
6649 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6650 klass->byval_arg.data.klass = eclass;
6652 klass->this_arg = klass->byval_arg;
6653 klass->this_arg.byref = 1;
6656 MonoError prepared_error;
6657 error_init (&prepared_error);
6658 name = mono_type_get_full_name (klass);
6659 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6660 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6661 mono_error_cleanup (&prepared_error);
6665 mono_loader_lock ();
6667 /* Check cache again */
6669 if (rank == 1 && !bounded) {
6670 mono_os_mutex_lock (&image->szarray_cache_lock);
6671 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6672 mono_os_mutex_unlock (&image->szarray_cache_lock);
6674 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6675 for (list = rootlist; list; list = list->next) {
6676 k = (MonoClass *)list->data;
6677 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6684 mono_loader_unlock ();
6688 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6690 classes_size += sizeof (MonoClassArray);
6691 ++class_array_count;
6693 if (rank == 1 && !bounded) {
6694 mono_os_mutex_lock (&image->szarray_cache_lock);
6695 g_hash_table_insert (image->szarray_cache, eclass, klass);
6696 mono_os_mutex_unlock (&image->szarray_cache_lock);
6698 list = g_slist_append (rootlist, klass);
6699 g_hash_table_insert (image->array_cache, eclass, list);
6702 mono_loader_unlock ();
6704 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6710 * mono_array_class_get:
6711 * \param element_class element class
6712 * \param rank the dimension of the array class
6713 * \returns A class object describing the array with element type \p element_type and
6714 * dimension \p rank.
6717 mono_array_class_get (MonoClass *eclass, guint32 rank)
6719 return mono_bounded_array_class_get (eclass, rank, FALSE);
6723 * mono_class_instance_size:
6724 * \param klass a class
6726 * Use to get the size of a class in bytes.
6728 * \returns The size of an object instance
6731 mono_class_instance_size (MonoClass *klass)
6733 if (!klass->size_inited)
6734 mono_class_init (klass);
6736 return klass->instance_size;
6740 * mono_class_min_align:
6741 * \param klass a class
6743 * Use to get the computed minimum alignment requirements for the specified class.
6745 * Returns: minimum alignment requirements
6748 mono_class_min_align (MonoClass *klass)
6750 if (!klass->size_inited)
6751 mono_class_init (klass);
6753 return klass->min_align;
6757 * mono_class_value_size:
6758 * \param klass a class
6760 * This function is used for value types, and return the
6761 * space and the alignment to store that kind of value object.
6763 * \returns the size of a value of kind \p klass
6766 mono_class_value_size (MonoClass *klass, guint32 *align)
6770 /* fixme: check disable, because we still have external revereces to
6771 * mscorlib and Dummy Objects
6773 /*g_assert (klass->valuetype);*/
6775 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6778 *align = klass->min_align;
6784 * mono_class_data_size:
6785 * \param klass a class
6787 * \returns The size of the static class data
6790 mono_class_data_size (MonoClass *klass)
6793 mono_class_init (klass);
6794 /* This can happen with dynamically created types */
6795 if (!klass->fields_inited)
6796 mono_class_setup_fields (klass);
6798 /* in arrays, sizes.class_size is unioned with element_size
6799 * and arrays have no static fields
6803 return klass->sizes.class_size;
6807 * Auxiliary routine to mono_class_get_field
6809 * Takes a field index instead of a field token.
6811 static MonoClassField *
6812 mono_class_get_field_idx (MonoClass *klass, int idx)
6814 mono_class_setup_fields (klass);
6815 if (mono_class_has_failure (klass))
6819 int first_field_idx = mono_class_get_first_field_idx (klass);
6820 int fcount = mono_class_get_field_count (klass);
6821 if (klass->image->uncompressed_metadata) {
6823 * first_field_idx points to the FieldPtr table, while idx points into the
6824 * Field table, so we have to do a search.
6826 /*FIXME this is broken for types with multiple fields with the same name.*/
6827 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6830 for (i = 0; i < fcount; ++i)
6831 if (mono_field_get_name (&klass->fields [i]) == name)
6832 return &klass->fields [i];
6833 g_assert_not_reached ();
6836 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6837 return &klass->fields [idx - first_field_idx];
6841 klass = klass->parent;
6847 * mono_class_get_field:
6848 * \param class the class to lookup the field.
6849 * \param field_token the field token
6851 * \returns A \c MonoClassField representing the type and offset of
6852 * the field, or a NULL value if the field does not belong to this
6856 mono_class_get_field (MonoClass *klass, guint32 field_token)
6858 int idx = mono_metadata_token_index (field_token);
6860 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6862 return mono_class_get_field_idx (klass, idx - 1);
6866 * mono_class_get_field_from_name:
6867 * \param klass the class to lookup the field.
6868 * \param name the field name
6870 * Search the class \p klass and its parents for a field with the name \p name.
6872 * \returns The \c MonoClassField pointer of the named field or NULL
6875 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6877 return mono_class_get_field_from_name_full (klass, name, NULL);
6881 * mono_class_get_field_from_name_full:
6882 * \param klass the class to lookup the field.
6883 * \param name the field name
6884 * \param type the type of the fields. This optional.
6886 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6888 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6889 * of its generic type definition.
6891 * \returns The MonoClassField pointer of the named field or NULL
6894 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6898 mono_class_setup_fields (klass);
6899 if (mono_class_has_failure (klass))
6903 int fcount = mono_class_get_field_count (klass);
6904 for (i = 0; i < fcount; ++i) {
6905 MonoClassField *field = &klass->fields [i];
6907 if (strcmp (name, mono_field_get_name (field)) != 0)
6911 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6912 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6917 klass = klass->parent;
6923 * mono_class_get_field_token:
6924 * \param field the field we need the token of
6926 * Get the token of a field. Note that the tokesn is only valid for the image
6927 * the field was loaded from. Don't use this function for fields in dynamic types.
6929 * \returns The token representing the field in the image it was loaded from.
6932 mono_class_get_field_token (MonoClassField *field)
6934 MonoClass *klass = field->parent;
6937 mono_class_setup_fields (klass);
6942 int first_field_idx = mono_class_get_first_field_idx (klass);
6943 int fcount = mono_class_get_field_count (klass);
6944 for (i = 0; i < fcount; ++i) {
6945 if (&klass->fields [i] == field) {
6946 int idx = first_field_idx + i + 1;
6948 if (klass->image->uncompressed_metadata)
6949 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6950 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6953 klass = klass->parent;
6956 g_assert_not_reached ();
6961 mono_field_get_index (MonoClassField *field)
6963 int index = field - field->parent->fields;
6964 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6970 * mono_class_get_field_default_value:
6972 * Return the default value of the field as a pointer into the metadata blob.
6975 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6978 guint32 constant_cols [MONO_CONSTANT_SIZE];
6980 MonoClass *klass = field->parent;
6981 MonoFieldDefaultValue *def_values;
6983 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6985 def_values = mono_class_get_field_def_values (klass);
6987 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6989 mono_class_set_field_def_values (klass, def_values);
6992 field_index = mono_field_get_index (field);
6994 if (!def_values [field_index].data) {
6995 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6999 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7001 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7002 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7003 mono_memory_barrier ();
7004 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7007 *def_type = def_values [field_index].def_type;
7008 return def_values [field_index].data;
7012 mono_property_get_index (MonoProperty *prop)
7014 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7015 int index = prop - info->properties;
7017 g_assert (index >= 0 && index < info->count);
7023 * mono_class_get_property_default_value:
7025 * Return the default value of the field as a pointer into the metadata blob.
7028 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7031 guint32 constant_cols [MONO_CONSTANT_SIZE];
7032 MonoClass *klass = property->parent;
7034 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7036 * We don't cache here because it is not used by C# so it's quite rare, but
7037 * we still do the lookup in klass->ext because that is where the data
7038 * is stored for dynamic assemblies.
7041 if (image_is_dynamic (klass->image)) {
7042 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7043 int prop_index = mono_property_get_index (property);
7044 if (info->def_values && info->def_values [prop_index].data) {
7045 *def_type = info->def_values [prop_index].def_type;
7046 return info->def_values [prop_index].data;
7050 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7054 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7055 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7056 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7060 * mono_class_get_event_token:
7063 mono_class_get_event_token (MonoEvent *event)
7065 MonoClass *klass = event->parent;
7069 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7071 for (i = 0; i < info->count; ++i) {
7072 if (&info->events [i] == event)
7073 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7076 klass = klass->parent;
7079 g_assert_not_reached ();
7084 * mono_class_get_property_from_name:
7085 * \param klass a class
7086 * \param name name of the property to lookup in the specified class
7088 * Use this method to lookup a property in a class
7089 * \returns the \c MonoProperty with the given name, or NULL if the property
7090 * does not exist on the \p klass.
7093 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7097 gpointer iter = NULL;
7098 while ((p = mono_class_get_properties (klass, &iter))) {
7099 if (! strcmp (name, p->name))
7102 klass = klass->parent;
7108 * mono_class_get_property_token:
7109 * \param prop MonoProperty to query
7111 * \returns The ECMA token for the specified property.
7114 mono_class_get_property_token (MonoProperty *prop)
7116 MonoClass *klass = prop->parent;
7120 gpointer iter = NULL;
7121 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7122 while ((p = mono_class_get_properties (klass, &iter))) {
7123 if (&info->properties [i] == prop)
7124 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7128 klass = klass->parent;
7131 g_assert_not_reached ();
7136 * mono_class_name_from_token:
7139 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7141 const char *name, *nspace;
7142 if (image_is_dynamic (image))
7143 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7145 switch (type_token & 0xff000000){
7146 case MONO_TOKEN_TYPE_DEF: {
7147 guint32 cols [MONO_TYPEDEF_SIZE];
7148 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7149 guint tidx = mono_metadata_token_index (type_token);
7151 if (tidx > tt->rows)
7152 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7154 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7155 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7156 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7157 if (strlen (nspace) == 0)
7158 return g_strdup_printf ("%s", name);
7160 return g_strdup_printf ("%s.%s", nspace, name);
7163 case MONO_TOKEN_TYPE_REF: {
7165 guint32 cols [MONO_TYPEREF_SIZE];
7166 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7167 guint tidx = mono_metadata_token_index (type_token);
7170 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7172 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7173 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7174 mono_error_cleanup (&error);
7178 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7179 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7180 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7181 if (strlen (nspace) == 0)
7182 return g_strdup_printf ("%s", name);
7184 return g_strdup_printf ("%s.%s", nspace, name);
7187 case MONO_TOKEN_TYPE_SPEC:
7188 return g_strdup_printf ("Typespec 0x%08x", type_token);
7190 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7195 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7197 if (image_is_dynamic (image))
7198 return g_strdup_printf ("DynamicAssembly %s", image->name);
7200 switch (type_token & 0xff000000){
7201 case MONO_TOKEN_TYPE_DEF:
7202 if (image->assembly)
7203 return mono_stringify_assembly_name (&image->assembly->aname);
7204 else if (image->assembly_name)
7205 return g_strdup (image->assembly_name);
7206 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7207 case MONO_TOKEN_TYPE_REF: {
7209 MonoAssemblyName aname;
7210 guint32 cols [MONO_TYPEREF_SIZE];
7211 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7212 guint32 idx = mono_metadata_token_index (type_token);
7215 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7217 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7218 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7219 mono_error_cleanup (&error);
7222 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7224 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7225 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7226 case MONO_RESOLUTION_SCOPE_MODULE:
7228 return g_strdup ("");
7229 case MONO_RESOLUTION_SCOPE_MODULEREF:
7231 return g_strdup ("");
7232 case MONO_RESOLUTION_SCOPE_TYPEREF:
7234 return g_strdup ("");
7235 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7236 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7237 return mono_stringify_assembly_name (&aname);
7239 g_assert_not_reached ();
7243 case MONO_TOKEN_TYPE_SPEC:
7245 return g_strdup ("");
7247 g_assert_not_reached ();
7254 * mono_class_get_full:
7255 * \param image the image where the class resides
7256 * \param type_token the token for the class
7257 * \param context the generic context used to evaluate generic instantiations in
7258 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7259 * \returns The \c MonoClass that represents \p type_token in \p image
7262 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7266 klass = mono_class_get_checked (image, type_token, &error);
7268 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7269 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7271 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7277 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7282 klass = mono_class_get_checked (image, type_token, error);
7284 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7285 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7290 * mono_class_get_checked:
7291 * \param image the image where the class resides
7292 * \param type_token the token for the class
7293 * \param error error object to return any error
7295 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7298 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7300 MonoClass *klass = NULL;
7304 if (image_is_dynamic (image)) {
7305 int table = mono_metadata_token_table (type_token);
7307 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7308 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7311 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7315 switch (type_token & 0xff000000){
7316 case MONO_TOKEN_TYPE_DEF:
7317 klass = mono_class_create_from_typedef (image, type_token, error);
7319 case MONO_TOKEN_TYPE_REF:
7320 klass = mono_class_from_typeref_checked (image, type_token, error);
7322 case MONO_TOKEN_TYPE_SPEC:
7323 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7326 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7330 /* Generic case, should be avoided for when a better error is possible. */
7331 if (!klass && mono_error_ok (error)) {
7332 char *name = mono_class_name_from_token (image, type_token);
7333 char *assembly = mono_assembly_name_from_token (image, type_token);
7334 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7342 * mono_type_get_checked:
7343 * \param image the image where the type resides
7344 * \param type_token the token for the type
7345 * \param context the generic context used to evaluate generic instantiations in
7346 * \param error Error handling context
7348 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7350 * \returns The MonoType that represents \p type_token in \p image
7353 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7355 MonoType *type = NULL;
7356 gboolean inflated = FALSE;
7360 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7361 if (image_is_dynamic (image)) {
7362 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7363 return_val_if_nok (error, NULL);
7364 return mono_class_get_type (klass);
7367 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7368 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7375 return mono_class_get_type (klass);
7378 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7385 MonoType *tmp = type;
7386 type = mono_class_get_type (mono_class_from_mono_type (type));
7387 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7388 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7389 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7391 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7393 if (type->type != tmp->type)
7396 mono_metadata_free_type (tmp);
7403 * \param image image where the class token will be looked up.
7404 * \param type_token a type token from the image
7405 * \returns the \c MonoClass with the given \p type_token on the \p image
7408 mono_class_get (MonoImage *image, guint32 type_token)
7410 return mono_class_get_full (image, type_token, NULL);
7414 * mono_image_init_name_cache:
7416 * Initializes the class name cache stored in image->name_cache.
7418 * LOCKING: Acquires the corresponding image lock.
7421 mono_image_init_name_cache (MonoImage *image)
7423 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7424 guint32 cols [MONO_TYPEDEF_SIZE];
7427 guint32 i, visib, nspace_index;
7428 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7430 if (image->name_cache)
7433 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7435 if (image_is_dynamic (image)) {
7436 mono_image_lock (image);
7437 if (image->name_cache) {
7438 /* Somebody initialized it before us */
7439 g_hash_table_destroy (the_name_cache);
7441 mono_atomic_store_release (&image->name_cache, the_name_cache);
7443 mono_image_unlock (image);
7447 /* Temporary hash table to avoid lookups in the nspace_table */
7448 name_cache2 = g_hash_table_new (NULL, NULL);
7450 for (i = 1; i <= t->rows; ++i) {
7451 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7452 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7454 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7455 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7457 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7459 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7460 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7462 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7463 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7464 if (!nspace_table) {
7465 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7466 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7467 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7470 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7473 /* Load type names from EXPORTEDTYPES table */
7475 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7476 guint32 cols [MONO_EXP_TYPE_SIZE];
7479 for (i = 0; i < t->rows; ++i) {
7480 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7482 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7483 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7487 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7488 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7490 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7491 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7492 if (!nspace_table) {
7493 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7494 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7495 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7498 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7502 g_hash_table_destroy (name_cache2);
7504 mono_image_lock (image);
7505 if (image->name_cache) {
7506 /* Somebody initialized it before us */
7507 g_hash_table_destroy (the_name_cache);
7509 mono_atomic_store_release (&image->name_cache, the_name_cache);
7511 mono_image_unlock (image);
7514 /*FIXME Only dynamic assemblies should allow this operation.*/
7516 * mono_image_add_to_name_cache:
7519 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7520 const char *name, guint32 index)
7522 GHashTable *nspace_table;
7523 GHashTable *name_cache;
7526 mono_image_init_name_cache (image);
7527 mono_image_lock (image);
7529 name_cache = image->name_cache;
7530 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7531 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7532 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7535 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7536 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7538 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7540 mono_image_unlock (image);
7549 find_nocase (gpointer key, gpointer value, gpointer user_data)
7551 char *name = (char*)key;
7552 FindUserData *data = (FindUserData*)user_data;
7554 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7555 data->value = value;
7559 * mono_class_from_name_case:
7560 * \param image The MonoImage where the type is looked up in
7561 * \param name_space the type namespace
7562 * \param name the type short name.
7563 * \deprecated use the mono_class_from_name_case_checked variant instead.
7565 * Obtains a \c MonoClass with a given namespace and a given name which
7566 * is located in the given \c MonoImage. The namespace and name
7567 * lookups are case insensitive.
7570 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7573 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7574 mono_error_cleanup (&error);
7580 * mono_class_from_name_case_checked:
7581 * \param image The MonoImage where the type is looked up in
7582 * \param name_space the type namespace
7583 * \param name the type short name.
7586 * Obtains a MonoClass with a given namespace and a given name which
7587 * is located in the given MonoImage. The namespace and name
7588 * lookups are case insensitive.
7590 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7591 * was not found. The \p error object will contain information about the problem
7595 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7597 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7598 guint32 cols [MONO_TYPEDEF_SIZE];
7605 if (image_is_dynamic (image)) {
7607 FindUserData user_data;
7609 mono_image_init_name_cache (image);
7610 mono_image_lock (image);
7612 user_data.key = name_space;
7613 user_data.value = NULL;
7614 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7616 if (user_data.value) {
7617 GHashTable *nspace_table = (GHashTable*)user_data.value;
7619 user_data.key = name;
7620 user_data.value = NULL;
7622 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7624 if (user_data.value)
7625 token = GPOINTER_TO_UINT (user_data.value);
7628 mono_image_unlock (image);
7631 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7637 /* add a cache if needed */
7638 for (i = 1; i <= t->rows; ++i) {
7639 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7640 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7642 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7643 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7645 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7647 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7648 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7649 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7650 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7656 return_nested_in (MonoClass *klass, char *nested)
7659 char *s = strchr (nested, '/');
7660 gpointer iter = NULL;
7667 while ((found = mono_class_get_nested_types (klass, &iter))) {
7668 if (strcmp (found->name, nested) == 0) {
7670 return return_nested_in (found, s);
7678 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7680 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7681 MonoImage *file_image;
7688 * The EXPORTEDTYPES table only contains public types, so have to search the
7690 * Note: image->modules contains the contents of the MODULEREF table, while
7691 * the real module list is in the FILE table.
7693 for (i = 0; i < file_table->rows; i++) {
7694 guint32 cols [MONO_FILE_SIZE];
7695 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7696 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7699 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7701 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7702 if (klass || !is_ok (error))
7711 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7713 GHashTable *nspace_table;
7714 MonoImage *loaded_image;
7723 // Checking visited images avoids stack overflows when cyclic references exist.
7724 if (g_hash_table_lookup (visited_images, image))
7727 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7729 if ((nested = strchr (name, '/'))) {
7730 int pos = nested - name;
7731 int len = strlen (name);
7734 memcpy (buf, name, len + 1);
7736 nested = buf + pos + 1;
7740 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7741 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7742 gboolean res = get_class_from_name (image, name_space, name, &klass);
7745 klass = search_modules (image, name_space, name, error);
7750 return klass ? return_nested_in (klass, nested) : NULL;
7756 mono_image_init_name_cache (image);
7757 mono_image_lock (image);
7759 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7762 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7764 mono_image_unlock (image);
7766 if (!token && image_is_dynamic (image) && image->modules) {
7767 /* Search modules as well */
7768 for (i = 0; i < image->module_count; ++i) {
7769 MonoImage *module = image->modules [i];
7771 klass = mono_class_from_name_checked (module, name_space, name, error);
7772 if (klass || !is_ok (error))
7778 klass = search_modules (image, name_space, name, error);
7779 if (klass || !is_ok (error))
7784 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7785 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7786 guint32 cols [MONO_EXP_TYPE_SIZE];
7789 idx = mono_metadata_token_index (token);
7791 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7793 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7794 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7795 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7798 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7800 return klass ? return_nested_in (klass, nested) : NULL;
7802 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7803 guint32 assembly_idx;
7805 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7807 mono_assembly_load_reference (image, assembly_idx - 1);
7808 g_assert (image->references [assembly_idx - 1]);
7809 if (image->references [assembly_idx - 1] == (gpointer)-1)
7811 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7813 return klass ? return_nested_in (klass, nested) : NULL;
7816 g_assert_not_reached ();
7820 token = MONO_TOKEN_TYPE_DEF | token;
7822 klass = mono_class_get_checked (image, token, error);
7824 return return_nested_in (klass, nested);
7829 * mono_class_from_name_checked:
7830 * \param image The MonoImage where the type is looked up in
7831 * \param name_space the type namespace
7832 * \param name the type short name.
7834 * Obtains a MonoClass with a given namespace and a given name which
7835 * is located in the given MonoImage.
7837 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7838 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7841 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7844 GHashTable *visited_images;
7846 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7848 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7850 g_hash_table_destroy (visited_images);
7856 * mono_class_from_name:
7857 * \param image The \c MonoImage where the type is looked up in
7858 * \param name_space the type namespace
7859 * \param name the type short name.
7861 * Obtains a \c MonoClass with a given namespace and a given name which
7862 * is located in the given \c MonoImage.
7864 * To reference nested classes, use the "/" character as a separator.
7865 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7866 * inside \c Foo, like this: "class Foo { class Bar {} }".
7869 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7874 klass = mono_class_from_name_checked (image, name_space, name, &error);
7875 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7881 * mono_class_load_from_name:
7882 * \param image The MonoImage where the type is looked up in
7883 * \param name_space the type namespace
7884 * \param name the type short name.
7886 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7887 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7888 * If they are missing. Thing of System.Object or System.String.
7891 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7896 klass = mono_class_from_name_checked (image, name_space, name, &error);
7898 g_error ("Runtime critical type %s.%s not found", name_space, name);
7899 if (!mono_error_ok (&error))
7900 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7905 * mono_class_try_load_from_name:
7906 * \param image The MonoImage where the type is looked up in
7907 * \param name_space the type namespace
7908 * \param name the type short name.
7910 * This function tries to load a type, returning the class was found or NULL otherwise.
7911 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7913 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7914 * a type that we would otherwise assume to be available but was not due some error.
7918 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7923 klass = mono_class_from_name_checked (image, name_space, name, &error);
7924 if (!mono_error_ok (&error))
7925 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7931 * mono_class_is_subclass_of:
7932 * \param klass class to probe if it is a subclass of another one
7933 * \param klassc the class we suspect is the base class
7934 * \param check_interfaces whether we should perform interface checks
7936 * This method determines whether \p klass is a subclass of \p klassc.
7938 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7939 * this method return TRUE if the \p klass implements the interface or
7940 * if \p klass is an interface, if one of its base classes is \p klass.
7942 * If \p check_interfaces is false, then if \p klass is not an interface,
7943 * it returns TRUE if the \p klass is a subclass of \p klassc.
7945 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7950 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7951 gboolean check_interfaces)
7953 /* FIXME test for interfaces with variant generic arguments */
7954 mono_class_init (klass);
7955 mono_class_init (klassc);
7957 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7958 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7960 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7963 for (i = 0; i < klass->interface_count; i ++) {
7964 MonoClass *ic = klass->interfaces [i];
7969 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7974 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7977 if (klassc == mono_defaults.object_class)
7984 mono_type_is_generic_argument (MonoType *type)
7986 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7990 mono_class_has_variant_generic_params (MonoClass *klass)
7993 MonoGenericContainer *container;
7995 if (!mono_class_is_ginst (klass))
7998 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8000 for (i = 0; i < container->type_argc; ++i)
8001 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8008 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8010 if (target == candidate)
8013 if (check_for_reference_conv &&
8014 mono_type_is_generic_argument (&target->byval_arg) &&
8015 mono_type_is_generic_argument (&candidate->byval_arg)) {
8016 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8017 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8019 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8022 if (!mono_class_is_assignable_from (target, candidate))
8028 * @container the generic container from the GTD
8029 * @klass: the class to be assigned to
8030 * @oklass: the source class
8032 * Both @klass and @oklass must be instances of the same generic interface.
8034 * Returns: TRUE if @klass can be assigned to a @klass variable
8037 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8040 MonoType **klass_argv, **oklass_argv;
8041 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8042 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8044 if (klass == oklass)
8047 /*Viable candidates are instances of the same generic interface*/
8048 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8051 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8052 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8054 for (j = 0; j < container->type_argc; ++j) {
8055 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8056 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8058 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8062 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8063 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8065 if (param1_class != param2_class) {
8066 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8067 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8069 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8070 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8080 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8082 MonoGenericParam *gparam, *ogparam;
8083 MonoGenericParamInfo *tinfo, *cinfo;
8084 MonoClass **candidate_class;
8085 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8088 if (target == candidate)
8090 if (target->byval_arg.type != candidate->byval_arg.type)
8093 gparam = target->byval_arg.data.generic_param;
8094 ogparam = candidate->byval_arg.data.generic_param;
8095 tinfo = mono_generic_param_info (gparam);
8096 cinfo = mono_generic_param_info (ogparam);
8098 class_constraint_satisfied = FALSE;
8099 valuetype_constraint_satisfied = FALSE;
8101 /*candidate must have a super set of target's special constraints*/
8102 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8103 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8105 if (cinfo->constraints) {
8106 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8107 MonoClass *cc = *candidate_class;
8109 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8110 class_constraint_satisfied = TRUE;
8111 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8112 valuetype_constraint_satisfied = TRUE;
8115 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8116 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8118 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8120 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8122 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8123 valuetype_constraint_satisfied)) {
8128 /*candidate type constraints must be a superset of target's*/
8129 if (tinfo->constraints) {
8130 MonoClass **target_class;
8131 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8132 MonoClass *tc = *target_class;
8135 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8136 * check it's constraints since it satisfy the constraint by itself.
8138 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8141 if (!cinfo->constraints)
8144 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8145 MonoClass *cc = *candidate_class;
8147 if (mono_class_is_assignable_from (tc, cc))
8151 * This happens when we have the following:
8153 * Bar<K> where K : IFace
8154 * Foo<T, U> where T : U where U : IFace
8156 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8159 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8160 if (mono_gparam_is_assignable_from (target, cc))
8164 if (!*candidate_class)
8169 /*candidate itself must have a constraint that satisfy target*/
8170 if (cinfo->constraints) {
8171 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8172 MonoClass *cc = *candidate_class;
8173 if (mono_class_is_assignable_from (target, cc))
8181 * mono_class_is_assignable_from:
8182 * \param klass the class to be assigned to
8183 * \param oklass the source class
8185 * \returns TRUE if an instance of class \p oklass can be assigned to an
8186 * instance of class \p klass
8189 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8192 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8194 mono_class_init (klass);
8196 if (!oklass->inited)
8197 mono_class_init (oklass);
8199 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8202 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8203 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8205 return mono_gparam_is_assignable_from (klass, oklass);
8208 if (MONO_CLASS_IS_INTERFACE (klass)) {
8209 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8210 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8211 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8215 for (i = 0; constraints [i]; ++i) {
8216 if (mono_class_is_assignable_from (klass, constraints [i]))
8224 /* interface_offsets might not be set for dynamic classes */
8225 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8227 * oklass might be a generic type parameter but they have
8228 * interface_offsets set.
8230 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8231 if (!is_ok (&error)) {
8232 mono_error_cleanup (&error);
8237 if (!oklass->interface_bitmap)
8238 /* Happens with generic instances of not-yet created dynamic types */
8240 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8243 if (klass->is_array_special_interface && oklass->rank == 1) {
8244 //XXX we could offset this by having the cast target computed at JIT time
8245 //XXX we could go even further and emit a wrapper that would do the extra type check
8246 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8247 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8249 // 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
8250 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8251 if (iface_klass->valuetype)
8252 iface_klass = iface_klass->cast_class;
8254 //array covariant casts only operates on scalar to scalar
8255 //This is so int[] can't be casted to IComparable<int>[]
8256 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8260 if (mono_class_has_variant_generic_params (klass)) {
8262 mono_class_setup_interfaces (oklass, &error);
8263 if (!mono_error_ok (&error)) {
8264 mono_error_cleanup (&error);
8268 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8269 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8270 MonoClass *iface = oklass->interfaces_packed [i];
8272 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8277 } else if (klass->delegate) {
8278 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8280 }else if (klass->rank) {
8281 MonoClass *eclass, *eoclass;
8283 if (oklass->rank != klass->rank)
8286 /* vectors vs. one dimensional arrays */
8287 if (oklass->byval_arg.type != klass->byval_arg.type)
8290 eclass = klass->cast_class;
8291 eoclass = oklass->cast_class;
8294 * a is b does not imply a[] is b[] when a is a valuetype, and
8295 * b is a reference type.
8298 if (eoclass->valuetype) {
8299 if ((eclass == mono_defaults.enum_class) ||
8300 (eclass == mono_defaults.enum_class->parent) ||
8301 (eclass == mono_defaults.object_class))
8305 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8306 } else if (mono_class_is_nullable (klass)) {
8307 if (mono_class_is_nullable (oklass))
8308 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8310 return mono_class_is_assignable_from (klass->cast_class, oklass);
8311 } else if (klass == mono_defaults.object_class)
8314 return mono_class_has_parent (oklass, klass);
8317 /*Check if @oklass is variant compatible with @klass.*/
8319 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8322 MonoType **klass_argv, **oklass_argv;
8323 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8324 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8326 /*Viable candidates are instances of the same generic interface*/
8327 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8330 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8331 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8333 for (j = 0; j < container->type_argc; ++j) {
8334 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8335 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8337 if (param1_class->valuetype != param2_class->valuetype)
8341 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8342 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8344 if (param1_class != param2_class) {
8345 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8346 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8348 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8349 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8357 /*Check if @candidate implements the interface @target*/
8359 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8363 gboolean is_variant = mono_class_has_variant_generic_params (target);
8365 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8366 if (mono_class_is_variant_compatible_slow (target, candidate))
8371 if (candidate == target)
8374 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8375 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8376 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8378 if (tb && tb->interfaces) {
8379 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8380 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8381 MonoClass *iface_class;
8383 /* we can't realize the type here since it can do pretty much anything. */
8386 iface_class = mono_class_from_mono_type (iface->type);
8387 if (iface_class == target)
8389 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8391 if (mono_class_implement_interface_slow (target, iface_class))
8396 /*setup_interfaces don't mono_class_init anything*/
8397 /*FIXME this doesn't handle primitive type arrays.
8398 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8399 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8401 mono_class_setup_interfaces (candidate, &error);
8402 if (!mono_error_ok (&error)) {
8403 mono_error_cleanup (&error);
8407 for (i = 0; i < candidate->interface_count; ++i) {
8408 if (candidate->interfaces [i] == target)
8411 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8414 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8418 candidate = candidate->parent;
8419 } while (candidate);
8425 * Check if @oklass can be assigned to @klass.
8426 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8429 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8431 if (candidate == target)
8433 if (target == mono_defaults.object_class)
8436 if (mono_class_has_parent (candidate, target))
8439 /*If target is not an interface there is no need to check them.*/
8440 if (MONO_CLASS_IS_INTERFACE (target))
8441 return mono_class_implement_interface_slow (target, candidate);
8443 if (target->delegate && mono_class_has_variant_generic_params (target))
8444 return mono_class_is_variant_compatible (target, candidate, FALSE);
8447 MonoClass *eclass, *eoclass;
8449 if (target->rank != candidate->rank)
8452 /* vectors vs. one dimensional arrays */
8453 if (target->byval_arg.type != candidate->byval_arg.type)
8456 eclass = target->cast_class;
8457 eoclass = candidate->cast_class;
8460 * a is b does not imply a[] is b[] when a is a valuetype, and
8461 * b is a reference type.
8464 if (eoclass->valuetype) {
8465 if ((eclass == mono_defaults.enum_class) ||
8466 (eclass == mono_defaults.enum_class->parent) ||
8467 (eclass == mono_defaults.object_class))
8471 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8473 /*FIXME properly handle nullables */
8474 /*FIXME properly handle (M)VAR */
8479 * mono_class_get_cctor:
8480 * \param klass A MonoClass pointer
8482 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8485 mono_class_get_cctor (MonoClass *klass)
8487 MonoCachedClassInfo cached_info;
8489 if (image_is_dynamic (klass->image)) {
8491 * has_cctor is not set for these classes because mono_class_init () is
8494 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8497 mono_class_init (klass);
8499 if (!klass->has_cctor)
8502 if (mono_class_is_ginst (klass) && !klass->methods)
8503 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8505 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8507 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8508 if (!mono_error_ok (&error))
8509 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8513 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8517 * mono_class_get_finalizer:
8518 * \param klass: The MonoClass pointer
8520 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8523 mono_class_get_finalizer (MonoClass *klass)
8525 MonoCachedClassInfo cached_info;
8528 mono_class_init (klass);
8529 if (!mono_class_has_finalizer (klass))
8532 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8534 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8535 if (!mono_error_ok (&error))
8536 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8539 mono_class_setup_vtable (klass);
8540 return klass->vtable [finalize_slot];
8545 * mono_class_needs_cctor_run:
8546 * \param klass the MonoClass pointer
8547 * \param caller a MonoMethod describing the caller
8549 * Determines whenever the class has a static constructor and whenever it
8550 * needs to be called when executing CALLER.
8553 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8557 method = mono_class_get_cctor (klass);
8559 return (method == caller) ? FALSE : TRUE;
8565 * mono_class_array_element_size:
8568 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8571 mono_class_array_element_size (MonoClass *klass)
8573 MonoType *type = &klass->byval_arg;
8576 switch (type->type) {
8579 case MONO_TYPE_BOOLEAN:
8583 case MONO_TYPE_CHAR:
8592 case MONO_TYPE_CLASS:
8593 case MONO_TYPE_STRING:
8594 case MONO_TYPE_OBJECT:
8595 case MONO_TYPE_SZARRAY:
8596 case MONO_TYPE_ARRAY:
8597 return sizeof (gpointer);
8602 case MONO_TYPE_VALUETYPE:
8603 if (type->data.klass->enumtype) {
8604 type = mono_class_enum_basetype (type->data.klass);
8605 klass = klass->element_class;
8608 return mono_class_instance_size (klass) - sizeof (MonoObject);
8609 case MONO_TYPE_GENERICINST:
8610 type = &type->data.generic_class->container_class->byval_arg;
8613 case MONO_TYPE_MVAR: {
8616 return mono_type_size (type, &align);
8618 case MONO_TYPE_VOID:
8622 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8628 * mono_array_element_size:
8629 * \param ac pointer to a \c MonoArrayClass
8631 * \returns The size of single array element.
8634 mono_array_element_size (MonoClass *ac)
8636 g_assert (ac->rank);
8637 return ac->sizes.element_size;
8644 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8645 MonoGenericContext *context)
8648 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8649 g_assert (mono_error_ok (&error));
8654 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8655 MonoGenericContext *context, MonoError *error)
8659 if (image_is_dynamic (image)) {
8660 MonoClass *tmp_handle_class;
8661 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8663 mono_error_assert_ok (error);
8664 g_assert (tmp_handle_class);
8666 *handle_class = tmp_handle_class;
8668 if (tmp_handle_class == mono_defaults.typehandle_class)
8669 return &((MonoClass*)obj)->byval_arg;
8674 switch (token & 0xff000000) {
8675 case MONO_TOKEN_TYPE_DEF:
8676 case MONO_TOKEN_TYPE_REF:
8677 case MONO_TOKEN_TYPE_SPEC: {
8680 *handle_class = mono_defaults.typehandle_class;
8681 type = mono_type_get_checked (image, token, context, error);
8685 mono_class_init (mono_class_from_mono_type (type));
8686 /* We return a MonoType* as handle */
8689 case MONO_TOKEN_FIELD_DEF: {
8691 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8693 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8697 *handle_class = mono_defaults.fieldhandle_class;
8698 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8702 mono_class_init (klass);
8703 return mono_class_get_field (klass, token);
8705 case MONO_TOKEN_METHOD_DEF:
8706 case MONO_TOKEN_METHOD_SPEC: {
8708 meth = mono_get_method_checked (image, token, NULL, context, error);
8710 *handle_class = mono_defaults.methodhandle_class;
8716 case MONO_TOKEN_MEMBER_REF: {
8717 guint32 cols [MONO_MEMBERREF_SIZE];
8719 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8720 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8721 mono_metadata_decode_blob_size (sig, &sig);
8722 if (*sig == 0x6) { /* it's a field */
8724 MonoClassField *field;
8725 field = mono_field_from_token_checked (image, token, &klass, context, error);
8727 *handle_class = mono_defaults.fieldhandle_class;
8731 meth = mono_get_method_checked (image, token, NULL, context, error);
8733 *handle_class = mono_defaults.methodhandle_class;
8738 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8744 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8746 MonoClass *handle_class;
8748 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8752 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8754 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8757 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8760 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8762 get_cached_class_info = func;
8766 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8768 if (!get_cached_class_info)
8771 return get_cached_class_info (klass, res);
8775 mono_install_get_class_from_name (MonoGetClassFromName func)
8777 get_class_from_name = func;
8781 * mono_class_get_image:
8783 * Use this method to get the \c MonoImage* where this class came from.
8785 * \returns The image where this class is defined.
8788 mono_class_get_image (MonoClass *klass)
8790 return klass->image;
8794 * mono_class_get_element_class:
8795 * \param klass the \c MonoClass to act on
8797 * Use this function to get the element class of an array.
8799 * \returns The element class of an array.
8802 mono_class_get_element_class (MonoClass *klass)
8804 return klass->element_class;
8808 * mono_class_is_valuetype:
8809 * \param klass the \c MonoClass to act on
8811 * Use this method to determine if the provided \c MonoClass* represents a value type,
8812 * or a reference type.
8814 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8817 mono_class_is_valuetype (MonoClass *klass)
8819 return klass->valuetype;
8823 * mono_class_is_enum:
8824 * \param klass the \c MonoClass to act on
8826 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8828 * \returns TRUE if the \c MonoClass represents an enumeration.
8831 mono_class_is_enum (MonoClass *klass)
8833 return klass->enumtype;
8837 * mono_class_enum_basetype:
8838 * \param klass the \c MonoClass to act on
8840 * Use this function to get the underlying type for an enumeration value.
8842 * \returns The underlying type representation for an enumeration.
8845 mono_class_enum_basetype (MonoClass *klass)
8847 if (klass->element_class == klass)
8848 /* SRE or broken types */
8851 return &klass->element_class->byval_arg;
8855 * mono_class_get_parent
8856 * \param klass the \c MonoClass to act on
8858 * \returns The parent class for this class.
8861 mono_class_get_parent (MonoClass *klass)
8863 return klass->parent;
8867 * mono_class_get_nesting_type:
8868 * \param klass the \c MonoClass to act on
8870 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8872 * If the return is NULL, this indicates that this class is not nested.
8874 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8877 mono_class_get_nesting_type (MonoClass *klass)
8879 return klass->nested_in;
8883 * mono_class_get_rank:
8884 * \param klass the MonoClass to act on
8886 * \returns The rank for the array (the number of dimensions).
8889 mono_class_get_rank (MonoClass *klass)
8895 * mono_class_get_name
8896 * \param klass the \c MonoClass to act on
8898 * \returns The name of the class.
8901 mono_class_get_name (MonoClass *klass)
8907 * mono_class_get_namespace:
8908 * \param klass the \c MonoClass to act on
8910 * \returns The namespace of the class.
8913 mono_class_get_namespace (MonoClass *klass)
8915 return klass->name_space;
8919 * mono_class_get_type:
8920 * \param klass the \c MonoClass to act on
8922 * This method returns the internal \c MonoType representation for the class.
8924 * \returns The \c MonoType from the class.
8927 mono_class_get_type (MonoClass *klass)
8929 return &klass->byval_arg;
8933 * mono_class_get_type_token:
8934 * \param klass the \c MonoClass to act on
8936 * This method returns type token for the class.
8938 * \returns The type token for the class.
8941 mono_class_get_type_token (MonoClass *klass)
8943 return klass->type_token;
8947 * mono_class_get_byref_type:
8948 * \param klass the \c MonoClass to act on
8953 mono_class_get_byref_type (MonoClass *klass)
8955 return &klass->this_arg;
8959 * mono_class_num_fields:
8960 * \param klass the \c MonoClass to act on
8962 * \returns The number of static and instance fields in the class.
8965 mono_class_num_fields (MonoClass *klass)
8967 return mono_class_get_field_count (klass);
8971 * mono_class_num_methods:
8972 * \param klass the \c MonoClass to act on
8974 * \returns The number of methods in the class.
8977 mono_class_num_methods (MonoClass *klass)
8979 return mono_class_get_method_count (klass);
8983 * mono_class_num_properties
8984 * \param klass the \c MonoClass to act on
8986 * \returns The number of properties in the class.
8989 mono_class_num_properties (MonoClass *klass)
8991 mono_class_setup_properties (klass);
8993 return mono_class_get_property_info (klass)->count;
8997 * mono_class_num_events:
8998 * \param klass the \c MonoClass to act on
9000 * \returns The number of events in the class.
9003 mono_class_num_events (MonoClass *klass)
9005 mono_class_setup_events (klass);
9007 return mono_class_get_event_info (klass)->count;
9011 * mono_class_get_fields:
9012 * \param klass the \c MonoClass to act on
9014 * This routine is an iterator routine for retrieving the fields in a class.
9016 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9017 * iterate over all of the elements. When no more values are
9018 * available, the return value is NULL.
9020 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9023 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9025 MonoClassField* field;
9029 mono_class_setup_fields (klass);
9030 if (mono_class_has_failure (klass))
9032 /* start from the first */
9033 if (mono_class_get_field_count (klass)) {
9034 *iter = &klass->fields [0];
9035 return &klass->fields [0];
9041 field = (MonoClassField *)*iter;
9043 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9051 * mono_class_get_methods:
9052 * \param klass the \c MonoClass to act on
9054 * This routine is an iterator routine for retrieving the fields in a class.
9056 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9057 * iterate over all of the elements. When no more values are
9058 * available, the return value is NULL.
9060 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9063 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9065 MonoMethod** method;
9069 mono_class_setup_methods (klass);
9072 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9073 * FIXME we should better report this error to the caller
9075 if (!klass->methods)
9077 /* start from the first */
9078 if (mono_class_get_method_count (klass)) {
9079 *iter = &klass->methods [0];
9080 return klass->methods [0];
9086 method = (MonoMethod **)*iter;
9088 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9096 * mono_class_get_virtual_methods:
9098 * Iterate over the virtual methods of KLASS.
9100 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9103 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9105 MonoMethod** method;
9108 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9110 mono_class_setup_methods (klass);
9112 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9113 * FIXME we should better report this error to the caller
9115 if (!klass->methods)
9117 /* start from the first */
9118 method = &klass->methods [0];
9120 method = (MonoMethod **)*iter;
9123 int mcount = mono_class_get_method_count (klass);
9124 while (method < &klass->methods [mcount]) {
9125 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9129 if (method < &klass->methods [mcount]) {
9136 /* Search directly in metadata to avoid calling setup_methods () */
9137 MonoMethod *res = NULL;
9143 start_index = GPOINTER_TO_UINT (*iter);
9146 int first_idx = mono_class_get_first_method_idx (klass);
9147 int mcount = mono_class_get_method_count (klass);
9148 for (i = start_index; i < mcount; ++i) {
9151 /* first_idx points into the methodptr table */
9152 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9154 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9160 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9161 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9163 /* Add 1 here so the if (*iter) check fails */
9164 *iter = GUINT_TO_POINTER (i + 1);
9173 * mono_class_get_properties:
9174 * \param klass the \c MonoClass to act on
9176 * This routine is an iterator routine for retrieving the properties in a class.
9178 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9179 * iterate over all of the elements. When no more values are
9180 * available, the return value is NULL.
9182 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9185 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9187 MonoProperty* property;
9191 mono_class_setup_properties (klass);
9192 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9193 /* start from the first */
9195 *iter = &info->properties [0];
9196 return (MonoProperty *)*iter;
9202 property = (MonoProperty *)*iter;
9204 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9205 if (property < &info->properties [info->count]) {
9207 return (MonoProperty *)*iter;
9213 * mono_class_get_events:
9214 * \param klass the \c MonoClass to act on
9216 * This routine is an iterator routine for retrieving the properties in a class.
9218 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9219 * iterate over all of the elements. When no more values are
9220 * available, the return value is NULL.
9222 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9225 mono_class_get_events (MonoClass* klass, gpointer *iter)
9231 mono_class_setup_events (klass);
9232 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9233 /* start from the first */
9235 *iter = &info->events [0];
9236 return (MonoEvent *)*iter;
9242 event = (MonoEvent *)*iter;
9244 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9245 if (event < &info->events [info->count]) {
9247 return (MonoEvent *)*iter;
9253 * mono_class_get_interfaces
9254 * \param klass the \c MonoClass to act on
9256 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9258 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9259 * iterate over all of the elements. When no more values are
9260 * available, the return value is NULL.
9262 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9265 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9273 mono_class_init (klass);
9274 if (!klass->interfaces_inited) {
9275 mono_class_setup_interfaces (klass, &error);
9276 if (!mono_error_ok (&error)) {
9277 mono_error_cleanup (&error);
9281 /* start from the first */
9282 if (klass->interface_count) {
9283 *iter = &klass->interfaces [0];
9284 return klass->interfaces [0];
9290 iface = (MonoClass **)*iter;
9292 if (iface < &klass->interfaces [klass->interface_count]) {
9300 setup_nested_types (MonoClass *klass)
9303 GList *classes, *nested_classes, *l;
9306 if (klass->nested_classes_inited)
9309 if (!klass->type_token) {
9310 mono_loader_lock ();
9311 klass->nested_classes_inited = TRUE;
9312 mono_loader_unlock ();
9316 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9320 guint32 cols [MONO_NESTED_CLASS_SIZE];
9321 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9322 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9323 if (!mono_error_ok (&error)) {
9324 /*FIXME don't swallow the error message*/
9325 mono_error_cleanup (&error);
9327 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9331 classes = g_list_prepend (classes, nclass);
9333 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9336 nested_classes = NULL;
9337 for (l = classes; l; l = l->next)
9338 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9339 g_list_free (classes);
9341 mono_loader_lock ();
9342 if (!klass->nested_classes_inited) {
9343 mono_class_set_nested_classes_property (klass, nested_classes);
9344 mono_memory_barrier ();
9345 klass->nested_classes_inited = TRUE;
9347 mono_loader_unlock ();
9351 * mono_class_get_nested_types
9352 * \param klass the \c MonoClass to act on
9354 * This routine is an iterator routine for retrieving the nested types of a class.
9355 * This works only if \p klass is non-generic, or a generic type definition.
9357 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9358 * iterate over all of the elements. When no more values are
9359 * available, the return value is NULL.
9361 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9364 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9370 if (!klass->nested_classes_inited)
9371 setup_nested_types (klass);
9374 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9375 /* start from the first */
9376 if (nested_classes) {
9377 *iter = nested_classes;
9378 return (MonoClass *)nested_classes->data;
9380 /* no nested types */
9384 item = (GList *)*iter;
9388 return (MonoClass *)item->data;
9395 * mono_class_is_delegate
9396 * \param klass the \c MonoClass to act on
9398 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9401 mono_class_is_delegate (MonoClass *klass)
9403 return klass->delegate;
9407 * mono_class_implements_interface
9408 * \param klass The MonoClass to act on
9409 * \param interface The interface to check if \p klass implements.
9411 * \returns TRUE if \p klass implements \p interface.
9414 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9416 return mono_class_is_assignable_from (iface, klass);
9420 * mono_field_get_name:
9421 * \param field the \c MonoClassField to act on
9423 * \returns The name of the field.
9426 mono_field_get_name (MonoClassField *field)
9432 * mono_field_get_type:
9433 * \param field the \c MonoClassField to act on
9434 * \returns \c MonoType of the field.
9437 mono_field_get_type (MonoClassField *field)
9440 MonoType *type = mono_field_get_type_checked (field, &error);
9441 if (!mono_error_ok (&error)) {
9442 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9443 mono_error_cleanup (&error);
9450 * mono_field_get_type_checked:
9451 * \param field the \c MonoClassField to act on
9452 * \param error used to return any error found while retrieving \p field type
9454 * \returns \c MonoType of the field.
9457 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9461 mono_field_resolve_type (field, error);
9466 * mono_field_get_parent:
9467 * \param field the \c MonoClassField to act on
9469 * \returns \c MonoClass where the field was defined.
9472 mono_field_get_parent (MonoClassField *field)
9474 return field->parent;
9478 * mono_field_get_flags;
9479 * \param field the \c MonoClassField to act on
9481 * The metadata flags for a field are encoded using the
9482 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9484 * \returns The flags for the field.
9487 mono_field_get_flags (MonoClassField *field)
9490 return mono_field_resolve_flags (field);
9491 return field->type->attrs;
9495 * mono_field_get_offset:
9496 * \param field the \c MonoClassField to act on
9498 * \returns The field offset.
9501 mono_field_get_offset (MonoClassField *field)
9503 return field->offset;
9507 mono_field_get_rva (MonoClassField *field)
9511 MonoClass *klass = field->parent;
9512 MonoFieldDefaultValue *def_values;
9514 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9516 def_values = mono_class_get_field_def_values (klass);
9518 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9520 mono_class_set_field_def_values (klass, def_values);
9523 field_index = mono_field_get_index (field);
9525 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9526 int first_field_idx = mono_class_get_first_field_idx (klass);
9527 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9529 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9530 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9533 return def_values [field_index].data;
9537 * mono_field_get_data:
9538 * \param field the \c MonoClassField to act on
9540 * \returns A pointer to the metadata constant value or to the field
9541 * data if it has an RVA flag.
9544 mono_field_get_data (MonoClassField *field)
9546 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9547 MonoTypeEnum def_type;
9549 return mono_class_get_field_default_value (field, &def_type);
9550 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9551 return mono_field_get_rva (field);
9558 * mono_property_get_name:
9559 * \param prop the \c MonoProperty to act on
9560 * \returns The name of the property
9563 mono_property_get_name (MonoProperty *prop)
9569 * mono_property_get_set_method
9570 * \param prop the \c MonoProperty to act on.
9571 * \returns The setter method of the property, a \c MonoMethod.
9574 mono_property_get_set_method (MonoProperty *prop)
9580 * mono_property_get_get_method
9581 * \param prop the MonoProperty to act on.
9582 * \returns The getter method of the property (A \c MonoMethod)
9585 mono_property_get_get_method (MonoProperty *prop)
9591 * mono_property_get_parent:
9592 * \param prop the \c MonoProperty to act on.
9593 * \returns The \c MonoClass where the property was defined.
9596 mono_property_get_parent (MonoProperty *prop)
9598 return prop->parent;
9602 * mono_property_get_flags:
9603 * \param prop the \c MonoProperty to act on.
9605 * The metadata flags for a property are encoded using the
9606 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9608 * \returns The flags for the property.
9611 mono_property_get_flags (MonoProperty *prop)
9617 * mono_event_get_name:
9618 * \param event the MonoEvent to act on
9619 * \returns The name of the event.
9622 mono_event_get_name (MonoEvent *event)
9628 * mono_event_get_add_method:
9629 * \param event The \c MonoEvent to act on.
9630 * \returns The \c add method for the event, a \c MonoMethod.
9633 mono_event_get_add_method (MonoEvent *event)
9639 * mono_event_get_remove_method:
9640 * \param event The \c MonoEvent to act on.
9641 * \returns The \c remove method for the event, a \c MonoMethod.
9644 mono_event_get_remove_method (MonoEvent *event)
9646 return event->remove;
9650 * mono_event_get_raise_method:
9651 * \param event The \c MonoEvent to act on.
9652 * \returns The \c raise method for the event, a \c MonoMethod.
9655 mono_event_get_raise_method (MonoEvent *event)
9657 return event->raise;
9661 * mono_event_get_parent:
9662 * \param event the MonoEvent to act on.
9663 * \returns The \c MonoClass where the event is defined.
9666 mono_event_get_parent (MonoEvent *event)
9668 return event->parent;
9672 * mono_event_get_flags
9673 * \param event the \c MonoEvent to act on.
9675 * The metadata flags for an event are encoded using the
9676 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9678 * \returns The flags for the event.
9681 mono_event_get_flags (MonoEvent *event)
9683 return event->attrs;
9687 * mono_class_get_method_from_name:
9688 * \param klass where to look for the method
9689 * \param name name of the method
9690 * \param param_count number of parameters. -1 for any number.
9692 * Obtains a \c MonoMethod with a given name and number of parameters.
9693 * It only works if there are no multiple signatures for any given method name.
9696 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9698 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9702 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9704 MonoMethod *res = NULL;
9707 /* Search directly in the metadata to avoid calling setup_methods () */
9708 int first_idx = mono_class_get_first_method_idx (klass);
9709 int mcount = mono_class_get_method_count (klass);
9710 for (i = 0; i < mcount; ++i) {
9712 guint32 cols [MONO_METHOD_SIZE];
9714 MonoMethodSignature *sig;
9716 /* first_idx points into the methodptr table */
9717 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9719 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9720 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9722 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9725 if (param_count == -1) {
9729 sig = mono_method_signature_checked (method, &error);
9731 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9734 if (sig->param_count == param_count) {
9745 * mono_class_get_method_from_name_flags:
9746 * \param klass where to look for the method
9747 * \param name_space name of the method
9748 * \param param_count number of parameters. -1 for any number.
9749 * \param flags flags which must be set in the method
9751 * Obtains a \c MonoMethod with a given name and number of parameters.
9752 * It only works if there are no multiple signatures for any given method name.
9755 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9757 MonoMethod *res = NULL;
9760 mono_class_init (klass);
9762 if (mono_class_is_ginst (klass) && !klass->methods) {
9763 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9766 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9767 if (!mono_error_ok (&error))
9768 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9773 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9774 mono_class_setup_methods (klass);
9776 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9777 See mono/tests/array_load_exception.il
9778 FIXME we should better report this error to the caller
9780 if (!klass->methods)
9782 int mcount = mono_class_get_method_count (klass);
9783 for (i = 0; i < mcount; ++i) {
9784 MonoMethod *method = klass->methods [i];
9786 if (method->name[0] == name [0] &&
9787 !strcmp (name, method->name) &&
9788 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9789 ((method->flags & flags) == flags)) {
9796 res = find_method_in_metadata (klass, name, param_count, flags);
9803 * mono_class_set_failure:
9804 * \param klass class in which the failure was detected
9805 * \param ex_type the kind of exception/error to be thrown (later)
9806 * \param ex_data exception data (specific to each type of exception/error)
9808 * Keep a detected failure informations in the class for later processing.
9809 * Note that only the first failure is kept.
9811 * LOCKING: Acquires the loader lock.
9814 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9816 g_assert (boxed_error != NULL);
9818 if (mono_class_has_failure (klass))
9821 mono_loader_lock ();
9822 klass->has_failure = 1;
9823 mono_class_set_exception_data (klass, boxed_error);
9824 mono_loader_unlock ();
9830 mono_class_has_failure (const MonoClass *klass)
9832 g_assert (klass != NULL);
9833 return klass->has_failure != 0;
9838 * mono_class_set_type_load_failure:
9839 * \param klass class in which the failure was detected
9840 * \param fmt \c printf -style error message string.
9842 * Collect detected failure informaion in the class for later processing.
9843 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9844 * Note that only the first failure is kept.
9846 * LOCKING: Acquires the loader lock.
9848 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9851 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9853 MonoError prepare_error;
9856 if (mono_class_has_failure (klass))
9859 error_init (&prepare_error);
9861 va_start (args, fmt);
9862 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9865 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9866 mono_error_cleanup (&prepare_error);
9867 return mono_class_set_failure (klass, box);
9871 * mono_classes_init:
9873 * Initialize the resources used by this module.
9876 mono_classes_init (void)
9878 mono_os_mutex_init (&classes_mutex);
9880 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9881 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9883 mono_counters_register ("MonoClassDef count",
9884 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9885 mono_counters_register ("MonoClassGtd count",
9886 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9887 mono_counters_register ("MonoClassGenericInst count",
9888 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9889 mono_counters_register ("MonoClassGenericParam count",
9890 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9891 mono_counters_register ("MonoClassArray count",
9892 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9893 mono_counters_register ("MonoClassPointer count",
9894 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9895 mono_counters_register ("Inflated methods size",
9896 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9897 mono_counters_register ("Inflated classes size",
9898 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9899 mono_counters_register ("MonoClass size",
9900 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9904 * mono_classes_cleanup:
9906 * Free the resources used by this module.
9909 mono_classes_cleanup (void)
9911 mono_native_tls_free (setup_fields_tls_id);
9912 mono_native_tls_free (init_pending_tls_id);
9914 if (global_interface_bitset)
9915 mono_bitset_free (global_interface_bitset);
9916 global_interface_bitset = NULL;
9917 mono_os_mutex_destroy (&classes_mutex);
9921 * mono_class_get_exception_for_failure:
9922 * \param klass class in which the failure was detected
9924 * \returns a constructed MonoException than the caller can then throw
9925 * using mono_raise_exception - or NULL if no failure is present (or
9926 * doesn't result in an exception).
9929 mono_class_get_exception_for_failure (MonoClass *klass)
9931 if (!mono_class_has_failure (klass))
9933 MonoError unboxed_error;
9934 error_init (&unboxed_error);
9935 mono_error_set_for_class_failure (&unboxed_error, klass);
9936 return mono_error_convert_to_exception (&unboxed_error);
9940 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9942 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9943 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9945 if (outer_klass == inner_klass)
9947 inner_klass = inner_klass->nested_in;
9948 } while (inner_klass);
9953 mono_class_get_generic_type_definition (MonoClass *klass)
9955 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9956 return gklass ? gklass->container_class : klass;
9960 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9962 * Generic instantiations are ignored for all super types of @klass.
9964 * Visibility checks ignoring generic instantiations.
9967 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9970 klass = mono_class_get_generic_type_definition (klass);
9971 parent = mono_class_get_generic_type_definition (parent);
9972 mono_class_setup_supertypes (klass);
9974 for (i = 0; i < klass->idepth; ++i) {
9975 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9981 * Subtype can only access parent members with family protection if the site object
9982 * is subclass of Subtype. For example:
9983 * class A { protected int x; }
9985 * void valid_access () {
9989 * void invalid_access () {
9996 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9998 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10001 if (context_klass == NULL)
10003 /*if access_klass is not member_klass context_klass must be type compat*/
10004 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10010 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10013 if (accessing == accessed)
10015 if (!accessed || !accessing)
10018 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10019 * anywhere so untrusted friends are not safe to access platform's code internals */
10020 if (mono_security_core_clr_enabled ()) {
10021 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10025 mono_assembly_load_friends (accessed);
10026 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10027 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10028 /* Be conservative with checks */
10029 if (!friend_->name)
10031 if (strcmp (accessing->aname.name, friend_->name))
10033 if (friend_->public_key_token [0]) {
10034 if (!accessing->aname.public_key_token [0])
10036 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10045 * If klass is a generic type or if it is derived from a generic type, return the
10046 * MonoClass of the generic definition
10047 * Returns NULL if not found
10050 get_generic_definition_class (MonoClass *klass)
10053 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10054 if (gklass && gklass->container_class)
10055 return gklass->container_class;
10056 klass = klass->parent;
10062 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10065 for (i = 0; i < ginst->type_argc; ++i) {
10066 MonoType *type = ginst->type_argv[i];
10067 switch (type->type) {
10068 case MONO_TYPE_SZARRAY:
10069 if (!can_access_type (access_klass, type->data.klass))
10072 case MONO_TYPE_ARRAY:
10073 if (!can_access_type (access_klass, type->data.array->eklass))
10076 case MONO_TYPE_PTR:
10077 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10080 case MONO_TYPE_CLASS:
10081 case MONO_TYPE_VALUETYPE:
10082 case MONO_TYPE_GENERICINST:
10083 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10093 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10097 if (access_klass == member_klass)
10100 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10103 if (access_klass->element_class && !access_klass->enumtype)
10104 access_klass = access_klass->element_class;
10106 if (member_klass->element_class && !member_klass->enumtype)
10107 member_klass = member_klass->element_class;
10109 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10111 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10114 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10117 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10120 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10123 /*Non nested type with nested visibility. We just fail it.*/
10124 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10127 switch (access_level) {
10128 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10129 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10131 case TYPE_ATTRIBUTE_PUBLIC:
10134 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10137 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10138 return is_nesting_type (member_klass, access_klass);
10140 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10141 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10143 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10144 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10146 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10147 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10148 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10150 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10151 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10152 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10157 /* FIXME: check visibility of type, too */
10159 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10161 MonoClass *member_generic_def;
10162 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10165 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10166 if (((access_gklass && access_gklass->container_class) ||
10167 mono_class_is_gtd (access_klass)) &&
10168 (member_generic_def = get_generic_definition_class (member_klass))) {
10169 MonoClass *access_container;
10171 if (mono_class_is_gtd (access_klass))
10172 access_container = access_klass;
10174 access_container = access_gklass->container_class;
10176 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10180 /* Partition I 8.5.3.2 */
10181 /* the access level values are the same for fields and methods */
10182 switch (access_level) {
10183 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10184 /* same compilation unit */
10185 return access_klass->image == member_klass->image;
10186 case FIELD_ATTRIBUTE_PRIVATE:
10187 return access_klass == member_klass;
10188 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10189 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10190 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10193 case FIELD_ATTRIBUTE_ASSEMBLY:
10194 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10195 case FIELD_ATTRIBUTE_FAMILY:
10196 if (is_valid_family_access (access_klass, member_klass, context_klass))
10199 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10200 if (is_valid_family_access (access_klass, member_klass, context_klass))
10202 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10203 case FIELD_ATTRIBUTE_PUBLIC:
10210 * mono_method_can_access_field:
10211 * \param method Method that will attempt to access the field
10212 * \param field the field to access
10214 * Used to determine if a method is allowed to access the specified field.
10216 * \returns TRUE if the given \p method is allowed to access the \p field while following
10217 * the accessibility rules of the CLI.
10220 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10222 /* FIXME: check all overlapping fields */
10223 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10225 MonoClass *nested = method->klass->nested_in;
10227 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10230 nested = nested->nested_in;
10237 * mono_method_can_access_method:
10238 * \param method Method that will attempt to access the other method
10239 * \param called the method that we want to probe for accessibility.
10241 * Used to determine if the \p method is allowed to access the specified \p called method.
10243 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10244 * the accessibility rules of the CLI.
10247 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10249 method = mono_method_get_method_definition (method);
10250 called = mono_method_get_method_definition (called);
10251 return mono_method_can_access_method_full (method, called, NULL);
10255 * mono_method_can_access_method_full:
10256 * @method: The caller method
10257 * @called: The called method
10258 * @context_klass: The static type on stack of the owner @called object used
10260 * This function must be used with instance calls, as they have more strict family accessibility.
10261 * It can be used with static methods, but context_klass should be NULL.
10263 * Returns: TRUE if caller have proper visibility and acessibility to @called
10266 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10268 /* Wrappers are except from access checks */
10269 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10272 MonoClass *access_class = method->klass;
10273 MonoClass *member_class = called->klass;
10274 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10276 MonoClass *nested = access_class->nested_in;
10278 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_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;
10302 if (called->is_inflated) {
10303 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10304 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10313 * mono_method_can_access_field_full:
10314 * @method: The caller method
10315 * @field: The accessed field
10316 * @context_klass: The static type on stack of the owner @field object used
10318 * This function must be used with instance fields, as they have more strict family accessibility.
10319 * It can be used with static fields, but context_klass should be NULL.
10321 * Returns: TRUE if caller have proper visibility and acessibility to @field
10324 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10326 MonoClass *access_class = method->klass;
10327 MonoClass *member_class = field->parent;
10328 /* FIXME: check all overlapping fields */
10329 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10331 MonoClass *nested = access_class->nested_in;
10333 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10336 nested = nested->nested_in;
10343 can = can_access_type (access_class, member_class);
10345 MonoClass *nested = access_class->nested_in;
10347 can = can_access_type (nested, member_class);
10350 nested = nested->nested_in;
10360 * mono_class_can_access_class:
10361 * @source_class: The source class
10362 * @target_class: The accessed class
10364 * This function returns is @target_class is visible to @source_class
10366 * Returns: TRUE if source have proper visibility and acessibility to target
10369 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10371 return can_access_type (source_class, target_class);
10375 * mono_type_is_valid_enum_basetype:
10376 * \param type The MonoType to check
10377 * \returns TRUE if the type can be used as the basetype of an enum
10379 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10380 switch (type->type) {
10383 case MONO_TYPE_BOOLEAN:
10386 case MONO_TYPE_CHAR:
10400 * mono_class_is_valid_enum:
10401 * \param klass An enum class to be validated
10403 * This method verify the required properties an enum should have.
10405 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10406 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10407 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10409 * \returns TRUE if the informed enum class is valid
10412 mono_class_is_valid_enum (MonoClass *klass)
10414 MonoClassField * field;
10415 gpointer iter = NULL;
10416 gboolean found_base_field = FALSE;
10418 g_assert (klass->enumtype);
10419 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10420 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10424 if (!mono_class_is_auto_layout (klass))
10427 while ((field = mono_class_get_fields (klass, &iter))) {
10428 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10429 if (found_base_field)
10431 found_base_field = TRUE;
10432 if (!mono_type_is_valid_enum_basetype (field->type))
10437 if (!found_base_field)
10440 if (mono_class_get_method_count (klass) > 0)
10447 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10449 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10453 * mono_class_setup_interface_id:
10455 * Initializes MonoClass::interface_id if required.
10457 * LOCKING: Acquires the loader lock.
10460 mono_class_setup_interface_id (MonoClass *klass)
10462 mono_loader_lock ();
10463 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10464 klass->interface_id = mono_get_unique_iid (klass);
10465 mono_loader_unlock ();
10469 * mono_class_setup_interfaces:
10471 * Initialize klass->interfaces/interfaces_count.
10472 * LOCKING: Acquires the loader lock.
10473 * This function can fail the type.
10476 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10478 int i, interface_count;
10479 MonoClass **interfaces;
10481 error_init (error);
10483 if (klass->interfaces_inited)
10486 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10487 MonoType *args [1];
10489 /* generic IList, ICollection, IEnumerable */
10490 interface_count = 2;
10491 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10493 args [0] = &klass->element_class->byval_arg;
10494 interfaces [0] = mono_class_bind_generic_parameters (
10495 mono_defaults.generic_ilist_class, 1, args, FALSE);
10496 interfaces [1] = mono_class_bind_generic_parameters (
10497 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10498 } else if (mono_class_is_ginst (klass)) {
10499 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10501 mono_class_setup_interfaces (gklass, error);
10502 if (!mono_error_ok (error)) {
10503 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10507 interface_count = gklass->interface_count;
10508 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10509 for (i = 0; i < interface_count; i++) {
10510 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10511 if (!mono_error_ok (error)) {
10512 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10517 interface_count = 0;
10521 mono_loader_lock ();
10522 if (!klass->interfaces_inited) {
10523 klass->interface_count = interface_count;
10524 klass->interfaces = interfaces;
10526 mono_memory_barrier ();
10528 klass->interfaces_inited = TRUE;
10530 mono_loader_unlock ();
10534 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10536 MonoClass *klass = field->parent;
10537 MonoImage *image = klass->image;
10538 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10540 int field_idx = field - klass->fields;
10542 error_init (error);
10545 MonoClassField *gfield = >d->fields [field_idx];
10546 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10547 if (!mono_error_ok (error)) {
10548 char *full_name = mono_type_get_full_name (gtd);
10549 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));
10550 g_free (full_name);
10553 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10554 if (!mono_error_ok (error)) {
10555 char *full_name = mono_type_get_full_name (klass);
10556 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));
10557 g_free (full_name);
10561 guint32 cols [MONO_FIELD_SIZE];
10562 MonoGenericContainer *container = NULL;
10563 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10565 /*FIXME, in theory we do not lazy load SRE fields*/
10566 g_assert (!image_is_dynamic (image));
10568 if (mono_class_is_gtd (klass)) {
10569 container = mono_class_get_generic_container (klass);
10571 container = mono_class_get_generic_container (gtd);
10572 g_assert (container);
10575 /* first_field_idx and idx points into the fieldptr table */
10576 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10578 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10579 char *full_name = mono_type_get_full_name (klass);
10580 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10581 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10582 g_free (full_name);
10586 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10588 mono_metadata_decode_value (sig, &sig);
10589 /* FIELD signature == 0x06 */
10590 g_assert (*sig == 0x06);
10592 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10594 char *full_name = mono_type_get_full_name (klass);
10595 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));
10596 g_free (full_name);
10599 mono_memory_barrier ();
10600 field->type = ftype;
10604 mono_field_resolve_flags (MonoClassField *field)
10606 MonoClass *klass = field->parent;
10607 MonoImage *image = klass->image;
10608 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10609 int field_idx = field - klass->fields;
10612 MonoClassField *gfield = >d->fields [field_idx];
10613 return mono_field_get_flags (gfield);
10615 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10617 /*FIXME, in theory we do not lazy load SRE fields*/
10618 g_assert (!image_is_dynamic (image));
10620 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10625 * mono_class_get_fields_lazy:
10626 * \param klass the MonoClass to act on
10628 * This routine is an iterator routine for retrieving the fields in a class.
10629 * Only minimal information about fields are loaded. Accessors must be used
10630 * for all MonoClassField returned.
10632 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10633 * iterate over all of the elements. When no more values are
10634 * available, the return value is NULL.
10636 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10639 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10641 MonoClassField* field;
10645 mono_class_setup_basic_field_info (klass);
10646 if (!klass->fields)
10648 /* start from the first */
10649 if (mono_class_get_field_count (klass)) {
10650 *iter = &klass->fields [0];
10651 return (MonoClassField *)*iter;
10657 field = (MonoClassField *)*iter;
10659 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10661 return (MonoClassField *)*iter;
10667 mono_class_full_name (MonoClass *klass)
10669 return mono_type_full_name (&klass->byval_arg);
10672 /* Declare all shared lazy type lookup functions */
10673 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10676 * mono_method_get_base_method:
10677 * \param method a method
10678 * \param definition if true, get the definition
10679 * \param error set on failure
10681 * Given a virtual method associated with a subclass, return the corresponding
10682 * method from an ancestor. If \p definition is FALSE, returns the method in the
10683 * superclass of the given method. If \p definition is TRUE, return the method
10684 * in the ancestor class where it was first declared. The type arguments will
10685 * be inflated in the ancestor classes. If the method is not associated with a
10686 * class, or isn't virtual, returns the method itself. On failure returns NULL
10687 * and sets \p error.
10690 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10692 MonoClass *klass, *parent;
10693 MonoGenericContext *generic_inst = NULL;
10694 MonoMethod *result = NULL;
10697 if (method->klass == NULL)
10700 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10701 MONO_CLASS_IS_INTERFACE (method->klass) ||
10702 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10705 slot = mono_method_get_vtable_slot (method);
10709 klass = method->klass;
10710 if (mono_class_is_ginst (klass)) {
10711 generic_inst = mono_class_get_context (klass);
10712 klass = mono_class_get_generic_class (klass)->container_class;
10717 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10718 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10719 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10720 or klass is the generic container class and generic_inst is the instantiation.
10722 when we go to the parent, if the parent is an open constructed type, we need to
10723 replace the type parameters by the definitions from the generic_inst, and then take it
10724 apart again into the klass and the generic_inst.
10726 For cases like this:
10727 class C<T> : B<T, int> {
10728 public override void Foo () { ... }
10730 class B<U,V> : A<HashMap<U,V>> {
10731 public override void Foo () { ... }
10734 public virtual void Foo () { ... }
10737 if at each iteration the parent isn't open, we can skip inflating it. if at some
10738 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10741 MonoGenericContext *parent_inst = NULL;
10742 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10743 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10744 return_val_if_nok (error, NULL);
10746 if (mono_class_is_ginst (parent)) {
10747 parent_inst = mono_class_get_context (parent);
10748 parent = mono_class_get_generic_class (parent)->container_class;
10751 mono_class_setup_vtable (parent);
10752 if (parent->vtable_size <= slot)
10755 generic_inst = parent_inst;
10758 klass = klass->parent;
10761 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10762 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10763 return_val_if_nok (error, NULL);
10765 generic_inst = NULL;
10767 if (mono_class_is_ginst (klass)) {
10768 generic_inst = mono_class_get_context (klass);
10769 klass = mono_class_get_generic_class (klass)->container_class;
10774 if (generic_inst) {
10775 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10776 return_val_if_nok (error, NULL);
10779 if (klass == method->klass)
10782 /*This is possible if definition == FALSE.
10783 * Do it here to be really sure we don't read invalid memory.
10785 if (slot >= klass->vtable_size)
10788 mono_class_setup_vtable (klass);
10790 result = klass->vtable [slot];
10791 if (result == NULL) {
10792 /* It is an abstract method */
10793 gboolean found = FALSE;
10794 gpointer iter = NULL;
10795 while ((result = mono_class_get_methods (klass, &iter))) {
10796 if (result->slot == slot) {
10801 /* found might be FALSE if we looked in an abstract class
10802 * that doesn't override an abstract method of its
10804 * abstract class Base {
10805 * public abstract void Foo ();
10807 * abstract class Derived : Base { }
10808 * class Child : Derived {
10809 * public override void Foo () { }
10812 * if m was Child.Foo and we ask for the base method,
10813 * then we get here with klass == Derived and found == FALSE
10815 /* but it shouldn't be the case that if we're looking
10816 * for the definition and didn't find a result; the
10817 * loop above should've taken us as far as we could
10819 g_assert (!(definition && !found));
10824 g_assert (result != NULL);