3 * Class management for the Mono runtime
6 * Miguel de Icaza (miguel@ximian.com)
8 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
9 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
11 * Licensed under the MIT license. See LICENSE file in the project root for full license information.
21 #include <mono/metadata/image.h>
22 #include <mono/metadata/image-internals.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/assembly-internals.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/profiler-private.h>
28 #include <mono/metadata/tabledefs.h>
29 #include <mono/metadata/tokentype.h>
30 #include <mono/metadata/class-internals.h>
31 #include <mono/metadata/object.h>
32 #include <mono/metadata/appdomain.h>
33 #include <mono/metadata/mono-endian.h>
34 #include <mono/metadata/debug-helpers.h>
35 #include <mono/metadata/reflection.h>
36 #include <mono/metadata/exception.h>
37 #include <mono/metadata/security-manager.h>
38 #include <mono/metadata/security-core-clr.h>
39 #include <mono/metadata/attrdefs.h>
40 #include <mono/metadata/gc-internals.h>
41 #include <mono/metadata/verify-internals.h>
42 #include <mono/metadata/mono-debug.h>
43 #include <mono/utils/mono-counters.h>
44 #include <mono/utils/mono-string.h>
45 #include <mono/utils/mono-error-internals.h>
46 #include <mono/utils/mono-logger-internals.h>
47 #include <mono/utils/mono-memory-model.h>
48 #include <mono/utils/atomic.h>
49 #include <mono/utils/bsearch.h>
50 #include <mono/utils/checked-build.h>
54 gboolean mono_print_vtable = FALSE;
55 gboolean mono_align_small_structs = FALSE;
58 guint32 inflated_classes_size, inflated_methods_size;
59 guint32 classes_size, class_ext_size, class_ext_count;
60 guint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
62 /* Low level lock which protects data structures in this module */
63 static mono_mutex_t classes_mutex;
65 /* Function supplied by the runtime to find classes by name using information from the AOT file */
66 static MonoGetClassFromName get_class_from_name = NULL;
68 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
69 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
70 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
71 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
72 static int generic_array_methods (MonoClass *klass);
73 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
75 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
76 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
77 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
78 static guint32 mono_field_resolve_flags (MonoClassField *field);
79 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
80 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
82 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
86 We use gclass recording to allow recursive system f types to be referenced by a parent.
88 Given the following type hierarchy:
90 class TextBox : TextBoxBase<TextBox> {}
91 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
92 class TextInput<T> : Input<T> where T: TextInput<T> {}
95 The runtime tries to load TextBoxBase<>.
96 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
97 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
98 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
100 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
101 at this point, iow, both are registered in the type map and both and a NULL parent. This means
102 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
104 To fix that what we do is to record all generic instantes created while resolving the parent of
105 any generic type definition and, after resolved, correct the parent field if needed.
108 static int record_gclass_instantiation;
109 static GSList *gclass_recorded_list;
110 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
112 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
113 static MonoNativeTlsKey setup_fields_tls_id;
115 static MonoNativeTlsKey init_pending_tls_id;
120 mono_locks_os_acquire (&classes_mutex, ClassesLock);
124 classes_unlock (void)
126 mono_locks_os_release (&classes_mutex, ClassesLock);
130 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
133 enable_gclass_recording (void)
135 ++record_gclass_instantiation;
139 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
142 disable_gclass_recording (gclass_record_func func, void *user_data)
144 GSList **head = &gclass_recorded_list;
146 g_assert (record_gclass_instantiation > 0);
147 --record_gclass_instantiation;
150 GSList *node = *head;
151 if (func ((MonoClass*)node->data, user_data)) {
153 g_slist_free_1 (node);
159 /* We automatically discard all recorded gclasses when disabled. */
160 if (!record_gclass_instantiation && gclass_recorded_list) {
161 g_slist_free (gclass_recorded_list);
162 gclass_recorded_list = NULL;
167 * mono_class_from_typeref:
168 * \param image a MonoImage
169 * \param type_token a TypeRef token
171 * Creates the \c MonoClass* structure representing the type defined by
172 * the typeref token valid inside \p image.
173 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
177 mono_class_from_typeref (MonoImage *image, guint32 type_token)
180 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
181 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
186 * mono_class_from_typeref_checked:
187 * \param image a MonoImage
188 * \param type_token a TypeRef token
189 * \param error error return code, if any.
191 * Creates the \c MonoClass* structure representing the type defined by
192 * the typeref token valid inside \p image.
194 * \returns The \c MonoClass* representing the typeref token, NULL if it could
195 * not be loaded with the \p error value filled with the information about the
199 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
201 guint32 cols [MONO_TYPEREF_SIZE];
202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
204 const char *name, *nspace;
205 MonoClass *res = NULL;
210 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
213 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
218 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
219 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
220 case MONO_RESOLUTION_SCOPE_MODULE:
222 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
223 This is not the observed behavior of existing implementations.
224 The defacto behavior is that it's just a typedef in disguise.
226 /* a typedef in disguise */
227 res = mono_class_from_name_checked (image, nspace, name, error);
230 case MONO_RESOLUTION_SCOPE_MODULEREF:
231 module = mono_image_load_module_checked (image, idx, error);
233 res = mono_class_from_name_checked (module, nspace, name, error);
236 case MONO_RESOLUTION_SCOPE_TYPEREF: {
237 MonoClass *enclosing;
240 if (idx == mono_metadata_token_index (type_token)) {
241 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
245 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
246 return_val_if_nok (error, NULL);
248 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
249 if (enclosing->nested_classes_inited && nested_classes) {
250 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
251 for (tmp = nested_classes; tmp; tmp = tmp->next) {
252 res = (MonoClass *)tmp->data;
253 if (strcmp (res->name, name) == 0)
257 /* Don't call mono_class_init as we might've been called by it recursively */
258 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
260 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
261 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
262 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
264 if (strcmp (nname, name) == 0)
265 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
267 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
270 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
273 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
277 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
278 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
282 if (!image->references || !image->references [idx - 1])
283 mono_assembly_load_reference (image, idx - 1);
284 g_assert (image->references [idx - 1]);
286 /* If the assembly did not load, register this as a type load exception */
287 if (image->references [idx - 1] == REFERENCE_MISSING){
288 MonoAssemblyName aname;
291 mono_assembly_get_assemblyref (image, idx - 1, &aname);
292 human_name = mono_stringify_assembly_name (&aname);
293 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
297 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
300 /* Generic case, should be avoided for when a better error is possible. */
301 if (!res && mono_error_ok (error)) {
302 char *name = mono_class_name_from_token (image, type_token);
303 char *assembly = mono_assembly_name_from_token (image, type_token);
304 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (from typeref, class/assembly %s, %s)", type_token, name, assembly);
311 mono_image_memdup (MonoImage *image, void *data, guint size)
313 void *res = mono_image_alloc (image, size);
314 memcpy (res, data, size);
318 /* Copy everything mono_metadata_free_array free. */
320 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
323 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
325 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
327 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
329 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
331 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
333 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
338 /* Copy everything mono_metadata_free_method_signature free. */
340 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
344 sig = mono_metadata_signature_dup_full (image, sig);
346 sig->ret = mono_metadata_type_dup (image, sig->ret);
347 for (i = 0; i < sig->param_count; ++i)
348 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
354 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
356 MonoAssembly *ta = klass->image->assembly;
359 name = mono_stringify_assembly_name (&ta->aname);
360 g_string_append_printf (str, ", %s", name);
365 mono_type_name_check_byref (MonoType *type, GString *str)
368 g_string_append_c (str, '&');
372 * mono_identifier_escape_type_name_chars:
373 * \param str a destination string
374 * \param identifier an IDENTIFIER in internal form
378 * The displayed form of the identifier is appended to str.
380 * The displayed form of an identifier has the characters ,+&*[]\
381 * that have special meaning in type names escaped with a preceeding
382 * backslash (\) character.
385 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
391 // reserve space for common case: there will be no escaped characters.
392 g_string_set_size(str, n + strlen(identifier));
393 g_string_set_size(str, n);
395 for (const char* s = identifier; *s != 0 ; s++) {
404 g_string_append_c (str, '\\');
405 g_string_append_c (str, *s);
408 g_string_append_c (str, *s);
416 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
417 MonoTypeNameFormat format)
421 switch (type->type) {
422 case MONO_TYPE_ARRAY: {
423 int i, rank = type->data.array->rank;
424 MonoTypeNameFormat nested_format;
426 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
427 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
429 mono_type_get_name_recurse (
430 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
431 g_string_append_c (str, '[');
433 g_string_append_c (str, '*');
434 for (i = 1; i < rank; i++)
435 g_string_append_c (str, ',');
436 g_string_append_c (str, ']');
438 mono_type_name_check_byref (type, str);
440 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
441 _mono_type_get_assembly_name (type->data.array->eklass, str);
444 case MONO_TYPE_SZARRAY: {
445 MonoTypeNameFormat nested_format;
447 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
448 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
450 mono_type_get_name_recurse (
451 &type->data.klass->byval_arg, str, FALSE, nested_format);
452 g_string_append (str, "[]");
454 mono_type_name_check_byref (type, str);
456 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
457 _mono_type_get_assembly_name (type->data.klass, str);
460 case MONO_TYPE_PTR: {
461 MonoTypeNameFormat nested_format;
463 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
464 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
466 mono_type_get_name_recurse (
467 type->data.type, str, FALSE, nested_format);
468 g_string_append_c (str, '*');
470 mono_type_name_check_byref (type, str);
472 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
473 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
478 if (!mono_generic_param_info (type->data.generic_param))
479 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
481 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
483 mono_type_name_check_byref (type, str);
487 klass = mono_class_from_mono_type (type);
488 if (klass->nested_in) {
489 mono_type_get_name_recurse (
490 &klass->nested_in->byval_arg, str, TRUE, format);
491 if (format == MONO_TYPE_NAME_FORMAT_IL)
492 g_string_append_c (str, '.');
494 g_string_append_c (str, '+');
495 } else if (*klass->name_space) {
496 if (format == MONO_TYPE_NAME_FORMAT_IL)
497 g_string_append (str, klass->name_space);
499 mono_identifier_escape_type_name_chars (str, klass->name_space);
500 g_string_append_c (str, '.');
502 if (format == MONO_TYPE_NAME_FORMAT_IL) {
503 char *s = strchr (klass->name, '`');
504 int len = s ? s - klass->name : strlen (klass->name);
505 g_string_append_len (str, klass->name, len);
507 mono_identifier_escape_type_name_chars (str, klass->name);
511 if (mono_class_is_ginst (klass)) {
512 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
513 MonoGenericInst *inst = gclass->context.class_inst;
514 MonoTypeNameFormat nested_format;
517 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
518 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
520 if (format == MONO_TYPE_NAME_FORMAT_IL)
521 g_string_append_c (str, '<');
523 g_string_append_c (str, '[');
524 for (i = 0; i < inst->type_argc; i++) {
525 MonoType *t = inst->type_argv [i];
528 g_string_append_c (str, ',');
529 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
530 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
531 g_string_append_c (str, '[');
532 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
533 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
534 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
535 g_string_append_c (str, ']');
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '>');
540 g_string_append_c (str, ']');
541 } else if (mono_class_is_gtd (klass) &&
542 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
543 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '<');
549 g_string_append_c (str, '[');
550 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
552 g_string_append_c (str, ',');
553 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
555 if (format == MONO_TYPE_NAME_FORMAT_IL)
556 g_string_append_c (str, '>');
558 g_string_append_c (str, ']');
561 mono_type_name_check_byref (type, str);
563 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
564 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
565 _mono_type_get_assembly_name (klass, str);
571 * mono_type_get_name_full:
573 * \param format the format for the return string.
576 * \returns The string representation in a number of formats:
578 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
579 * returned in the format required by \c System.Reflection, this is the
580 * inverse of mono_reflection_parse_type().
582 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
583 * be used by the IL assembler.
585 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
587 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
590 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
594 result = g_string_new ("");
596 mono_type_get_name_recurse (type, result, FALSE, format);
598 return g_string_free (result, FALSE);
602 * mono_type_get_full_name:
603 * \param class a class
605 * \returns The string representation for type as required by System.Reflection.
606 * The inverse of mono_reflection_parse_type().
609 mono_type_get_full_name (MonoClass *klass)
611 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
615 * mono_type_get_name:
617 * \returns The string representation for type as it would be represented in IL code.
620 mono_type_get_name (MonoType *type)
622 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
626 * mono_type_get_underlying_type:
628 * \returns The \c MonoType for the underlying integer type if \p type
629 * is an enum and byref is false, otherwise the type itself.
632 mono_type_get_underlying_type (MonoType *type)
634 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
635 return mono_class_enum_basetype (type->data.klass);
636 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.generic_class->container_class);
642 * mono_class_is_open_constructed_type:
645 * \returns TRUE if type represents a generics open constructed type.
646 * IOW, not all type parameters required for the instantiation have
647 * been provided or it's a generic type definition.
649 * An open constructed type means it's a non realizable type. Not to
650 * be mixed up with an abstract type - we can't cast or dispatch to
651 * an open type, for example.
654 mono_class_is_open_constructed_type (MonoType *t)
660 case MONO_TYPE_SZARRAY:
661 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
662 case MONO_TYPE_ARRAY:
663 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
665 return mono_class_is_open_constructed_type (t->data.type);
666 case MONO_TYPE_GENERICINST:
667 return t->data.generic_class->context.class_inst->is_open;
668 case MONO_TYPE_CLASS:
669 case MONO_TYPE_VALUETYPE:
670 return mono_class_is_gtd (t->data.klass);
677 This is a simple function to catch the most common bad instances of generic types.
678 Specially those that might lead to further failures in the runtime.
681 is_valid_generic_argument (MonoType *type)
683 switch (type->type) {
685 //case MONO_TYPE_TYPEDBYREF:
693 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
697 switch (type->type) {
698 case MONO_TYPE_MVAR: {
700 int num = mono_type_get_generic_param_num (type);
701 MonoGenericInst *inst = context->method_inst;
704 if (num >= inst->type_argc) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
707 num, info ? info->name : "", inst->type_argc);
711 if (!is_valid_generic_argument (inst->type_argv [num])) {
712 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
713 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
714 num, info ? info->name : "", inst->type_argv [num]->type);
718 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
719 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
720 * ->byref and ->attrs from @type are propagated to the returned type.
722 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
723 nt->byref = type->byref;
724 nt->attrs = type->attrs;
727 case MONO_TYPE_VAR: {
729 int num = mono_type_get_generic_param_num (type);
730 MonoGenericInst *inst = context->class_inst;
733 if (num >= inst->type_argc) {
734 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
735 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
736 num, info ? info->name : "", inst->type_argc);
739 if (!is_valid_generic_argument (inst->type_argv [num])) {
740 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
741 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
742 num, info ? info->name : "", inst->type_argv [num]->type);
745 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
746 nt->byref = type->byref;
747 nt->attrs = type->attrs;
750 case MONO_TYPE_SZARRAY: {
751 MonoClass *eclass = type->data.klass;
752 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
753 if (!inflated || !mono_error_ok (error))
755 nt = mono_metadata_type_dup (image, type);
756 nt->data.klass = mono_class_from_mono_type (inflated);
757 mono_metadata_free_type (inflated);
760 case MONO_TYPE_ARRAY: {
761 MonoClass *eclass = type->data.array->eklass;
762 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
763 if (!inflated || !mono_error_ok (error))
765 nt = mono_metadata_type_dup (image, type);
766 nt->data.array->eklass = mono_class_from_mono_type (inflated);
767 mono_metadata_free_type (inflated);
770 case MONO_TYPE_GENERICINST: {
771 MonoGenericClass *gclass = type->data.generic_class;
772 MonoGenericInst *inst;
774 if (!gclass->context.class_inst->is_open)
777 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
778 return_val_if_nok (error, NULL);
780 if (inst != gclass->context.class_inst)
781 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
783 if (gclass == type->data.generic_class)
786 nt = mono_metadata_type_dup (image, type);
787 nt->data.generic_class = gclass;
790 case MONO_TYPE_CLASS:
791 case MONO_TYPE_VALUETYPE: {
792 MonoClass *klass = type->data.klass;
793 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
794 MonoGenericInst *inst;
795 MonoGenericClass *gclass = NULL;
801 /* We can't use context->class_inst directly, since it can have more elements */
802 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
803 return_val_if_nok (error, NULL);
805 if (inst == container->context.class_inst)
808 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
810 nt = mono_metadata_type_dup (image, type);
811 nt->type = MONO_TYPE_GENERICINST;
812 nt->data.generic_class = gclass;
822 mono_generic_class_get_context (MonoGenericClass *gclass)
824 return &gclass->context;
828 mono_class_get_context (MonoClass *klass)
830 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
831 return gklass ? mono_generic_class_get_context (gklass) : NULL;
835 * mono_class_inflate_generic_type_with_mempool:
836 * @mempool: a mempool
838 * @context: a generics context
839 * @error: error context
841 * The same as mono_class_inflate_generic_type, but allocates the MonoType
842 * from mempool if it is non-NULL. If it is NULL, the MonoType is
843 * allocated on the heap and is owned by the caller.
844 * The returned type can potentially be the same as TYPE, so it should not be
845 * modified by the caller, and it should be freed using mono_metadata_free_type ().
848 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
850 MonoType *inflated = NULL;
854 inflated = inflate_generic_type (image, type, context, error);
855 return_val_if_nok (error, NULL);
858 MonoType *shared = mono_metadata_get_shared_type (type);
863 return mono_metadata_type_dup (image, type);
867 mono_stats.inflated_type_count++;
872 * mono_class_inflate_generic_type:
874 * \param context a generics context
875 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
877 * If \p type is a generic type and \p context is not NULL, instantiate it using the
878 * generics context \p context.
880 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
881 * on the heap and is owned by the caller. Returns NULL on error.
884 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
888 result = mono_class_inflate_generic_type_checked (type, context, &error);
889 mono_error_cleanup (&error);
894 * mono_class_inflate_generic_type:
896 * @context: a generics context
897 * @error: error context to use
899 * If @type is a generic type and @context is not NULL, instantiate it using the
900 * generics context @context.
902 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
903 * on the heap and is owned by the caller.
906 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
908 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
912 * mono_class_inflate_generic_type_no_copy:
914 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
918 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
920 MonoType *inflated = NULL;
924 inflated = inflate_generic_type (image, type, context, error);
925 return_val_if_nok (error, NULL);
931 mono_stats.inflated_type_count++;
936 * mono_class_inflate_generic_class:
938 * Inflate the class @gklass with @context. Set @error on failure.
941 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
946 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
947 return_val_if_nok (error, NULL);
949 res = mono_class_from_mono_type (inflated);
950 mono_metadata_free_type (inflated);
955 static MonoGenericContext
956 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
958 MonoGenericInst *class_inst = NULL;
959 MonoGenericInst *method_inst = NULL;
960 MonoGenericContext res = { NULL, NULL };
964 if (context->class_inst) {
965 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
966 if (!mono_error_ok (error))
970 if (context->method_inst) {
971 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
972 if (!mono_error_ok (error))
976 res.class_inst = class_inst;
977 res.method_inst = method_inst;
983 * mono_class_inflate_generic_method:
984 * \param method a generic method
985 * \param context a generics context
987 * Instantiate the generic method \p method using the generics context \p context.
989 * \returns The new instantiated method
992 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
994 return mono_class_inflate_generic_method_full (method, NULL, context);
998 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1000 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1004 * mono_class_inflate_generic_method_full:
1006 * Instantiate method \p method with the generic context \p context.
1007 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1008 * Use mono_method_signature() and mono_method_get_header() to get the correct values.
1011 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1014 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1015 if (!mono_error_ok (&error))
1016 /*FIXME do proper error handling - on this case, kill this function. */
1017 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1023 * mono_class_inflate_generic_method_full_checked:
1024 * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1027 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1030 MonoMethodInflated *iresult, *cached;
1031 MonoMethodSignature *sig;
1032 MonoGenericContext tmp_context;
1036 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1037 while (method->is_inflated) {
1038 MonoGenericContext *method_context = mono_method_get_context (method);
1039 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1041 tmp_context = inflate_generic_context (method_context, context, error);
1042 return_val_if_nok (error, NULL);
1044 context = &tmp_context;
1046 if (mono_metadata_generic_context_equal (method_context, context))
1049 method = imethod->declaring;
1053 * A method only needs to be inflated if the context has argument for which it is
1056 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1057 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1060 if (!((method->is_generic && context->method_inst) ||
1061 (mono_class_is_gtd (method->klass) && context->class_inst)))
1064 iresult = g_new0 (MonoMethodInflated, 1);
1065 iresult->context = *context;
1066 iresult->declaring = method;
1068 if (!context->method_inst && method->is_generic)
1069 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1071 if (!context->class_inst) {
1072 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1073 if (mono_class_is_gtd (iresult->declaring->klass))
1074 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1076 /* This can happen with some callers like mono_object_get_virtual_method () */
1077 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1078 iresult->context.class_inst = NULL;
1080 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1083 mono_image_set_lock (set);
1084 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1085 mono_image_set_unlock (set);
1089 return (MonoMethod*)cached;
1092 mono_stats.inflated_method_count++;
1094 inflated_methods_size += sizeof (MonoMethodInflated);
1096 sig = mono_method_signature (method);
1098 char *name = mono_type_get_full_name (method->klass);
1099 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1105 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1107 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1110 result = (MonoMethod *) iresult;
1111 result->is_inflated = TRUE;
1112 result->is_generic = FALSE;
1113 result->sre_method = FALSE;
1114 result->signature = NULL;
1116 if (method->wrapper_type) {
1117 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1118 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1119 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1121 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1122 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1125 if (iresult->context.method_inst) {
1126 /* Set the generic_container of the result to the generic_container of method */
1127 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1129 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1130 result->is_generic = 1;
1131 mono_method_set_generic_container (result, generic_container);
1136 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1137 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1141 if (mono_class_is_gtd (method->klass))
1142 result->klass = klass_hint;
1144 if (!result->klass) {
1145 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1146 if (!mono_error_ok (error))
1149 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1151 mono_metadata_free_type (inflated);
1155 * FIXME: This should hold, but it doesn't:
1157 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1158 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1159 * g_assert (result->is_generic);
1162 * Fixing this here causes other things to break, hence a very
1163 * ugly hack in mini-trampolines.c - see
1164 * is_generic_method_definition().
1168 mono_image_set_lock (set);
1169 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1171 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1172 iresult->owner = set;
1175 mono_image_set_unlock (set);
1177 return (MonoMethod*)cached;
1185 * mono_get_inflated_method:
1187 * Obsolete. We keep it around since it's mentioned in the public API.
1190 mono_get_inflated_method (MonoMethod *method)
1196 * mono_method_get_context_general:
1198 * @uninflated: handle uninflated methods?
1200 * Returns the generic context of a method or NULL if it doesn't have
1201 * one. For an inflated method that's the context stored in the
1202 * method. Otherwise it's in the method's generic container or in the
1203 * generic container of the method's class.
1206 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1208 if (method->is_inflated) {
1209 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1210 return &imethod->context;
1214 if (method->is_generic)
1215 return &(mono_method_get_generic_container (method)->context);
1216 if (mono_class_is_gtd (method->klass))
1217 return &mono_class_get_generic_container (method->klass)->context;
1222 * mono_method_get_context:
1225 * Returns the generic context for method if it's inflated, otherwise
1229 mono_method_get_context (MonoMethod *method)
1231 return mono_method_get_context_general (method, FALSE);
1235 * mono_method_get_generic_container:
1237 * Returns the generic container of METHOD, which should be a generic method definition.
1238 * Returns NULL if METHOD is not a generic method definition.
1239 * LOCKING: Acquires the loader lock.
1241 MonoGenericContainer*
1242 mono_method_get_generic_container (MonoMethod *method)
1244 MonoGenericContainer *container;
1246 if (!method->is_generic)
1249 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1250 g_assert (container);
1256 * mono_method_set_generic_container:
1258 * Sets the generic container of METHOD to CONTAINER.
1259 * LOCKING: Acquires the image lock.
1262 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1264 g_assert (method->is_generic);
1266 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1270 * mono_class_find_enum_basetype:
1271 * \param class The enum class
1273 * Determine the basetype of an enum by iterating through its fields. We do this
1274 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1277 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1279 MonoGenericContainer *container = NULL;
1280 MonoImage *m = klass->image;
1281 const int top = mono_class_get_field_count (klass);
1282 int i, first_field_idx;
1284 g_assert (klass->enumtype);
1288 container = mono_class_try_get_generic_container (klass);
1289 if (mono_class_is_ginst (klass)) {
1290 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1292 container = mono_class_get_generic_container (gklass);
1293 g_assert (container);
1297 * Fetch all the field information.
1299 first_field_idx = mono_class_get_first_field_idx (klass);
1300 for (i = 0; i < top; i++){
1302 guint32 cols [MONO_FIELD_SIZE];
1303 int idx = first_field_idx + i;
1306 /* first_field_idx and idx points into the fieldptr table */
1307 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1309 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1312 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1313 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1317 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1318 mono_metadata_decode_value (sig, &sig);
1319 /* FIELD signature == 0x06 */
1321 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1325 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1329 if (mono_class_is_ginst (klass)) {
1330 //FIXME do we leak here?
1331 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1332 if (!mono_error_ok (error))
1334 ftype->attrs = cols [MONO_FIELD_FLAGS];
1339 mono_error_set_type_load_class (error, klass, "Could not find base type");
1346 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1349 mono_type_has_exceptions (MonoType *type)
1351 switch (type->type) {
1352 case MONO_TYPE_CLASS:
1353 case MONO_TYPE_VALUETYPE:
1354 case MONO_TYPE_SZARRAY:
1355 return mono_class_has_failure (type->data.klass);
1356 case MONO_TYPE_ARRAY:
1357 return mono_class_has_failure (type->data.array->eklass);
1358 case MONO_TYPE_GENERICINST:
1359 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1366 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1368 g_assert (mono_class_has_failure (klass));
1369 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1370 mono_error_set_from_boxed (oerror, box);
1376 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1380 mono_class_alloc (MonoClass *klass, int size)
1382 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1384 return mono_image_set_alloc (gklass->owner, size);
1386 return mono_image_alloc (klass->image, size);
1390 mono_class_alloc0 (MonoClass *klass, int size)
1394 res = mono_class_alloc (klass, size);
1395 memset (res, 0, size);
1399 #define mono_class_new0(klass,struct_type, n_structs) \
1400 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1403 * mono_class_setup_basic_field_info:
1404 * \param class The class to initialize
1406 * Initializes the following fields in MonoClass:
1407 * * klass->fields (only field->parent and field->name)
1408 * * klass->field.count
1409 * * klass->first_field_idx
1410 * LOCKING: Acquires the loader lock
1413 mono_class_setup_basic_field_info (MonoClass *klass)
1415 MonoGenericClass *gklass;
1416 MonoClassField *field;
1417 MonoClassField *fields;
1425 gklass = mono_class_try_get_generic_class (klass);
1426 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1427 image = klass->image;
1430 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1432 * This happens when a generic instance of an unfinished generic typebuilder
1433 * is used as an element type for creating an array type. We can't initialize
1434 * the fields of this class using the fields of gklass, since gklass is not
1435 * finished yet, fields could be added to it later.
1441 mono_class_setup_basic_field_info (gtd);
1443 mono_loader_lock ();
1444 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1445 mono_loader_unlock ();
1448 top = mono_class_get_field_count (klass);
1450 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1453 * Fetch all the field information.
1455 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1456 for (i = 0; i < top; i++) {
1457 field = &fields [i];
1458 field->parent = klass;
1461 field->name = mono_field_get_name (>d->fields [i]);
1463 int idx = first_field_idx + i;
1464 /* first_field_idx and idx points into the fieldptr table */
1465 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1466 /* The name is needed for fieldrefs */
1467 field->name = mono_metadata_string_heap (image, name_idx);
1471 mono_memory_barrier ();
1473 mono_loader_lock ();
1475 klass->fields = fields;
1476 mono_loader_unlock ();
1480 * mono_class_set_failure_causedby_class:
1481 * \param klass the class that is failing
1482 * \param caused_by the class that caused the failure
1483 * \param msg Why \p klass is failing.
1485 * If \p caused_by has a failure, sets a TypeLoadException failure on
1486 * \p klass with message "\p msg, due to: {\p caused_by message}".
1488 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1491 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1493 if (mono_class_has_failure (caused_by)) {
1494 MonoError cause_error;
1495 error_init (&cause_error);
1496 mono_error_set_for_class_failure (&cause_error, caused_by);
1497 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1498 mono_error_cleanup (&cause_error);
1507 * mono_class_setup_fields:
1508 * \p klass The class to initialize
1510 * Initializes klass->fields, computes class layout and sizes.
1511 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1512 * Sets the following fields in \p klass:
1513 * - all the fields initialized by mono_class_init_sizes ()
1514 * - element_class/cast_class (for enums)
1515 * - field->type/offset for all fields
1518 * LOCKING: Acquires the loader lock.
1521 mono_class_setup_fields (MonoClass *klass)
1524 MonoImage *m = klass->image;
1526 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1528 guint32 real_size = 0;
1529 guint32 packing_size = 0;
1531 gboolean explicit_size;
1532 MonoClassField *field;
1533 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1534 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1536 if (klass->fields_inited)
1539 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1541 * This happens when a generic instance of an unfinished generic typebuilder
1542 * is used as an element type for creating an array type. We can't initialize
1543 * the fields of this class using the fields of gklass, since gklass is not
1544 * finished yet, fields could be added to it later.
1549 mono_class_setup_basic_field_info (klass);
1550 top = mono_class_get_field_count (klass);
1553 mono_class_setup_fields (gtd);
1554 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1559 if (klass->parent) {
1560 /* For generic instances, klass->parent might not have been initialized */
1561 mono_class_init (klass->parent);
1562 mono_class_setup_fields (klass->parent);
1563 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1565 instance_size = klass->parent->instance_size;
1567 instance_size = sizeof (MonoObject);
1570 /* Get the real size */
1571 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1573 instance_size += real_size;
1576 * This function can recursively call itself.
1577 * Prevent infinite recursion by using a list in TLS.
1579 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1580 if (g_slist_find (init_list, klass))
1582 init_list = g_slist_prepend (init_list, klass);
1583 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1586 * Fetch all the field information.
1588 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1589 for (i = 0; i < top; i++) {
1590 int idx = first_field_idx + i;
1591 field = &klass->fields [i];
1594 mono_field_resolve_type (field, &error);
1595 if (!mono_error_ok (&error)) {
1596 /*mono_field_resolve_type already failed class*/
1597 mono_error_cleanup (&error);
1601 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1602 g_assert (field->type);
1605 if (!mono_type_get_underlying_type (field->type)) {
1606 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
1610 if (mono_field_is_deleted (field))
1612 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1614 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1615 int offset = uoffset;
1617 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1618 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1621 if (offset < -1) { /*-1 is used to encode special static fields */
1622 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1625 if (mono_class_is_gtd (klass)) {
1626 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1630 if (mono_type_has_exceptions (field->type)) {
1631 char *class_name = mono_type_get_full_name (klass);
1632 char *type_name = mono_type_full_name (field->type);
1634 mono_class_set_type_load_failure (klass, "Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1635 g_free (class_name);
1639 /* The def_value of fields is compute lazily during vtable creation */
1642 if (!mono_class_has_failure (klass)) {
1643 mono_loader_lock ();
1644 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1645 mono_loader_unlock ();
1648 init_list = g_slist_remove (init_list, klass);
1649 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1653 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1656 mono_loader_lock ();
1657 klass->instance_size = cached_info->instance_size;
1658 klass->sizes.class_size = cached_info->class_size;
1659 klass->packing_size = cached_info->packing_size;
1660 klass->min_align = cached_info->min_align;
1661 klass->blittable = cached_info->blittable;
1662 klass->has_references = cached_info->has_references;
1663 klass->has_static_refs = cached_info->has_static_refs;
1664 klass->no_special_static_fields = cached_info->no_special_static_fields;
1665 mono_loader_unlock ();
1668 if (!klass->size_inited)
1669 mono_class_setup_fields (klass);
1674 * mono_class_init_sizes:
1676 * Initializes the size related fields of @klass without loading all field data if possible.
1677 * Sets the following fields in @klass:
1679 * - sizes.class_size
1686 * Can fail the class.
1688 * LOCKING: Acquires the loader lock.
1691 mono_class_init_sizes (MonoClass *klass)
1693 MonoCachedClassInfo cached_info;
1694 gboolean has_cached_info;
1696 if (klass->size_inited)
1699 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1701 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1705 * mono_type_get_basic_type_from_generic:
1708 * Returns a closed type corresponding to the possibly open type
1712 mono_type_get_basic_type_from_generic (MonoType *type)
1714 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1715 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1716 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1717 return &mono_defaults.object_class->byval_arg;
1722 class_has_references (MonoClass *klass)
1724 mono_class_init_sizes (klass);
1727 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1728 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1731 return klass->has_references;
1735 type_has_references (MonoClass *klass, MonoType *ftype)
1737 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1739 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1740 MonoGenericParam *gparam = ftype->data.generic_param;
1742 if (gparam->gshared_constraint)
1743 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1749 * mono_class_layout_fields:
1751 * @base_instance_size: base instance size
1754 * This contains the common code for computing the layout of classes and sizes.
1755 * This should only be called from mono_class_setup_fields () and
1756 * typebuilder_setup_fields ().
1758 * LOCKING: Acquires the loader lock
1761 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1764 const int top = mono_class_get_field_count (klass);
1765 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1766 guint32 pass, passes, real_size;
1767 gboolean gc_aware_layout = FALSE;
1768 gboolean has_static_fields = FALSE;
1769 gboolean has_references = FALSE;
1770 gboolean has_static_refs = FALSE;
1771 MonoClassField *field;
1773 int instance_size = base_instance_size;
1774 int class_size, min_align;
1776 gboolean *fields_has_references;
1779 * We want to avoid doing complicated work inside locks, so we compute all the required
1780 * information and write it to @klass inside a lock.
1782 if (klass->fields_inited)
1785 if ((packing_size & 0xffffff00) != 0) {
1786 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1790 if (klass->parent) {
1791 min_align = klass->parent->min_align;
1792 /* we use | since it may have been set already */
1793 has_references = klass->has_references | klass->parent->has_references;
1797 /* We can't really enable 16 bytes alignment until the GC supports it.
1798 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1799 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1800 Bug #506144 is an example of this issue.
1802 if (klass->simd_type)
1807 * When we do generic sharing we need to have layout
1808 * information for open generic classes (either with a generic
1809 * context containing type variables or with a generic
1810 * container), so we don't return in that case anymore.
1813 if (klass->enumtype) {
1814 for (i = 0; i < top; i++) {
1815 field = &klass->fields [i];
1816 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1817 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1822 if (!mono_class_enum_basetype (klass)) {
1823 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1829 * Enable GC aware auto layout: in this mode, reference
1830 * fields are grouped together inside objects, increasing collector
1832 * Requires that all classes whose layout is known to native code be annotated
1833 * with [StructLayout (LayoutKind.Sequential)]
1834 * Value types have gc_aware_layout disabled by default, as per
1835 * what the default is for other runtimes.
1837 /* corlib is missing [StructLayout] directives in many places */
1838 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1839 if (!klass->valuetype)
1840 gc_aware_layout = TRUE;
1843 /* Compute klass->blittable */
1846 blittable = klass->parent->blittable;
1847 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1849 for (i = 0; i < top; i++) {
1850 field = &klass->fields [i];
1852 if (mono_field_is_deleted (field))
1854 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1857 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1860 MonoClass *field_class = mono_class_from_mono_type (field->type);
1862 mono_class_setup_fields (field_class);
1863 if (mono_class_has_failure (field_class)) {
1864 MonoError field_error;
1865 error_init (&field_error);
1866 mono_error_set_for_class_failure (&field_error, field_class);
1867 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1868 mono_error_cleanup (&field_error);
1872 if (!field_class || !field_class->blittable)
1876 if (klass->enumtype)
1877 blittable = klass->element_class->blittable;
1879 if (mono_class_has_failure (klass))
1881 if (klass == mono_defaults.string_class)
1884 /* Compute klass->has_references */
1886 * Process non-static fields first, since static fields might recursively
1887 * refer to the class itself.
1889 for (i = 0; i < top; i++) {
1892 field = &klass->fields [i];
1894 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1895 ftype = mono_type_get_underlying_type (field->type);
1896 ftype = mono_type_get_basic_type_from_generic (ftype);
1897 if (type_has_references (klass, ftype))
1898 has_references = TRUE;
1903 * Compute field layout and total size (not considering static fields)
1905 field_offsets = g_new0 (int, top);
1906 fields_has_references = g_new0 (gboolean, top);
1907 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1909 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1910 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1911 if (gc_aware_layout)
1916 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1919 if (klass->parent) {
1920 mono_class_setup_fields (klass->parent);
1921 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1923 real_size = klass->parent->instance_size;
1925 real_size = sizeof (MonoObject);
1928 for (pass = 0; pass < passes; ++pass) {
1929 for (i = 0; i < top; i++){
1934 field = &klass->fields [i];
1936 if (mono_field_is_deleted (field))
1938 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1941 ftype = mono_type_get_underlying_type (field->type);
1942 ftype = mono_type_get_basic_type_from_generic (ftype);
1943 if (gc_aware_layout) {
1944 fields_has_references [i] = type_has_references (klass, ftype);
1945 if (fields_has_references [i]) {
1954 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1955 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1956 /* This field is a hack inserted by MCS to empty structures */
1960 size = mono_type_size (field->type, &align);
1962 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1963 align = packing_size ? MIN (packing_size, align): align;
1964 /* if the field has managed references, we need to force-align it
1967 if (type_has_references (klass, ftype))
1968 align = MAX (align, sizeof (gpointer));
1970 min_align = MAX (align, min_align);
1971 field_offsets [i] = real_size;
1973 field_offsets [i] += align - 1;
1974 field_offsets [i] &= ~(align - 1);
1976 /*TypeBuilders produce all sort of weird things*/
1977 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1978 real_size = field_offsets [i] + size;
1981 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1982 if (klass->simd_type)
1983 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1984 instance_size = MAX (real_size, instance_size);
1986 if (instance_size & (min_align - 1)) {
1987 instance_size += min_align - 1;
1988 instance_size &= ~(min_align - 1);
1992 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1996 for (i = 0; i < top; i++) {
2001 field = &klass->fields [i];
2004 * There must be info about all the fields in a type if it
2005 * uses explicit layout.
2007 if (mono_field_is_deleted (field))
2009 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2012 size = mono_type_size (field->type, &align);
2013 align = packing_size ? MIN (packing_size, align): align;
2014 min_align = MAX (align, min_align);
2017 /* Already set by typebuilder_setup_fields () */
2018 field_offsets [i] = field->offset + sizeof (MonoObject);
2020 int idx = first_field_idx + i;
2022 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2023 field_offsets [i] = offset + sizeof (MonoObject);
2025 ftype = mono_type_get_underlying_type (field->type);
2026 ftype = mono_type_get_basic_type_from_generic (ftype);
2027 if (type_has_references (klass, ftype)) {
2028 if (field_offsets [i] % sizeof (gpointer)) {
2029 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2036 real_size = MAX (real_size, size + field_offsets [i]);
2039 if (klass->has_references) {
2040 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2042 /* Check for overlapping reference and non-reference fields */
2043 for (i = 0; i < top; i++) {
2046 field = &klass->fields [i];
2048 if (mono_field_is_deleted (field))
2050 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2052 ftype = mono_type_get_underlying_type (field->type);
2053 if (MONO_TYPE_IS_REFERENCE (ftype))
2054 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2056 for (i = 0; i < top; i++) {
2057 field = &klass->fields [i];
2059 if (mono_field_is_deleted (field))
2061 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2064 // FIXME: Too much code does this
2066 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2067 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]);
2071 g_free (ref_bitmap);
2074 instance_size = MAX (real_size, instance_size);
2075 if (instance_size & (min_align - 1)) {
2076 instance_size += min_align - 1;
2077 instance_size &= ~(min_align - 1);
2083 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2085 * This leads to all kinds of problems with nested structs, so only
2086 * enable it when a MONO_DEBUG property is set.
2088 * For small structs, set min_align to at least the struct size to improve
2089 * performance, and since the JIT memset/memcpy code assumes this and generates
2090 * unaligned accesses otherwise. See #78990 for a testcase.
2092 if (mono_align_small_structs && top) {
2093 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2094 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2098 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2099 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2100 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2101 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2103 /* Publish the data */
2104 mono_loader_lock ();
2105 if (klass->instance_size && !klass->image->dynamic) {
2106 /* Might be already set using cached info */
2107 if (klass->instance_size != instance_size) {
2108 /* Emit info to help debugging */
2109 g_print ("%s\n", mono_class_full_name (klass));
2110 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2111 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2112 g_print ("%d %d\n", klass->min_align, min_align);
2113 for (i = 0; i < top; ++i) {
2114 field = &klass->fields [i];
2115 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2116 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2119 g_assert (klass->instance_size == instance_size);
2121 klass->instance_size = instance_size;
2123 klass->blittable = blittable;
2124 klass->has_references = has_references;
2125 klass->packing_size = packing_size;
2126 klass->min_align = min_align;
2127 for (i = 0; i < top; ++i) {
2128 field = &klass->fields [i];
2129 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2130 klass->fields [i].offset = field_offsets [i];
2133 mono_memory_barrier ();
2134 klass->size_inited = 1;
2135 mono_loader_unlock ();
2138 * Compute static field layout and size
2139 * Static fields can reference the class itself, so this has to be
2140 * done after instance_size etc. are initialized.
2143 for (i = 0; i < top; i++) {
2147 field = &klass->fields [i];
2149 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2151 if (mono_field_is_deleted (field))
2154 if (mono_type_has_exceptions (field->type)) {
2155 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2159 has_static_fields = TRUE;
2161 size = mono_type_size (field->type, &align);
2162 field_offsets [i] = class_size;
2163 /*align is always non-zero here*/
2164 field_offsets [i] += align - 1;
2165 field_offsets [i] &= ~(align - 1);
2166 class_size = field_offsets [i] + size;
2169 if (has_static_fields && class_size == 0)
2170 /* Simplify code which depends on class_size != 0 if the class has static fields */
2173 /* Compute klass->has_static_refs */
2174 has_static_refs = FALSE;
2175 for (i = 0; i < top; i++) {
2178 field = &klass->fields [i];
2180 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2181 ftype = mono_type_get_underlying_type (field->type);
2182 ftype = mono_type_get_basic_type_from_generic (ftype);
2183 if (type_has_references (klass, ftype))
2184 has_static_refs = TRUE;
2188 /*valuetypes can't be neither bigger than 1Mb or empty. */
2189 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2190 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2192 /* Publish the data */
2193 mono_loader_lock ();
2195 klass->sizes.class_size = class_size;
2196 klass->has_static_refs = has_static_refs;
2197 for (i = 0; i < top; ++i) {
2198 field = &klass->fields [i];
2200 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2201 field->offset = field_offsets [i];
2204 mono_memory_barrier ();
2205 klass->fields_inited = 1;
2206 mono_loader_unlock ();
2208 g_free (field_offsets);
2209 g_free (fields_has_references);
2213 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2217 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2218 method->klass = klass;
2219 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2220 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2221 method->signature = sig;
2222 method->name = name;
2225 if (name [0] == '.') {
2226 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2228 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2234 * mono_class_setup_methods:
2237 * Initializes the 'methods' array in CLASS.
2238 * Calling this method should be avoided if possible since it allocates a lot
2239 * of long-living MonoMethod structures.
2240 * Methods belonging to an interface are assigned a sequential slot starting
2243 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2246 mono_class_setup_methods (MonoClass *klass)
2249 MonoMethod **methods;
2254 if (mono_class_is_ginst (klass)) {
2256 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2258 mono_class_init (gklass);
2259 if (!mono_class_has_failure (gklass))
2260 mono_class_setup_methods (gklass);
2261 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2264 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2265 count = mono_class_get_method_count (gklass);
2266 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2268 for (i = 0; i < count; i++) {
2269 methods [i] = mono_class_inflate_generic_method_full_checked (
2270 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2271 if (!mono_error_ok (&error)) {
2272 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2273 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2276 mono_error_cleanup (&error);
2280 } else if (klass->rank) {
2282 MonoMethod *amethod;
2283 MonoMethodSignature *sig;
2284 int count_generic = 0, first_generic = 0;
2286 gboolean jagged_ctor = FALSE;
2288 count = 3 + (klass->rank > 1? 2: 1);
2290 mono_class_setup_interfaces (klass, &error);
2291 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2293 if (klass->rank == 1 && klass->element_class->rank) {
2298 if (klass->interface_count) {
2299 count_generic = generic_array_methods (klass);
2300 first_generic = count;
2301 count += klass->interface_count * count_generic;
2304 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2306 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2307 sig->ret = &mono_defaults.void_class->byval_arg;
2308 sig->pinvoke = TRUE;
2309 sig->hasthis = TRUE;
2310 for (i = 0; i < klass->rank; ++i)
2311 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2313 amethod = create_array_method (klass, ".ctor", sig);
2314 methods [method_num++] = amethod;
2315 if (klass->rank > 1) {
2316 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2317 sig->ret = &mono_defaults.void_class->byval_arg;
2318 sig->pinvoke = TRUE;
2319 sig->hasthis = TRUE;
2320 for (i = 0; i < klass->rank * 2; ++i)
2321 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2323 amethod = create_array_method (klass, ".ctor", sig);
2324 methods [method_num++] = amethod;
2328 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2329 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2330 sig->ret = &mono_defaults.void_class->byval_arg;
2331 sig->pinvoke = TRUE;
2332 sig->hasthis = TRUE;
2333 for (i = 0; i < klass->rank + 1; ++i)
2334 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2335 amethod = create_array_method (klass, ".ctor", sig);
2336 methods [method_num++] = amethod;
2339 /* element Get (idx11, [idx2, ...]) */
2340 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2341 sig->ret = &klass->element_class->byval_arg;
2342 sig->pinvoke = TRUE;
2343 sig->hasthis = TRUE;
2344 for (i = 0; i < klass->rank; ++i)
2345 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2346 amethod = create_array_method (klass, "Get", sig);
2347 methods [method_num++] = amethod;
2348 /* element& Address (idx11, [idx2, ...]) */
2349 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2350 sig->ret = &klass->element_class->this_arg;
2351 sig->pinvoke = TRUE;
2352 sig->hasthis = TRUE;
2353 for (i = 0; i < klass->rank; ++i)
2354 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2355 amethod = create_array_method (klass, "Address", sig);
2356 methods [method_num++] = amethod;
2357 /* void Set (idx11, [idx2, ...], element) */
2358 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2359 sig->ret = &mono_defaults.void_class->byval_arg;
2360 sig->pinvoke = TRUE;
2361 sig->hasthis = TRUE;
2362 for (i = 0; i < klass->rank; ++i)
2363 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2364 sig->params [i] = &klass->element_class->byval_arg;
2365 amethod = create_array_method (klass, "Set", sig);
2366 methods [method_num++] = amethod;
2368 GHashTable *cache = g_hash_table_new (NULL, NULL);
2369 for (i = 0; i < klass->interface_count; i++)
2370 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2371 g_hash_table_destroy (cache);
2372 } else if (mono_class_has_static_metadata (klass)) {
2374 int first_idx = mono_class_get_first_method_idx (klass);
2376 count = mono_class_get_method_count (klass);
2377 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2378 for (i = 0; i < count; ++i) {
2379 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2380 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2382 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2383 mono_error_cleanup (&error);
2387 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2391 if (MONO_CLASS_IS_INTERFACE (klass)) {
2393 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2394 for (i = 0; i < count; ++i) {
2395 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2396 methods [i]->slot = slot++;
2400 mono_image_lock (klass->image);
2402 if (!klass->methods) {
2403 mono_class_set_method_count (klass, count);
2405 /* Needed because of the double-checking locking pattern */
2406 mono_memory_barrier ();
2408 klass->methods = methods;
2411 mono_image_unlock (klass->image);
2415 * mono_class_get_method_by_index:
2417 * Returns klass->methods [index], initializing klass->methods if neccesary.
2419 * LOCKING: Acquires the loader lock.
2422 mono_class_get_method_by_index (MonoClass *klass, int index)
2426 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2427 /* Avoid calling setup_methods () if possible */
2428 if (gklass && !klass->methods) {
2431 m = mono_class_inflate_generic_method_full_checked (
2432 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2433 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2435 * If setup_methods () is called later for this class, no duplicates are created,
2436 * since inflate_generic_method guarantees that only one instance of a method
2437 * is created for each context.
2440 mono_class_setup_methods (klass);
2441 g_assert (m == klass->methods [index]);
2445 mono_class_setup_methods (klass);
2446 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2448 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2449 return klass->methods [index];
2454 * mono_class_get_inflated_method:
2456 * Given an inflated class CLASS and a method METHOD which should be a method of
2457 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2460 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2462 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2465 g_assert (method->klass == gklass);
2467 mono_class_setup_methods (gklass);
2468 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2470 mcount = mono_class_get_method_count (gklass);
2471 for (i = 0; i < mcount; ++i) {
2472 if (gklass->methods [i] == method) {
2473 if (klass->methods) {
2474 return klass->methods [i];
2477 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2478 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2488 * mono_class_get_vtable_entry:
2490 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2491 * LOCKING: Acquires the loader lock.
2494 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2498 if (klass->rank == 1) {
2500 * szarrays do not overwrite any methods of Array, so we can avoid
2501 * initializing their vtables in some cases.
2503 mono_class_setup_vtable (klass->parent);
2504 if (offset < klass->parent->vtable_size)
2505 return klass->parent->vtable [offset];
2508 if (mono_class_is_ginst (klass)) {
2510 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2511 mono_class_setup_vtable (gklass);
2512 m = gklass->vtable [offset];
2514 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2515 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2517 mono_class_setup_vtable (klass);
2518 if (mono_class_has_failure (klass))
2520 m = klass->vtable [offset];
2527 * mono_class_get_vtable_size:
2529 * Return the vtable size for KLASS.
2532 mono_class_get_vtable_size (MonoClass *klass)
2534 mono_class_setup_vtable (klass);
2536 return klass->vtable_size;
2540 * mono_class_setup_properties:
2542 * Initialize klass->ext.property and klass->ext.properties.
2544 * This method can fail the class.
2547 mono_class_setup_properties (MonoClass *klass)
2549 guint startm, endm, i, j;
2550 guint32 cols [MONO_PROPERTY_SIZE];
2551 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2552 MonoProperty *properties;
2555 MonoClassPropertyInfo *info;
2557 info = mono_class_get_property_info (klass);
2561 if (mono_class_is_ginst (klass)) {
2562 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2564 mono_class_init (gklass);
2565 mono_class_setup_properties (gklass);
2566 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2569 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2570 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2572 for (i = 0; i < ginfo->count; i++) {
2574 MonoProperty *prop = &properties [i];
2576 *prop = ginfo->properties [i];
2579 prop->get = mono_class_inflate_generic_method_full_checked (
2580 prop->get, klass, mono_class_get_context (klass), &error);
2582 prop->set = mono_class_inflate_generic_method_full_checked (
2583 prop->set, klass, mono_class_get_context (klass), &error);
2585 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2586 prop->parent = klass;
2589 first = ginfo->first;
2590 count = ginfo->count;
2592 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2593 count = last - first;
2596 mono_class_setup_methods (klass);
2597 if (mono_class_has_failure (klass))
2601 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2602 for (i = first; i < last; ++i) {
2603 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2604 properties [i - first].parent = klass;
2605 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2606 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2608 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2609 int first_idx = mono_class_get_first_method_idx (klass);
2610 for (j = startm; j < endm; ++j) {
2613 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2615 if (klass->image->uncompressed_metadata) {
2617 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2618 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2619 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2621 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2624 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2625 case METHOD_SEMANTIC_SETTER:
2626 properties [i - first].set = method;
2628 case METHOD_SEMANTIC_GETTER:
2629 properties [i - first].get = method;
2638 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2639 info->first = first;
2640 info->count = count;
2641 info->properties = properties;
2642 mono_memory_barrier ();
2644 /* This might leak 'info' which was allocated from the image mempool */
2645 mono_class_set_property_info (klass, info);
2649 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2651 MonoMethod **om, **retval;
2654 for (om = methods, count = 0; *om; ++om, ++count)
2657 retval = g_new0 (MonoMethod*, count + 1);
2659 for (om = methods, count = 0; *om; ++om, ++count) {
2661 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2662 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2668 /*This method can fail the class.*/
2670 mono_class_setup_events (MonoClass *klass)
2673 guint startm, endm, i, j;
2674 guint32 cols [MONO_EVENT_SIZE];
2675 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2679 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2683 if (mono_class_is_ginst (klass)) {
2684 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2685 MonoGenericContext *context = NULL;
2687 mono_class_setup_events (gklass);
2688 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2691 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2692 first = ginfo->first;
2693 count = ginfo->count;
2695 events = mono_class_new0 (klass, MonoEvent, count);
2698 context = mono_class_get_context (klass);
2700 for (i = 0; i < count; i++) {
2702 MonoEvent *event = &events [i];
2703 MonoEvent *gevent = &ginfo->events [i];
2705 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2707 event->parent = klass;
2708 event->name = gevent->name;
2709 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2710 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2711 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2712 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2713 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2714 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2716 #ifndef MONO_SMALL_CONFIG
2717 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2719 event->attrs = gevent->attrs;
2722 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2723 count = last - first;
2726 mono_class_setup_methods (klass);
2727 if (mono_class_has_failure (klass)) {
2732 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2733 for (i = first; i < last; ++i) {
2734 MonoEvent *event = &events [i - first];
2736 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2737 event->parent = klass;
2738 event->attrs = cols [MONO_EVENT_FLAGS];
2739 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2741 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2742 int first_idx = mono_class_get_first_method_idx (klass);
2743 for (j = startm; j < endm; ++j) {
2746 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2748 if (klass->image->uncompressed_metadata) {
2750 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2751 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2752 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2754 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2757 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2758 case METHOD_SEMANTIC_ADD_ON:
2759 event->add = method;
2761 case METHOD_SEMANTIC_REMOVE_ON:
2762 event->remove = method;
2764 case METHOD_SEMANTIC_FIRE:
2765 event->raise = method;
2767 case METHOD_SEMANTIC_OTHER: {
2768 #ifndef MONO_SMALL_CONFIG
2771 if (event->other == NULL) {
2772 event->other = g_new0 (MonoMethod*, 2);
2774 while (event->other [n])
2776 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2778 event->other [n] = method;
2779 /* NULL terminated */
2780 event->other [n + 1] = NULL;
2791 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2792 info->events = events;
2793 info->first = first;
2794 info->count = count;
2796 mono_memory_barrier ();
2798 mono_class_set_event_info (klass, info);
2802 * Global pool of interface IDs, represented as a bitset.
2803 * LOCKING: Protected by the classes lock.
2805 static MonoBitSet *global_interface_bitset = NULL;
2808 * mono_unload_interface_ids:
2809 * @bitset: bit set of interface IDs
2811 * When an image is unloaded, the interface IDs associated with
2812 * the image are put back in the global pool of IDs so the numbers
2816 mono_unload_interface_ids (MonoBitSet *bitset)
2819 mono_bitset_sub (global_interface_bitset, bitset);
2824 mono_unload_interface_id (MonoClass *klass)
2826 if (global_interface_bitset && klass->interface_id) {
2828 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2834 * mono_get_unique_iid:
2835 * \param klass interface
2837 * Assign a unique integer ID to the interface represented by \p klass.
2838 * The ID will positive and as small as possible.
2839 * LOCKING: Acquires the classes lock.
2840 * \returns The new ID.
2843 mono_get_unique_iid (MonoClass *klass)
2847 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2851 if (!global_interface_bitset) {
2852 global_interface_bitset = mono_bitset_new (128, 0);
2855 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2857 int old_size = mono_bitset_size (global_interface_bitset);
2858 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2859 mono_bitset_free (global_interface_bitset);
2860 global_interface_bitset = new_set;
2863 mono_bitset_set (global_interface_bitset, iid);
2864 /* set the bit also in the per-image set */
2865 if (!mono_class_is_ginst (klass)) {
2866 if (klass->image->interface_bitset) {
2867 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2868 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2869 mono_bitset_free (klass->image->interface_bitset);
2870 klass->image->interface_bitset = new_set;
2873 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2875 mono_bitset_set (klass->image->interface_bitset, iid);
2880 #ifndef MONO_SMALL_CONFIG
2881 if (mono_print_vtable) {
2883 char *type_name = mono_type_full_name (&klass->byval_arg);
2884 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2885 if (gklass && !gklass->context.class_inst->is_open) {
2886 generic_id = gklass->context.class_inst->id;
2887 g_assert (generic_id != 0);
2891 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2896 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2897 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2898 g_assert (iid < INT_MAX);
2903 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2908 mono_class_setup_interfaces (klass, error);
2909 return_if_nok (error);
2911 for (i = 0; i < klass->interface_count; i++) {
2912 ic = klass->interfaces [i];
2915 *res = g_ptr_array_new ();
2916 if (*ifaces == NULL)
2917 *ifaces = g_hash_table_new (NULL, NULL);
2918 if (g_hash_table_lookup (*ifaces, ic))
2920 g_ptr_array_add (*res, ic);
2921 g_hash_table_insert (*ifaces, ic, ic);
2922 mono_class_init (ic);
2923 if (mono_class_has_failure (ic)) {
2924 mono_error_set_type_load_class (error, ic, "Error Loading class");
2928 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2929 return_if_nok (error);
2934 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2936 GPtrArray *res = NULL;
2937 GHashTable *ifaces = NULL;
2939 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2941 g_hash_table_destroy (ifaces);
2942 if (!mono_error_ok (error)) {
2944 g_ptr_array_free (res, TRUE);
2951 compare_interface_ids (const void *p_key, const void *p_element)
2953 const MonoClass *key = (const MonoClass *)p_key;
2954 const MonoClass *element = *(const MonoClass **)p_element;
2956 return (key->interface_id - element->interface_id);
2959 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2961 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2963 MonoClass **result = (MonoClass **)mono_binary_search (
2965 klass->interfaces_packed,
2966 klass->interface_offsets_count,
2967 sizeof (MonoClass *),
2968 compare_interface_ids);
2970 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2977 * mono_class_interface_offset_with_variance:
2979 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2980 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2982 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2984 * FIXME figure out MS disambiguation rules and fix this function.
2987 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2989 int i = mono_class_interface_offset (klass, itf);
2990 *non_exact_match = FALSE;
2994 if (itf->is_array_special_interface && klass->rank < 2) {
2995 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2997 for (i = 0; i < klass->interface_offsets_count; i++) {
2998 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2999 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3000 *non_exact_match = TRUE;
3001 return klass->interface_offsets_packed [i];
3006 if (!mono_class_has_variant_generic_params (itf))
3009 for (i = 0; i < klass->interface_offsets_count; i++) {
3010 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3011 *non_exact_match = TRUE;
3012 return klass->interface_offsets_packed [i];
3020 print_implemented_interfaces (MonoClass *klass)
3024 GPtrArray *ifaces = NULL;
3026 int ancestor_level = 0;
3028 name = mono_type_get_full_name (klass);
3029 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3032 for (i = 0; i < klass->interface_offsets_count; i++)
3033 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3034 klass->interfaces_packed [i]->interface_id,
3035 klass->interface_offsets_packed [i],
3036 mono_class_get_method_count (klass->interfaces_packed [i]),
3037 klass->interfaces_packed [i]->name_space,
3038 klass->interfaces_packed [i]->name );
3039 printf ("Interface flags: ");
3040 for (i = 0; i <= klass->max_interface_id; i++)
3041 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3042 printf ("(%d,T)", i);
3044 printf ("(%d,F)", i);
3046 printf ("Dump interface flags:");
3047 #ifdef COMPRESSED_INTERFACE_BITMAP
3049 const uint8_t* p = klass->interface_bitmap;
3050 i = klass->max_interface_id;
3052 printf (" %d x 00 %02X", p [0], p [1]);
3058 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3059 printf (" %02X", klass->interface_bitmap [i]);
3062 while (klass != NULL) {
3063 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3064 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3065 if (!mono_error_ok (&error)) {
3066 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3067 mono_error_cleanup (&error);
3068 } else if (ifaces) {
3069 for (i = 0; i < ifaces->len; i++) {
3070 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3071 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3072 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3074 mono_class_interface_offset (klass, ic),
3075 mono_class_get_method_count (ic),
3079 g_ptr_array_free (ifaces, TRUE);
3082 klass = klass->parent;
3087 * Return the number of virtual methods.
3088 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3089 * Return -1 on failure.
3090 * FIXME It would be nice if this information could be cached somewhere.
3093 count_virtual_methods (MonoClass *klass)
3095 int i, mcount, vcount = 0;
3097 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3099 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3100 mono_class_setup_methods (klass);
3101 if (mono_class_has_failure (klass))
3104 mcount = mono_class_get_method_count (klass);
3105 for (i = 0; i < mcount; ++i) {
3106 flags = klass->methods [i]->flags;
3107 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3111 int first_idx = mono_class_get_first_method_idx (klass);
3112 mcount = mono_class_get_method_count (klass);
3113 for (i = 0; i < mcount; ++i) {
3114 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3116 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3124 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3132 m = (l + num_ifaces) / 2;
3133 if (interfaces_full [m] == ic)
3135 if (l == num_ifaces)
3137 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3146 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3148 int i = find_interface (num_ifaces, interfaces_full, ic);
3152 interface_offsets_full [i] = offset;
3155 for (i = 0; i < num_ifaces; ++i) {
3156 if (interfaces_full [i]) {
3158 if (interfaces_full [i]->interface_id < ic->interface_id)
3161 while (end < num_ifaces && interfaces_full [end]) end++;
3162 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3163 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3165 interfaces_full [i] = ic;
3166 interface_offsets_full [i] = offset;
3172 #ifdef COMPRESSED_INTERFACE_BITMAP
3175 * Compressed interface bitmap design.
3177 * Interface bitmaps take a large amount of memory, because their size is
3178 * linear with the maximum interface id assigned in the process (each interface
3179 * is assigned a unique id as it is loaded). The number of interface classes
3180 * is high because of the many implicit interfaces implemented by arrays (we'll
3181 * need to lazy-load them in the future).
3182 * Most classes implement a very small number of interfaces, so the bitmap is
3183 * sparse. This bitmap needs to be checked by interface casts, so access to the
3184 * needed bit must be fast and doable with few jit instructions.
3186 * The current compression format is as follows:
3187 * *) it is a sequence of one or more two-byte elements
3188 * *) the first byte in the element is the count of empty bitmap bytes
3189 * at the current bitmap position
3190 * *) the second byte in the element is an actual bitmap byte at the current
3193 * As an example, the following compressed bitmap bytes:
3194 * 0x07 0x01 0x00 0x7
3195 * correspond to the following bitmap:
3196 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3198 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3199 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3200 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3204 * mono_compress_bitmap:
3205 * \param dest destination buffer
3206 * \param bitmap bitmap buffer
3207 * \param size size of \p bitmap in bytes
3209 * This is a mono internal function.
3210 * The \p bitmap data is compressed into a format that is small but
3211 * still searchable in few instructions by the JIT and runtime.
3212 * The compressed data is stored in the buffer pointed to by the
3213 * \p dest array. Passing a NULL value for \p dest allows to just compute
3214 * the size of the buffer.
3215 * This compression algorithm assumes the bits set in the bitmap are
3216 * few and far between, like in interface bitmaps.
3217 * \returns The size of the compressed bitmap in bytes.
3220 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3224 const uint8_t *end = bitmap + size;
3225 while (bitmap < end) {
3226 if (*bitmap || numz == 255) {
3250 * mono_class_interface_match:
3251 * \param bitmap a compressed bitmap buffer
3252 * \param id the index to check in the bitmap
3254 * This is a mono internal function.
3255 * Checks if a bit is set in a compressed interface bitmap. \p id must
3256 * be already checked for being smaller than the maximum id encoded in the
3259 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3263 mono_class_interface_match (const uint8_t *bitmap, int id)
3266 id -= bitmap [0] * 8;
3270 return bitmap [1] & (1 << id);
3279 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3280 * LOCKING: Acquires the loader lock.
3283 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3287 int i, j, num_ifaces;
3289 MonoClass **interfaces_full = NULL;
3290 int *interface_offsets_full = NULL;
3292 GPtrArray **ifaces_array = NULL;
3293 int interface_offsets_count;
3295 mono_loader_lock ();
3297 mono_class_setup_supertypes (klass);
3299 /* compute maximum number of slots and maximum interface id */
3301 num_ifaces = 0; /* this can include duplicated ones */
3302 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3303 for (j = 0; j < klass->idepth; j++) {
3304 k = klass->supertypes [j];
3306 num_ifaces += k->interface_count;
3307 for (i = 0; i < k->interface_count; i++) {
3308 ic = k->interfaces [i];
3310 mono_class_init (ic);
3312 if (max_iid < ic->interface_id)
3313 max_iid = ic->interface_id;
3315 ifaces = mono_class_get_implemented_interfaces (k, &error);
3316 if (!mono_error_ok (&error)) {
3317 char *name = mono_type_get_full_name (k);
3318 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3320 mono_error_cleanup (&error);
3325 num_ifaces += ifaces->len;
3326 for (i = 0; i < ifaces->len; ++i) {
3327 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3328 if (max_iid < ic->interface_id)
3329 max_iid = ic->interface_id;
3331 ifaces_array [j] = ifaces;
3335 if (MONO_CLASS_IS_INTERFACE (klass)) {
3337 if (max_iid < klass->interface_id)
3338 max_iid = klass->interface_id;
3341 /* compute vtable offset for interfaces */
3342 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3343 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3345 for (i = 0; i < num_ifaces; i++)
3346 interface_offsets_full [i] = -1;
3348 /* skip the current class */
3349 for (j = 0; j < klass->idepth - 1; j++) {
3350 k = klass->supertypes [j];
3351 ifaces = ifaces_array [j];
3354 for (i = 0; i < ifaces->len; ++i) {
3356 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3358 /*Force the sharing of interface offsets between parent and subtypes.*/
3359 io = mono_class_interface_offset (k, ic);
3361 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3366 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3367 ifaces = ifaces_array [klass->idepth - 1];
3369 for (i = 0; i < ifaces->len; ++i) {
3371 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3372 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3374 count = count_virtual_methods (ic);
3376 char *name = mono_type_get_full_name (ic);
3377 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3386 if (MONO_CLASS_IS_INTERFACE (klass))
3387 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3389 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3390 if (interface_offsets_full [i] != -1)
3391 interface_offsets_count ++;
3394 /* Publish the data */
3395 klass->max_interface_id = max_iid;
3397 * We might get called multiple times:
3398 * - mono_class_init ()
3399 * - mono_class_setup_vtable ().
3400 * - mono_class_setup_interface_offsets ().
3401 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3402 * means we have to overwrite those when called from other places (#4440).
3404 if (klass->interfaces_packed) {
3406 g_assert (klass->interface_offsets_count == interface_offsets_count);
3410 klass->interface_offsets_count = interface_offsets_count;
3411 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3412 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3413 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3414 #ifdef COMPRESSED_INTERFACE_BITMAP
3415 bitmap = g_malloc0 (bsize);
3417 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3419 for (i = 0; i < interface_offsets_count; i++) {
3420 guint32 id = interfaces_full [i]->interface_id;
3421 bitmap [id >> 3] |= (1 << (id & 7));
3422 klass->interfaces_packed [i] = interfaces_full [i];
3423 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3425 #ifdef COMPRESSED_INTERFACE_BITMAP
3426 i = mono_compress_bitmap (NULL, bitmap, bsize);
3427 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3428 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3431 klass->interface_bitmap = bitmap;
3435 mono_loader_unlock ();
3437 g_free (interfaces_full);
3438 g_free (interface_offsets_full);
3439 for (i = 0; i < klass->idepth; i++) {
3440 ifaces = ifaces_array [i];
3442 g_ptr_array_free (ifaces, TRUE);
3444 g_free (ifaces_array);
3446 //printf ("JUST DONE: ");
3447 //print_implemented_interfaces (klass);
3453 * Setup interface offsets for interfaces.
3455 * - klass->max_interface_id
3456 * - klass->interface_offsets_count
3457 * - klass->interfaces_packed
3458 * - klass->interface_offsets_packed
3459 * - klass->interface_bitmap
3461 * This function can fail @class.
3464 mono_class_setup_interface_offsets (MonoClass *klass)
3466 setup_interface_offsets (klass, 0, FALSE);
3469 /*Checks if @klass has @parent as one of it's parents type gtd
3473 * Bar<T> : Foo<Bar<Bar<T>>>
3477 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3479 klass = mono_class_get_generic_type_definition (klass);
3480 parent = mono_class_get_generic_type_definition (parent);
3481 mono_class_setup_supertypes (klass);
3482 mono_class_setup_supertypes (parent);
3484 return klass->idepth >= parent->idepth &&
3485 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3489 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3491 MonoGenericInst *ginst;
3494 if (!mono_class_is_ginst (klass)) {
3495 mono_class_setup_vtable_full (klass, in_setup);
3496 return !mono_class_has_failure (klass);
3499 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3500 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3503 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3504 for (i = 0; i < ginst->type_argc; ++i) {
3506 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3508 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3509 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3510 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3512 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3513 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3521 * mono_class_setup_vtable:
3523 * Creates the generic vtable of CLASS.
3524 * Initializes the following fields in MonoClass:
3527 * Plus all the fields initialized by setup_interface_offsets ().
3528 * If there is an error during vtable construction, klass->has_failure
3529 * is set and details are stored in a MonoErrorBoxed.
3531 * LOCKING: Acquires the loader lock.
3534 mono_class_setup_vtable (MonoClass *klass)
3536 mono_class_setup_vtable_full (klass, NULL);
3540 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3543 MonoMethod **overrides;
3544 MonoGenericContext *context;
3552 if (MONO_CLASS_IS_INTERFACE (klass)) {
3553 /* This sets method->slot for all methods if this is an interface */
3554 mono_class_setup_methods (klass);
3558 if (mono_class_has_failure (klass))
3561 if (g_list_find (in_setup, klass))
3564 mono_loader_lock ();
3566 if (klass->vtable) {
3567 mono_loader_unlock ();
3571 mono_stats.generic_vtable_count ++;
3572 in_setup = g_list_prepend (in_setup, klass);
3574 if (mono_class_is_ginst (klass)) {
3575 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3576 mono_loader_unlock ();
3577 g_list_remove (in_setup, klass);
3581 context = mono_class_get_context (klass);
3582 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3584 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3585 type_token = klass->type_token;
3588 if (image_is_dynamic (klass->image)) {
3589 /* Generic instances can have zero method overrides without causing any harm.
3590 * This is true since we don't do layout all over again for them, we simply inflate
3591 * the layout of the parent.
3593 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3594 if (!is_ok (&error)) {
3595 mono_loader_unlock ();
3596 g_list_remove (in_setup, klass);
3597 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3598 mono_error_cleanup (&error);
3602 /* The following call fails if there are missing methods in the type */
3603 /* FIXME it's probably a good idea to avoid this for generic instances. */
3604 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3608 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3610 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3614 mono_loader_unlock ();
3615 g_list_remove (in_setup, klass);
3620 #define DEBUG_INTERFACE_VTABLE_CODE 0
3621 #define TRACE_INTERFACE_VTABLE_CODE 0
3622 #define VERIFY_INTERFACE_VTABLE_CODE 0
3623 #define VTABLE_SELECTOR (1)
3625 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3626 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3627 if (!(VTABLE_SELECTOR)) break; \
3631 #define DEBUG_INTERFACE_VTABLE(stmt)
3634 #if TRACE_INTERFACE_VTABLE_CODE
3635 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3636 if (!(VTABLE_SELECTOR)) break; \
3640 #define TRACE_INTERFACE_VTABLE(stmt)
3643 #if VERIFY_INTERFACE_VTABLE_CODE
3644 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3645 if (!(VTABLE_SELECTOR)) break; \
3649 #define VERIFY_INTERFACE_VTABLE(stmt)
3653 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3655 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3659 GString *res = g_string_new ("");
3661 g_string_append_c (res, '(');
3662 for (i = 0; i < sig->param_count; ++i) {
3664 g_string_append_c (res, ',');
3665 mono_type_get_desc (res, sig->params [i], include_namespace);
3667 g_string_append (res, ")=>");
3668 if (sig->ret != NULL) {
3669 mono_type_get_desc (res, sig->ret, include_namespace);
3671 g_string_append (res, "NULL");
3674 g_string_free (res, FALSE);
3678 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3679 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3680 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3681 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3689 is_wcf_hack_disabled (void)
3691 static gboolean disabled;
3692 static gboolean inited = FALSE;
3694 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3701 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3703 MonoMethodSignature *cmsig, *imsig;
3704 if (strcmp (im->name, cm->name) == 0) {
3705 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3706 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3709 if (! slot_is_empty) {
3710 if (require_newslot) {
3711 if (! interface_is_explicitly_implemented_by_class) {
3712 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3715 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3716 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3720 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3723 cmsig = mono_method_signature (cm);
3724 imsig = mono_method_signature (im);
3725 if (!cmsig || !imsig) {
3726 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3730 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3731 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3732 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3733 TRACE_INTERFACE_VTABLE (printf ("]"));
3736 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3737 if (mono_security_core_clr_enabled ())
3738 mono_security_core_clr_check_override (klass, cm, im);
3740 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3741 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3742 char *body_name = mono_method_full_name (cm, TRUE);
3743 char *decl_name = mono_method_full_name (im, TRUE);
3744 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3752 MonoClass *ic = im->klass;
3753 const char *ic_name_space = ic->name_space;
3754 const char *ic_name = ic->name;
3757 if (! require_newslot) {
3758 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3761 if (cm->klass->rank == 0) {
3762 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3765 cmsig = mono_method_signature (cm);
3766 imsig = mono_method_signature (im);
3767 if (!cmsig || !imsig) {
3768 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3772 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3773 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3774 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3775 TRACE_INTERFACE_VTABLE (printf ("]"));
3778 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3779 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3782 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3783 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3786 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))) {
3787 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3791 subname = strstr (cm->name, ic_name_space);
3792 if (subname != cm->name) {
3793 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3796 subname += strlen (ic_name_space);
3797 if (subname [0] != '.') {
3798 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3802 if (strstr (subname, ic_name) != subname) {
3803 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3806 subname += strlen (ic_name);
3807 if (subname [0] != '.') {
3808 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3812 if (strcmp (subname, im->name) != 0) {
3813 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3817 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3818 if (mono_security_core_clr_enabled ())
3819 mono_security_core_clr_check_override (klass, cm, im);
3821 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3822 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3823 char *body_name = mono_method_full_name (cm, TRUE);
3824 char *decl_name = mono_method_full_name (im, TRUE);
3825 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3835 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3837 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3838 MonoMethod *method = key;
3839 MonoMethod *override = value;
3840 MonoClass *method_class = mono_method_get_class (method);
3841 MonoClass *override_class = mono_method_get_class (override);
3843 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3844 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3845 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3848 print_overrides (GHashTable *override_map, const char *message) {
3850 printf ("Override map \"%s\" START:\n", message);
3851 g_hash_table_foreach (override_map, foreach_override, NULL);
3852 printf ("Override map \"%s\" END.\n", message);
3854 printf ("Override map \"%s\" EMPTY.\n", message);
3858 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3859 char *full_name = mono_type_full_name (&klass->byval_arg);
3863 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3865 if (print_interfaces) {
3866 print_implemented_interfaces (klass);
3867 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3870 if (klass->parent) {
3871 parent_size = klass->parent->vtable_size;
3875 for (i = 0; i < size; ++i) {
3876 MonoMethod *cm = vtable [i];
3877 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3878 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3880 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3888 #if VERIFY_INTERFACE_VTABLE_CODE
3890 mono_method_try_get_vtable_index (MonoMethod *method)
3892 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3893 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3894 if (imethod->declaring->is_generic)
3895 return imethod->declaring->slot;
3897 return method->slot;
3901 mono_class_verify_vtable (MonoClass *klass)
3904 char *full_name = mono_type_full_name (&klass->byval_arg);
3906 printf ("*** Verifying VTable of class '%s' \n", full_name);
3910 if (!klass->methods)
3913 count = mono_class_method_count (klass);
3914 for (i = 0; i < count; ++i) {
3915 MonoMethod *cm = klass->methods [i];
3918 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3922 full_name = mono_method_full_name (cm, TRUE);
3924 slot = mono_method_try_get_vtable_index (cm);
3926 if (slot >= klass->vtable_size) {
3927 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3931 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3932 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3933 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3934 g_free (other_name);
3937 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3944 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3947 char *method_signature;
3950 for (index = 0; index < onum; ++index) {
3951 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3952 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3954 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3955 type_name = mono_type_full_name (&klass->byval_arg);
3956 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3957 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3958 g_free (method_signature);
3960 mono_class_setup_methods (klass);
3961 if (mono_class_has_failure (klass)) {
3962 char *name = mono_type_get_full_name (klass);
3963 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3967 mcount = mono_class_get_method_count (klass);
3968 for (index = 0; index < mcount; ++index) {
3969 MonoMethod *cm = klass->methods [index];
3970 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3972 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3973 g_free (method_signature);
3978 mono_method_get_method_definition (MonoMethod *method)
3980 while (method->is_inflated)
3981 method = ((MonoMethodInflated*)method)->declaring;
3986 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3990 for (i = 0; i < onum; ++i) {
3991 MonoMethod *decl = overrides [i * 2];
3992 MonoMethod *body = overrides [i * 2 + 1];
3994 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3995 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3999 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4000 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4001 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4003 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4007 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4008 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4009 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4011 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4015 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4016 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4020 body = mono_method_get_method_definition (body);
4021 decl = mono_method_get_method_definition (decl);
4023 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4024 char *body_name = mono_method_full_name (body, TRUE);
4025 char *decl_name = mono_method_full_name (decl, TRUE);
4026 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4036 mono_class_need_stelemref_method (MonoClass *klass)
4038 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4042 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4045 dslot = mono_method_get_vtable_slot (decl);
4047 mono_class_set_type_load_failure (klass, "");
4051 dslot += mono_class_interface_offset (klass, decl->klass);
4052 vtable [dslot] = override;
4053 if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4055 * If override from an interface, then it is an override of a default interface method,
4056 * don't override its slot.
4058 vtable [dslot]->slot = dslot;
4061 if (mono_security_core_clr_enabled ())
4062 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4068 * LOCKING: this is supposed to be called with the loader lock held.
4071 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4075 MonoMethod **vtable = NULL;
4076 int i, max_vtsize = 0, cur_slot = 0;
4078 GPtrArray *ifaces = NULL;
4079 GHashTable *override_map = NULL;
4081 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4082 int first_non_interface_slot;
4084 GSList *virt_methods = NULL, *l;
4085 int stelemref_slot = 0;
4090 if (overrides && !verify_class_overrides (klass, overrides, onum))
4093 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4094 if (!mono_error_ok (&error)) {
4095 char *name = mono_type_get_full_name (klass);
4096 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4098 mono_error_cleanup (&error);
4100 } else if (ifaces) {
4101 for (i = 0; i < ifaces->len; i++) {
4102 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4103 max_vtsize += mono_class_get_method_count (ic);
4105 g_ptr_array_free (ifaces, TRUE);
4109 if (klass->parent) {
4110 mono_class_init (klass->parent);
4111 mono_class_setup_vtable_full (klass->parent, in_setup);
4113 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4116 max_vtsize += klass->parent->vtable_size;
4117 cur_slot = klass->parent->vtable_size;
4120 max_vtsize += mono_class_get_method_count (klass);
4122 /*Array have a slot for stelemref*/
4123 if (mono_class_need_stelemref_method (klass)) {
4124 stelemref_slot = cur_slot;
4129 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4131 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4132 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4135 max_iid = klass->max_interface_id;
4136 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4138 /* Optimized version for generic instances */
4139 if (mono_class_is_ginst (klass)) {
4141 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4144 mono_class_setup_vtable_full (gklass, in_setup);
4145 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4148 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4149 klass->vtable_size = gklass->vtable_size;
4150 for (i = 0; i < gklass->vtable_size; ++i)
4151 if (gklass->vtable [i]) {
4152 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4153 if (!mono_error_ok (&error)) {
4154 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4155 mono_error_cleanup (&error);
4159 tmp [i]->slot = gklass->vtable [i]->slot;
4161 mono_memory_barrier ();
4162 klass->vtable = tmp;
4164 /* Have to set method->slot for abstract virtual methods */
4165 if (klass->methods && gklass->methods) {
4166 int mcount = mono_class_get_method_count (klass);
4167 for (i = 0; i < mcount; ++i)
4168 if (klass->methods [i]->slot == -1)
4169 klass->methods [i]->slot = gklass->methods [i]->slot;
4175 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4177 if (klass->parent && klass->parent->vtable_size) {
4178 MonoClass *parent = klass->parent;
4181 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4183 // Also inherit parent interface vtables, just as a starting point.
4184 // This is needed otherwise bug-77127.exe fails when the property methods
4185 // have different names in the iterface and the class, because for child
4186 // classes the ".override" information is not used anymore.
4187 for (i = 0; i < parent->interface_offsets_count; i++) {
4188 MonoClass *parent_interface = parent->interfaces_packed [i];
4189 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4190 /*FIXME this is now dead code as this condition will never hold true.
4191 Since interface offsets are inherited then the offset of an interface implemented
4192 by a parent will never be the out of it's vtable boundary.
4194 if (interface_offset >= parent->vtable_size) {
4195 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4198 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4199 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4200 int mcount = mono_class_get_method_count (parent_interface);
4201 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4202 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4203 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4204 parent_interface_offset + j, parent_interface_offset, j,
4205 interface_offset + j, interface_offset, j));
4212 /*Array have a slot for stelemref*/
4213 if (mono_class_need_stelemref_method (klass)) {
4214 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4216 method->slot = stelemref_slot;
4218 g_assert (method->slot == stelemref_slot);
4220 vtable [stelemref_slot] = method;
4223 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4225 /* Process overrides from interface default methods */
4226 // FIXME: Ordering between interfaces
4227 for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4228 ic = klass->interfaces_packed [ifindex];
4230 mono_class_setup_methods (ic);
4231 if (mono_class_has_failure (ic))
4234 MonoMethod **iface_overrides;
4236 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4238 for (int i = 0; i < iface_onum; i++) {
4239 MonoMethod *decl = iface_overrides [i*2];
4240 MonoMethod *override = iface_overrides [i*2 + 1];
4241 if (!apply_override (klass, vtable, decl, override))
4245 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4246 g_hash_table_insert (override_map, decl, override);
4248 g_free (iface_overrides);
4252 /* override interface methods */
4253 for (i = 0; i < onum; i++) {
4254 MonoMethod *decl = overrides [i*2];
4255 MonoMethod *override = overrides [i*2 + 1];
4256 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4257 if (!apply_override (klass, vtable, decl, override))
4261 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4262 g_hash_table_insert (override_map, decl, override);
4266 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4267 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4270 * Create a list of virtual methods to avoid calling
4271 * mono_class_get_virtual_methods () which is slow because of the metadata
4275 gpointer iter = NULL;
4278 virt_methods = NULL;
4279 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4280 virt_methods = g_slist_prepend (virt_methods, cm);
4282 if (mono_class_has_failure (klass))
4286 // Loop on all implemented interfaces...
4287 for (i = 0; i < klass->interface_offsets_count; i++) {
4288 MonoClass *parent = klass->parent;
4290 gboolean interface_is_explicitly_implemented_by_class;
4293 ic = klass->interfaces_packed [i];
4294 ic_offset = mono_class_interface_offset (klass, ic);
4296 mono_class_setup_methods (ic);
4297 if (mono_class_has_failure (ic))
4300 // Check if this interface is explicitly implemented (instead of just inherited)
4301 if (parent != NULL) {
4302 int implemented_interfaces_index;
4303 interface_is_explicitly_implemented_by_class = FALSE;
4304 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4305 if (ic == klass->interfaces [implemented_interfaces_index]) {
4306 interface_is_explicitly_implemented_by_class = TRUE;
4311 interface_is_explicitly_implemented_by_class = TRUE;
4314 // Loop on all interface methods...
4315 int mcount = mono_class_get_method_count (ic);
4316 for (im_index = 0; im_index < mcount; im_index++) {
4317 MonoMethod *im = ic->methods [im_index];
4318 int im_slot = ic_offset + im->slot;
4319 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4321 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4324 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4326 // If there is an explicit implementation, just use it right away,
4327 // otherwise look for a matching method
4328 if (override_im == NULL) {
4332 // First look for a suitable method among the class methods
4333 for (l = virt_methods; l; l = l->next) {
4334 cm = (MonoMethod *)l->data;
4335 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)));
4336 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4337 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4338 vtable [im_slot] = cm;
4339 /* Why do we need this? */
4344 TRACE_INTERFACE_VTABLE (printf ("\n"));
4345 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4349 // If the slot is still empty, look in all the inherited virtual methods...
4350 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4351 MonoClass *parent = klass->parent;
4352 // Reverse order, so that last added methods are preferred
4353 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4354 MonoMethod *cm = parent->vtable [cm_index];
4356 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));
4357 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4358 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4359 vtable [im_slot] = cm;
4360 /* Why do we need this? */
4366 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4368 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4372 if (vtable [im_slot] == NULL) {
4373 if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4374 TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
4375 vtable [im_slot] = im;
4379 g_assert (vtable [im_slot] == override_im);
4384 // If the class is not abstract, check that all its interface slots are full.
4385 // The check is done here and not directly at the end of the loop above because
4386 // it can happen (for injected generic array interfaces) that the same slot is
4387 // processed multiple times (those interfaces have overlapping slots), and it
4388 // will not always be the first pass the one that fills the slot.
4389 if (!mono_class_is_abstract (klass)) {
4390 for (i = 0; i < klass->interface_offsets_count; i++) {
4394 ic = klass->interfaces_packed [i];
4395 ic_offset = mono_class_interface_offset (klass, ic);
4397 int mcount = mono_class_get_method_count (ic);
4398 for (im_index = 0; im_index < mcount; im_index++) {
4399 MonoMethod *im = ic->methods [im_index];
4400 int im_slot = ic_offset + im->slot;
4402 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4405 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4406 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4407 if (vtable [im_slot] == NULL) {
4408 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4415 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4416 for (l = virt_methods; l; l = l->next) {
4417 cm = (MonoMethod *)l->data;
4419 * If the method is REUSE_SLOT, we must check in the
4420 * base class for a method to override.
4422 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4424 for (k = klass->parent; k ; k = k->parent) {
4429 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4430 MonoMethodSignature *cmsig, *m1sig;
4432 cmsig = mono_method_signature (cm);
4433 m1sig = mono_method_signature (m1);
4435 if (!cmsig || !m1sig) {
4436 /* FIXME proper error message */
4437 mono_class_set_type_load_failure (klass, "");
4441 if (!strcmp(cm->name, m1->name) &&
4442 mono_metadata_signature_equal (cmsig, m1sig)) {
4444 if (mono_security_core_clr_enabled ())
4445 mono_security_core_clr_check_override (klass, cm, m1);
4447 slot = mono_method_get_vtable_slot (m1);
4451 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4452 char *body_name = mono_method_full_name (cm, TRUE);
4453 char *decl_name = mono_method_full_name (m1, TRUE);
4454 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4460 g_assert (cm->slot < max_vtsize);
4462 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4463 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4464 mono_method_full_name (m1, 1), m1,
4465 mono_method_full_name (cm, 1), cm));
4466 g_hash_table_insert (override_map, m1, cm);
4470 if (mono_class_has_failure (k))
4480 /*Non final newslot methods must be given a non-interface vtable slot*/
4481 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4485 cm->slot = cur_slot++;
4487 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4488 vtable [cm->slot] = cm;
4491 /* override non interface methods */
4492 for (i = 0; i < onum; i++) {
4493 MonoMethod *decl = overrides [i*2];
4494 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4495 g_assert (decl->slot != -1);
4496 vtable [decl->slot] = overrides [i*2 + 1];
4497 overrides [i * 2 + 1]->slot = decl->slot;
4499 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4500 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4501 mono_method_full_name (decl, 1), decl,
4502 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4503 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4505 if (mono_security_core_clr_enabled ())
4506 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4511 * If a method occupies more than one place in the vtable, and it is
4512 * overriden, then change the other occurances too.
4517 for (i = 0; i < max_vtsize; ++i)
4519 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4521 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4526 g_hash_table_destroy (override_map);
4527 override_map = NULL;
4530 g_slist_free (virt_methods);
4531 virt_methods = NULL;
4533 g_assert (cur_slot <= max_vtsize);
4535 /* Ensure that all vtable slots are filled with concrete instance methods */
4536 if (!mono_class_is_abstract (klass)) {
4537 for (i = 0; i < cur_slot; ++i) {
4538 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4539 char *type_name = mono_type_get_full_name (klass);
4540 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4541 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4543 g_free (method_name);
4550 if (mono_class_is_ginst (klass)) {
4551 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4553 mono_class_init (gklass);
4555 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4557 /* Check that the vtable_size value computed in mono_class_init () is correct */
4558 if (klass->vtable_size)
4559 g_assert (cur_slot == klass->vtable_size);
4560 klass->vtable_size = cur_slot;
4563 /* Try to share the vtable with our parent. */
4564 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4565 mono_memory_barrier ();
4566 klass->vtable = klass->parent->vtable;
4568 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4569 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4570 mono_memory_barrier ();
4571 klass->vtable = tmp;
4574 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4575 if (mono_print_vtable) {
4578 print_implemented_interfaces (klass);
4580 for (i = 0; i <= max_iid; i++)
4581 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4584 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4585 klass->vtable_size, icount);
4587 for (i = 0; i < cur_slot; ++i) {
4592 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4593 mono_method_full_name (cm, TRUE));
4599 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4600 klass->name, max_iid);
4602 for (i = 0; i < klass->interface_count; i++) {
4603 ic = klass->interfaces [i];
4604 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4605 mono_class_interface_offset (klass, ic),
4606 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4609 for (k = klass->parent; k ; k = k->parent) {
4610 for (i = 0; i < k->interface_count; i++) {
4611 ic = k->interfaces [i];
4612 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4613 mono_class_interface_offset (klass, ic),
4614 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4622 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4627 char *name = mono_type_get_full_name (klass);
4628 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4632 g_hash_table_destroy (override_map);
4634 g_slist_free (virt_methods);
4639 * mono_method_get_vtable_slot:
4641 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4642 * LOCKING: Acquires the loader lock.
4644 * FIXME Use proper MonoError machinery here.
4647 mono_method_get_vtable_slot (MonoMethod *method)
4649 if (method->slot == -1) {
4650 mono_class_setup_vtable (method->klass);
4651 if (mono_class_has_failure (method->klass))
4653 if (method->slot == -1) {
4657 if (!mono_class_is_ginst (method->klass)) {
4658 g_assert (method->is_inflated);
4659 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4662 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4663 g_assert (mono_class_is_ginst (method->klass));
4664 gklass = mono_class_get_generic_class (method->klass)->container_class;
4665 mono_class_setup_methods (method->klass);
4666 g_assert (method->klass->methods);
4667 mcount = mono_class_get_method_count (method->klass);
4668 for (i = 0; i < mcount; ++i) {
4669 if (method->klass->methods [i] == method)
4672 g_assert (i < mcount);
4673 g_assert (gklass->methods);
4674 method->slot = gklass->methods [i]->slot;
4676 g_assert (method->slot != -1);
4678 return method->slot;
4682 * mono_method_get_vtable_index:
4683 * \param method a method
4685 * Returns the index into the runtime vtable to access the method or,
4686 * in the case of a virtual generic method, the virtual generic method
4687 * thunk. Returns -1 on failure.
4689 * FIXME Use proper MonoError machinery here.
4692 mono_method_get_vtable_index (MonoMethod *method)
4694 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4695 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4696 if (imethod->declaring->is_generic)
4697 return mono_method_get_vtable_slot (imethod->declaring);
4699 return mono_method_get_vtable_slot (method);
4702 static MonoMethod *default_ghc = NULL;
4703 static MonoMethod *default_finalize = NULL;
4704 static int finalize_slot = -1;
4705 static int ghc_slot = -1;
4708 initialize_object_slots (MonoClass *klass)
4713 if (klass == mono_defaults.object_class) {
4714 mono_class_setup_vtable (klass);
4715 for (i = 0; i < klass->vtable_size; ++i) {
4716 MonoMethod *cm = klass->vtable [i];
4718 if (!strcmp (cm->name, "GetHashCode"))
4720 else if (!strcmp (cm->name, "Finalize"))
4724 g_assert (ghc_slot > 0);
4725 default_ghc = klass->vtable [ghc_slot];
4727 g_assert (finalize_slot > 0);
4728 default_finalize = klass->vtable [finalize_slot];
4733 MonoMethod *array_method;
4735 } GenericArrayMethodInfo;
4737 static int generic_array_method_num = 0;
4738 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4741 generic_array_methods (MonoClass *klass)
4743 int i, count_generic = 0, mcount;
4744 GList *list = NULL, *tmp;
4745 if (generic_array_method_num)
4746 return generic_array_method_num;
4747 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4748 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4749 mcount = mono_class_get_method_count (klass->parent);
4750 for (i = 0; i < mcount; i++) {
4751 MonoMethod *m = klass->parent->methods [i];
4752 if (!strncmp (m->name, "InternalArray__", 15)) {
4754 list = g_list_prepend (list, m);
4757 list = g_list_reverse (list);
4758 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4760 for (tmp = list; tmp; tmp = tmp->next) {
4761 const char *mname, *iname;
4763 MonoMethod *m = (MonoMethod *)tmp->data;
4764 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4765 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4767 generic_array_method_info [i].array_method = m;
4768 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4769 iname = "System.Collections.Generic.ICollection`1.";
4770 mname = m->name + 27;
4771 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4772 iname = "System.Collections.Generic.IEnumerable`1.";
4773 mname = m->name + 27;
4774 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4775 iname = "System.Collections.Generic.IReadOnlyList`1.";
4776 mname = m->name + strlen (ireadonlylist_prefix);
4777 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4778 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4779 mname = m->name + strlen (ireadonlycollection_prefix);
4780 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4781 iname = "System.Collections.Generic.IList`1.";
4782 mname = m->name + 15;
4784 g_assert_not_reached ();
4787 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4788 strcpy (name, iname);
4789 strcpy (name + strlen (iname), mname);
4790 generic_array_method_info [i].name = name;
4793 /*g_print ("array generic methods: %d\n", count_generic);*/
4795 generic_array_method_num = count_generic;
4797 return generic_array_method_num;
4801 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4803 MonoGenericContext tmp_context;
4806 tmp_context.class_inst = NULL;
4807 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4808 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4810 for (i = 0; i < generic_array_method_num; i++) {
4812 MonoMethod *m = generic_array_method_info [i].array_method;
4813 MonoMethod *inflated, *helper;
4815 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4816 mono_error_assert_ok (&error);
4817 helper = g_hash_table_lookup (cache, inflated);
4819 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4820 g_hash_table_insert (cache, inflated, helper);
4822 methods [pos ++] = helper;
4827 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4829 int null_length = strlen ("(null)");
4830 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4831 char *s = (char *)mono_image_alloc (image, len);
4834 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4835 g_assert (result == len - 1);
4842 * \param klass the class to initialize
4844 * Compute the \c instance_size, \c class_size and other infos that cannot be
4845 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4846 * Initializes the following fields in \p klass:
4847 * - all the fields initialized by \c mono_class_init_sizes
4852 * LOCKING: Acquires the loader lock.
4854 * \returns TRUE on success or FALSE if there was a problem in loading
4855 * the type (incorrect assemblies, missing assemblies, methods, etc).
4858 mono_class_init (MonoClass *klass)
4860 int i, vtable_size = 0, array_method_count = 0;
4861 MonoCachedClassInfo cached_info;
4862 gboolean has_cached_info;
4863 gboolean locked = FALSE;
4864 gboolean ghcimpl = FALSE;
4865 gboolean has_cctor = FALSE;
4866 int first_iface_slot = 0;
4870 /* Double-checking locking pattern */
4871 if (klass->inited || mono_class_has_failure (klass))
4872 return !mono_class_has_failure (klass);
4874 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4877 * This function can recursively call itself.
4879 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4880 if (g_slist_find (init_list, klass)) {
4881 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4884 init_list = g_slist_prepend (init_list, klass);
4885 mono_native_tls_set_value (init_pending_tls_id, init_list);
4888 * We want to avoid doing complicated work inside locks, so we compute all the required
4889 * information and write it to @klass inside a lock.
4892 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4893 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4897 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4898 MonoClass *element_class = klass->element_class;
4899 if (!element_class->inited)
4900 mono_class_init (element_class);
4901 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4905 mono_stats.initialized_class_count++;
4907 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4908 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4910 mono_class_init (gklass);
4911 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4914 mono_class_setup_interface_id (klass);
4917 if (klass->parent && !klass->parent->inited)
4918 mono_class_init (klass->parent);
4920 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4922 /* Compute instance size etc. */
4923 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4924 if (mono_class_has_failure (klass))
4927 mono_class_setup_supertypes (klass);
4930 initialize_object_slots (klass);
4933 * Initialize the rest of the data without creating a generic vtable if possible.
4934 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4935 * also avoid computing a generic vtable.
4937 if (has_cached_info) {
4939 vtable_size = cached_info.vtable_size;
4940 ghcimpl = cached_info.ghcimpl;
4941 has_cctor = cached_info.has_cctor;
4942 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4943 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4944 * The first slot if for array with.
4946 static int szarray_vtable_size[2] = { 0 };
4948 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4951 if (!szarray_vtable_size [slot]) {
4952 mono_class_setup_vtable (klass);
4953 szarray_vtable_size [slot] = klass->vtable_size;
4954 vtable_size = klass->vtable_size;
4956 vtable_size = szarray_vtable_size[slot];
4958 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4959 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4961 /* Generic instance case */
4962 ghcimpl = gklass->ghcimpl;
4963 has_cctor = gklass->has_cctor;
4965 mono_class_setup_vtable (gklass);
4966 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4969 vtable_size = gklass->vtable_size;
4973 /* ghcimpl is not currently used
4975 if (klass->parent) {
4976 MonoMethod *cmethod = klass->vtable [ghc_slot];
4977 if (cmethod->is_inflated)
4978 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4979 if (cmethod == default_ghc) {
4985 /* C# doesn't allow interfaces to have cctors */
4986 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4987 MonoMethod *cmethod = NULL;
4989 if (mono_class_is_ginst (klass)) {
4990 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4992 /* Generic instance case */
4993 ghcimpl = gklass->ghcimpl;
4994 has_cctor = gklass->has_cctor;
4995 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4996 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4997 /* The find_method function ignores the 'flags' argument */
4998 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5001 mono_class_setup_methods (klass);
5002 if (mono_class_has_failure (klass))
5005 int mcount = mono_class_get_method_count (klass);
5006 for (i = 0; i < mcount; ++i) {
5007 MonoMethod *method = klass->methods [i];
5008 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5009 (strcmp (".cctor", method->name) == 0)) {
5019 array_method_count = 3 + (klass->rank > 1? 2: 1);
5021 if (klass->interface_count) {
5022 int count_generic = generic_array_methods (klass);
5023 array_method_count += klass->interface_count * count_generic;
5027 if (klass->parent) {
5028 if (!klass->parent->vtable_size)
5029 mono_class_setup_vtable (klass->parent);
5030 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5032 g_assert (klass->parent->vtable_size);
5033 first_iface_slot = klass->parent->vtable_size;
5034 if (mono_class_need_stelemref_method (klass))
5039 * Do the actual changes to @klass inside the loader lock
5041 mono_loader_lock ();
5044 if (klass->inited || mono_class_has_failure (klass)) {
5045 mono_loader_unlock ();
5046 /* Somebody might have gotten in before us */
5047 return !mono_class_has_failure (klass);
5050 mono_stats.initialized_class_count++;
5052 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5053 mono_stats.generic_class_count++;
5055 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5056 klass->nested_classes_inited = TRUE;
5057 klass->ghcimpl = ghcimpl;
5058 klass->has_cctor = has_cctor;
5060 klass->vtable_size = vtable_size;
5061 if (has_cached_info) {
5062 klass->has_finalize = cached_info.has_finalize;
5063 klass->has_finalize_inited = TRUE;
5066 mono_class_set_method_count (klass, array_method_count);
5068 mono_loader_unlock ();
5071 setup_interface_offsets (klass, first_iface_slot, TRUE);
5073 if (mono_security_core_clr_enabled ())
5074 mono_security_core_clr_check_inheritance (klass);
5076 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5077 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5082 init_list = g_slist_remove (init_list, klass);
5083 mono_native_tls_set_value (init_pending_tls_id, init_list);
5086 mono_loader_unlock ();
5088 /* Leave this for last */
5089 mono_loader_lock ();
5091 mono_loader_unlock ();
5093 return !mono_class_has_failure (klass);
5097 * mono_class_has_finalizer:
5099 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5103 mono_class_has_finalizer (MonoClass *klass)
5105 gboolean has_finalize = FALSE;
5107 if (klass->has_finalize_inited)
5108 return klass->has_finalize;
5110 /* Interfaces and valuetypes are not supposed to have finalizers */
5111 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5112 MonoMethod *cmethod = NULL;
5114 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5115 } else if (mono_class_is_ginst (klass)) {
5116 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5118 has_finalize = mono_class_has_finalizer (gklass);
5119 } else if (klass->parent && klass->parent->has_finalize) {
5120 has_finalize = TRUE;
5122 if (klass->parent) {
5124 * Can't search in metadata for a method named Finalize, because that
5125 * ignores overrides.
5127 mono_class_setup_vtable (klass);
5128 if (mono_class_has_failure (klass))
5131 cmethod = klass->vtable [finalize_slot];
5135 g_assert (klass->vtable_size > finalize_slot);
5137 if (klass->parent) {
5138 if (cmethod->is_inflated)
5139 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5140 if (cmethod != default_finalize)
5141 has_finalize = TRUE;
5147 mono_loader_lock ();
5148 if (!klass->has_finalize_inited) {
5149 klass->has_finalize = has_finalize ? 1 : 0;
5151 mono_memory_barrier ();
5152 klass->has_finalize_inited = TRUE;
5154 mono_loader_unlock ();
5156 return klass->has_finalize;
5160 mono_is_corlib_image (MonoImage *image)
5162 return image == mono_defaults.corlib;
5166 * LOCKING: this assumes the loader lock is held
5169 mono_class_setup_mono_type (MonoClass *klass)
5171 const char *name = klass->name;
5172 const char *nspace = klass->name_space;
5173 gboolean is_corlib = mono_is_corlib_image (klass->image);
5175 klass->this_arg.byref = 1;
5176 klass->this_arg.data.klass = klass;
5177 klass->this_arg.type = MONO_TYPE_CLASS;
5178 klass->byval_arg.data.klass = klass;
5179 klass->byval_arg.type = MONO_TYPE_CLASS;
5181 if (is_corlib && !strcmp (nspace, "System")) {
5182 if (!strcmp (name, "ValueType")) {
5184 * do not set the valuetype bit for System.ValueType.
5185 * klass->valuetype = 1;
5187 klass->blittable = TRUE;
5188 } else if (!strcmp (name, "Enum")) {
5190 * do not set the valuetype bit for System.Enum.
5191 * klass->valuetype = 1;
5193 klass->valuetype = 0;
5194 klass->enumtype = 0;
5195 } else if (!strcmp (name, "Object")) {
5196 klass->byval_arg.type = MONO_TYPE_OBJECT;
5197 klass->this_arg.type = MONO_TYPE_OBJECT;
5198 } else if (!strcmp (name, "String")) {
5199 klass->byval_arg.type = MONO_TYPE_STRING;
5200 klass->this_arg.type = MONO_TYPE_STRING;
5201 } else if (!strcmp (name, "TypedReference")) {
5202 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5203 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5207 if (klass->valuetype) {
5208 int t = MONO_TYPE_VALUETYPE;
5210 if (is_corlib && !strcmp (nspace, "System")) {
5213 if (!strcmp (name, "Boolean")) {
5214 t = MONO_TYPE_BOOLEAN;
5215 } else if (!strcmp(name, "Byte")) {
5217 klass->blittable = TRUE;
5221 if (!strcmp (name, "Char")) {
5226 if (!strcmp (name, "Double")) {
5228 klass->blittable = TRUE;
5232 if (!strcmp (name, "Int32")) {
5234 klass->blittable = TRUE;
5235 } else if (!strcmp(name, "Int16")) {
5237 klass->blittable = TRUE;
5238 } else if (!strcmp(name, "Int64")) {
5240 klass->blittable = TRUE;
5241 } else if (!strcmp(name, "IntPtr")) {
5243 klass->blittable = TRUE;
5247 if (!strcmp (name, "Single")) {
5249 klass->blittable = TRUE;
5250 } else if (!strcmp(name, "SByte")) {
5252 klass->blittable = TRUE;
5256 if (!strcmp (name, "UInt32")) {
5258 klass->blittable = TRUE;
5259 } else if (!strcmp(name, "UInt16")) {
5261 klass->blittable = TRUE;
5262 } else if (!strcmp(name, "UInt64")) {
5264 klass->blittable = TRUE;
5265 } else if (!strcmp(name, "UIntPtr")) {
5267 klass->blittable = TRUE;
5271 if (!strcmp (name, "TypedReference")) {
5272 t = MONO_TYPE_TYPEDBYREF;
5273 klass->blittable = TRUE;
5277 if (!strcmp (name, "Void")) {
5285 klass->byval_arg.type = (MonoTypeEnum)t;
5286 klass->this_arg.type = (MonoTypeEnum)t;
5289 if (MONO_CLASS_IS_INTERFACE (klass)) {
5290 klass->interface_id = mono_get_unique_iid (klass);
5292 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5293 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5294 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5295 * MS returns diferrent types based on which instance is called. For example:
5296 * object obj = new byte[10][];
5297 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5298 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5301 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5302 klass->is_array_special_interface = 1;
5309 * COM initialization is delayed until needed.
5310 * However when a [ComImport] attribute is present on a type it will trigger
5311 * the initialization. This is not a problem unless the BCL being executed
5312 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5315 init_com_from_comimport (MonoClass *klass)
5317 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5318 if (mono_security_core_clr_enabled ()) {
5319 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5320 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5321 /* but it can not be made available for application (i.e. user code) since all COM calls
5322 * are considered native calls. In this case we fail with a TypeLoadException (just like
5323 * Silverlight 2 does */
5324 mono_class_set_type_load_failure (klass, "");
5329 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5331 #endif /*DISABLE_COM*/
5334 * LOCKING: this assumes the loader lock is held
5337 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5339 gboolean system_namespace;
5340 gboolean is_corlib = mono_is_corlib_image (klass->image);
5342 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5344 /* if root of the hierarchy */
5345 if (system_namespace && !strcmp (klass->name, "Object")) {
5346 klass->parent = NULL;
5347 klass->instance_size = sizeof (MonoObject);
5350 if (!strcmp (klass->name, "<Module>")) {
5351 klass->parent = NULL;
5352 klass->instance_size = 0;
5356 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5357 /* Imported COM Objects always derive from __ComObject. */
5359 if (MONO_CLASS_IS_IMPORT (klass)) {
5360 init_com_from_comimport (klass);
5361 if (parent == mono_defaults.object_class)
5362 parent = mono_class_get_com_object_class ();
5366 /* set the parent to something useful and safe, but mark the type as broken */
5367 parent = mono_defaults.object_class;
5368 mono_class_set_type_load_failure (klass, "");
5372 klass->parent = parent;
5374 if (mono_class_is_ginst (parent) && !parent->name) {
5376 * If the parent is a generic instance, we may get
5377 * called before it is fully initialized, especially
5378 * before it has its name.
5383 #ifndef DISABLE_REMOTING
5384 klass->marshalbyref = parent->marshalbyref;
5385 klass->contextbound = parent->contextbound;
5388 klass->delegate = parent->delegate;
5390 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5391 mono_class_set_is_com_object (klass);
5393 if (system_namespace) {
5394 #ifndef DISABLE_REMOTING
5395 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5396 klass->marshalbyref = 1;
5398 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5399 klass->contextbound = 1;
5401 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5402 klass->delegate = 1;
5405 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5406 (strcmp (klass->parent->name_space, "System") == 0)))
5407 klass->valuetype = 1;
5408 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5409 klass->valuetype = klass->enumtype = 1;
5411 /*klass->enumtype = klass->parent->enumtype; */
5413 /* initialize com types if COM interfaces are present */
5415 if (MONO_CLASS_IS_IMPORT (klass))
5416 init_com_from_comimport (klass);
5418 klass->parent = NULL;
5424 * mono_class_setup_supertypes:
5427 * Build the data structure needed to make fast type checks work.
5428 * This currently sets two fields in @class:
5429 * - idepth: distance between @class and System.Object in the type
5431 * - supertypes: array of classes: each element has a class in the hierarchy
5432 * starting from @class up to System.Object
5434 * LOCKING: Acquires the loader lock.
5437 mono_class_setup_supertypes (MonoClass *klass)
5440 MonoClass **supertypes;
5442 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5446 if (klass->parent && !klass->parent->supertypes)
5447 mono_class_setup_supertypes (klass->parent);
5449 idepth = klass->parent->idepth + 1;
5453 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5454 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5456 if (klass->parent) {
5457 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5460 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5461 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5463 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5466 mono_memory_barrier ();
5468 mono_loader_lock ();
5469 klass->idepth = idepth;
5470 /* Needed so idepth is visible before supertypes is set */
5471 mono_memory_barrier ();
5472 klass->supertypes = supertypes;
5473 mono_loader_unlock ();
5477 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5479 return mono_class_get_generic_class (gclass)->container_class == user_data;
5483 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5485 MonoClass *gtd = (MonoClass*)user_data;
5486 /* Only try to fix generic instances of @gtd */
5487 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5490 /* Check if the generic instance has no parent. */
5491 if (gtd->parent && !gclass->parent)
5492 mono_generic_class_setup_parent (gclass, gtd);
5498 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5500 mono_class_set_type_load_failure (klass, "%s", msg);
5501 mono_error_set_type_load_class (error, klass, "%s", msg);
5505 * mono_class_create_from_typedef:
5506 * \param image: image where the token is valid
5507 * \param type_token: typedef token
5508 * \param error: used to return any error found while creating the type
5510 * Create the MonoClass* representing the specified type token.
5511 * \p type_token must be a TypeDef token.
5513 * FIXME: don't return NULL on failure, just the the caller figure it out.
5516 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5518 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5519 MonoClass *klass, *parent = NULL;
5520 guint32 cols [MONO_TYPEDEF_SIZE];
5521 guint32 cols_next [MONO_TYPEDEF_SIZE];
5522 guint tidx = mono_metadata_token_index (type_token);
5523 MonoGenericContext *context = NULL;
5524 const char *name, *nspace;
5526 MonoClass **interfaces;
5527 guint32 field_last, method_last;
5528 guint32 nesting_tokeen;
5532 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5533 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5537 mono_loader_lock ();
5539 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5540 mono_loader_unlock ();
5544 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5546 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5547 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5549 if (mono_metadata_has_generic_params (image, type_token)) {
5550 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5551 klass->class_kind = MONO_CLASS_GTD;
5552 classes_size += sizeof (MonoClassGtd);
5555 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5556 klass->class_kind = MONO_CLASS_DEF;
5557 classes_size += sizeof (MonoClassDef);
5562 klass->name_space = nspace;
5564 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5566 klass->image = image;
5567 klass->type_token = type_token;
5568 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5570 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5573 * Check whether we're a generic type definition.
5575 if (mono_class_is_gtd (klass)) {
5576 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5577 generic_container->owner.klass = klass;
5578 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5579 context = &generic_container->context;
5580 mono_class_set_generic_container (klass, generic_container);
5581 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5582 canonical_inst->type = MONO_TYPE_GENERICINST;
5583 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5584 enable_gclass_recording ();
5587 if (cols [MONO_TYPEDEF_EXTENDS]) {
5589 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5591 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5592 /*WARNING: this must satisfy mono_metadata_type_hash*/
5593 klass->this_arg.byref = 1;
5594 klass->this_arg.data.klass = klass;
5595 klass->this_arg.type = MONO_TYPE_CLASS;
5596 klass->byval_arg.data.klass = klass;
5597 klass->byval_arg.type = MONO_TYPE_CLASS;
5599 parent = mono_class_get_checked (image, parent_token, error);
5600 if (parent && context) /* Always inflate */
5601 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5603 if (parent == NULL) {
5604 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5605 goto parent_failure;
5608 for (tmp = parent; tmp; tmp = tmp->parent) {
5610 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5611 goto parent_failure;
5613 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5614 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5615 goto parent_failure;
5620 mono_class_setup_parent (klass, parent);
5622 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5623 mono_class_setup_mono_type (klass);
5625 if (mono_class_is_gtd (klass))
5626 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5629 * This might access klass->byval_arg for recursion generated by generic constraints,
5630 * so it has to come after setup_mono_type ().
5632 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5633 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5634 if (!mono_error_ok (error)) {
5635 /*FIXME implement a mono_class_set_failure_from_mono_error */
5636 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5637 mono_loader_unlock ();
5638 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5643 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5647 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5651 klass->cast_class = klass->element_class = klass;
5652 if (mono_is_corlib_image (klass->image)) {
5653 switch (klass->byval_arg.type) {
5655 if (mono_defaults.byte_class)
5656 klass->cast_class = mono_defaults.byte_class;
5659 if (mono_defaults.sbyte_class)
5660 mono_defaults.sbyte_class = klass;
5663 if (mono_defaults.uint16_class)
5664 mono_defaults.uint16_class = klass;
5667 if (mono_defaults.int16_class)
5668 klass->cast_class = mono_defaults.int16_class;
5671 if (mono_defaults.uint32_class)
5672 mono_defaults.uint32_class = klass;
5675 if (mono_defaults.int32_class)
5676 klass->cast_class = mono_defaults.int32_class;
5679 if (mono_defaults.uint64_class)
5680 mono_defaults.uint64_class = klass;
5683 if (mono_defaults.int64_class)
5684 klass->cast_class = mono_defaults.int64_class;
5689 if (!klass->enumtype) {
5690 if (!mono_metadata_interfaces_from_typedef_full (
5691 image, type_token, &interfaces, &icount, FALSE, context, error)){
5693 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5694 mono_loader_unlock ();
5695 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5699 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5700 g_assert(icount <= 65535);
5702 klass->interfaces = interfaces;
5703 klass->interface_count = icount;
5704 klass->interfaces_inited = 1;
5707 /*g_print ("Load class %s\n", name);*/
5710 * Compute the field and method lists
5712 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5713 mono_class_set_first_field_idx (klass, first_field_idx);
5714 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5715 mono_class_set_first_method_idx (klass, first_method_idx);
5717 if (tt->rows > tidx){
5718 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5719 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5720 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5722 field_last = image->tables [MONO_TABLE_FIELD].rows;
5723 method_last = image->tables [MONO_TABLE_METHOD].rows;
5726 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5727 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5728 mono_class_set_field_count (klass, field_last - first_field_idx);
5729 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5730 mono_class_set_method_count (klass, method_last - first_method_idx);
5732 /* reserve space to store vector pointer in arrays */
5733 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5734 klass->instance_size += 2 * sizeof (gpointer);
5735 g_assert (mono_class_get_field_count (klass) == 0);
5738 if (klass->enumtype) {
5739 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5740 if (!enum_basetype) {
5741 /*set it to a default value as the whole runtime can't handle this to be null*/
5742 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5743 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5744 mono_loader_unlock ();
5745 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5748 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5752 * If we're a generic type definition, load the constraints.
5753 * We must do this after the class has been constructed to make certain recursive scenarios
5756 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5757 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5758 mono_loader_unlock ();
5759 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5763 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5764 if (!strncmp (name, "Vector", 6))
5765 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");
5766 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5767 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5768 klass->simd_type = 1;
5771 mono_loader_unlock ();
5773 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5778 if (mono_class_is_gtd (klass))
5779 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5781 mono_class_setup_mono_type (klass);
5782 mono_loader_unlock ();
5783 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5787 /** Is klass a Nullable<T> ginst? */
5789 mono_class_is_nullable (MonoClass *klass)
5791 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5792 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5796 /** if klass is T? return T */
5798 mono_class_get_nullable_param (MonoClass *klass)
5800 g_assert (mono_class_is_nullable (klass));
5801 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5805 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5809 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5811 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5812 if (!mono_error_ok (&error)) {
5813 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5814 klass->parent = mono_defaults.object_class;
5815 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5816 mono_error_cleanup (&error);
5819 mono_loader_lock ();
5821 mono_class_setup_parent (klass, klass->parent);
5823 if (klass->enumtype) {
5824 klass->cast_class = gtd->cast_class;
5825 klass->element_class = gtd->element_class;
5827 mono_loader_unlock ();
5831 mono_type_is_primitive (MonoType *type)
5833 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5834 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5838 * Create the `MonoClass' for an instantiation of a generic type.
5839 * We only do this if we actually need it.
5842 mono_generic_class_get_class (MonoGenericClass *gclass)
5844 MonoClass *klass, *gklass;
5846 if (gclass->cached_class)
5847 return gclass->cached_class;
5849 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5851 gklass = gclass->container_class;
5853 if (gklass->nested_in) {
5854 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5855 klass->nested_in = gklass->nested_in;
5858 klass->name = gklass->name;
5859 klass->name_space = gklass->name_space;
5861 klass->image = gklass->image;
5862 klass->type_token = gklass->type_token;
5864 klass->class_kind = MONO_CLASS_GINST;
5866 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5868 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5869 klass->this_arg.type = klass->byval_arg.type;
5870 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5871 klass->this_arg.byref = TRUE;
5872 klass->enumtype = gklass->enumtype;
5873 klass->valuetype = gklass->valuetype;
5876 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5877 g_assert (gclass->context.class_inst);
5878 g_assert (gclass->context.class_inst->type_argc > 0);
5879 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5880 klass->simd_type = 1;
5882 klass->is_array_special_interface = gklass->is_array_special_interface;
5884 klass->cast_class = klass->element_class = klass;
5886 if (gclass->is_dynamic) {
5888 * 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.
5889 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5890 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5892 if (!gklass->wastypebuilder)
5895 if (klass->enumtype) {
5897 * For enums, gklass->fields might not been set, but instance_size etc. is
5898 * already set in mono_reflection_create_internal_class (). For non-enums,
5899 * these will be computed normally in mono_class_layout_fields ().
5901 klass->instance_size = gklass->instance_size;
5902 klass->sizes.class_size = gklass->sizes.class_size;
5903 klass->size_inited = 1;
5907 mono_loader_lock ();
5909 if (gclass->cached_class) {
5910 mono_loader_unlock ();
5911 return gclass->cached_class;
5914 if (record_gclass_instantiation > 0)
5915 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5917 if (mono_class_is_nullable (klass))
5918 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5920 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5922 mono_generic_class_setup_parent (klass, gklass);
5924 if (gclass->is_dynamic)
5925 mono_class_setup_supertypes (klass);
5927 mono_memory_barrier ();
5928 gclass->cached_class = klass;
5930 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5932 ++class_ginst_count;
5933 inflated_classes_size += sizeof (MonoClassGenericInst);
5935 mono_loader_unlock ();
5941 get_image_for_container (MonoGenericContainer *container)
5944 if (container->is_anonymous) {
5945 result = container->owner.image;
5948 if (container->is_method) {
5949 MonoMethod *method = container->owner.method;
5950 g_assert_checked (method);
5951 klass = method->klass;
5953 klass = container->owner.klass;
5955 g_assert_checked (klass);
5956 result = klass->image;
5963 get_image_for_generic_param (MonoGenericParam *param)
5965 MonoGenericContainer *container = mono_generic_param_owner (param);
5966 g_assert_checked (container);
5967 return get_image_for_container (container);
5970 // Make a string in the designated image consisting of a single integer.
5971 #define INT_STRING_SIZE 16
5973 make_generic_name_string (MonoImage *image, int num)
5975 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5976 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5980 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5981 // pinfo is derived from param by the caller for us.
5983 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5985 MonoClass *klass, **ptr;
5987 MonoGenericContainer *container = mono_generic_param_owner (param);
5988 g_assert_checked (container);
5990 MonoImage *image = get_image_for_container (container);
5991 gboolean is_mvar = container->is_method;
5992 gboolean is_anonymous = container->is_anonymous;
5994 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5995 klass->class_kind = MONO_CLASS_GPARAM;
5996 classes_size += sizeof (MonoClassGenericParam);
5997 ++class_gparam_count;
6000 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6002 int n = mono_generic_param_num (param);
6003 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6007 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6008 } else if (is_mvar) {
6009 MonoMethod *omethod = container->owner.method;
6010 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6012 MonoClass *oklass = container->owner.klass;
6013 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6016 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6018 // Count non-NULL items in pinfo->constraints
6021 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6025 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6026 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6028 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6029 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6031 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6034 if (count - pos > 0) {
6035 klass->interface_count = count - pos;
6036 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6037 klass->interfaces_inited = TRUE;
6038 for (i = pos; i < count; i++)
6039 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6042 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6044 klass->inited = TRUE;
6045 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6046 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6048 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6049 klass->this_arg.type = klass->byval_arg.type;
6050 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6051 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6052 klass->this_arg.byref = TRUE;
6054 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6055 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6057 /*Init these fields to sane values*/
6058 klass->min_align = 1;
6060 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6061 * constrained to, the JIT depends on this.
6063 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6064 mono_memory_barrier ();
6065 klass->size_inited = 1;
6067 mono_class_setup_supertypes (klass);
6069 if (count - pos > 0) {
6070 mono_class_setup_vtable (klass->parent);
6071 if (mono_class_has_failure (klass->parent))
6072 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6074 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6080 #define FAST_CACHE_SIZE 16
6083 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6084 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6085 * we cache the MonoClasses.
6086 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6087 * LOCKING: Takes the image lock depending on @take_lock.
6090 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6092 int n = mono_generic_param_num (param);
6093 MonoImage *image = get_image_for_generic_param (param);
6094 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6095 MonoClass *klass = NULL;
6100 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6101 // For high numbers or constraints we have to use pointer hashes.
6102 if (param->gshared_constraint) {
6103 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6106 mono_image_lock (image);
6107 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6109 mono_image_unlock (image);
6114 if (n < FAST_CACHE_SIZE) {
6116 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6118 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6120 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6123 mono_image_lock (image);
6124 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6126 mono_image_unlock (image);
6133 * LOCKING: Image lock (param->image) must be held
6136 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6138 int n = mono_generic_param_num (param);
6139 MonoImage *image = get_image_for_generic_param (param);
6140 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6144 if (param->gshared_constraint) {
6145 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6147 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6148 mono_memory_barrier ();
6150 image->mvar_cache_constrained = ht;
6152 image->var_cache_constrained = ht;
6154 g_hash_table_insert (ht, param, klass);
6155 } else if (n < FAST_CACHE_SIZE) {
6157 /* Requires locking to avoid droping an already published class */
6158 if (!image->mvar_cache_fast)
6159 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6160 image->mvar_cache_fast [n] = klass;
6162 if (!image->var_cache_fast)
6163 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6164 image->var_cache_fast [n] = klass;
6167 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6169 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6171 ht = g_hash_table_new (NULL, NULL);
6172 mono_memory_barrier ();
6174 image->mvar_cache_slow = ht;
6176 image->var_cache_slow = ht;
6179 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6184 * LOCKING: Acquires the image lock (@image).
6187 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6189 MonoImage *image = get_image_for_generic_param (param);
6190 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6191 MonoClass *klass, *klass2;
6193 // If a klass already exists for this object and is cached, return it.
6194 if (pinfo) // Non-anonymous
6195 klass = pinfo->pklass;
6197 klass = get_anon_gparam_class (param, TRUE);
6202 // Create a new klass
6203 klass = make_generic_param_class (param, pinfo);
6205 // Now we need to cache the klass we created.
6206 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6207 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6208 // and allow our newly-created klass object to just leak.
6209 mono_memory_barrier ();
6211 mono_image_lock (image);
6213 // Here "klass2" refers to the klass potentially created by the other thread.
6214 if (pinfo) // Repeat check from above
6215 klass2 = pinfo->pklass;
6217 klass2 = get_anon_gparam_class (param, FALSE);
6224 pinfo->pklass = klass;
6226 set_anon_gparam_class (param, klass);
6228 mono_image_unlock (image);
6230 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6232 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6234 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6240 * mono_class_from_generic_parameter:
6241 * \param param Parameter to find/construct a class for.
6242 * \param arg2 Is ignored.
6243 * \param arg3 Is ignored.
6246 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6248 return mono_class_from_generic_parameter_internal (param);
6252 * mono_ptr_class_get:
6255 mono_ptr_class_get (MonoType *type)
6258 MonoClass *el_class;
6262 el_class = mono_class_from_mono_type (type);
6263 image = el_class->image;
6265 mono_image_lock (image);
6266 if (image->ptr_cache) {
6267 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6268 mono_image_unlock (image);
6272 mono_image_unlock (image);
6274 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6276 classes_size += sizeof (MonoClassPointer);
6277 ++class_pointer_count;
6279 result->parent = NULL; /* no parent for PTR types */
6280 result->name_space = el_class->name_space;
6281 name = g_strdup_printf ("%s*", el_class->name);
6282 result->name = mono_image_strdup (image, name);
6283 result->class_kind = MONO_CLASS_POINTER;
6286 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6288 result->image = el_class->image;
6289 result->inited = TRUE;
6290 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6291 result->cast_class = result->element_class = el_class;
6292 result->blittable = TRUE;
6294 result->byval_arg.type = MONO_TYPE_PTR;
6295 result->this_arg.type = result->byval_arg.type;
6296 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6297 result->this_arg.byref = TRUE;
6299 mono_class_setup_supertypes (result);
6301 mono_image_lock (image);
6302 if (image->ptr_cache) {
6304 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6305 mono_image_unlock (image);
6306 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6310 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6312 g_hash_table_insert (image->ptr_cache, el_class, result);
6313 mono_image_unlock (image);
6315 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6321 mono_fnptr_class_get (MonoMethodSignature *sig)
6323 MonoClass *result, *cached;
6324 static GHashTable *ptr_hash = NULL;
6326 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6328 mono_loader_lock ();
6330 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6331 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6332 mono_loader_unlock ();
6336 result = g_new0 (MonoClass, 1);
6338 result->parent = NULL; /* no parent for PTR types */
6339 result->name_space = "System";
6340 result->name = "MonoFNPtrFakeClass";
6341 result->class_kind = MONO_CLASS_POINTER;
6343 result->image = mono_defaults.corlib; /* need to fix... */
6344 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6345 result->cast_class = result->element_class = result;
6346 result->byval_arg.type = MONO_TYPE_FNPTR;
6347 result->this_arg.type = result->byval_arg.type;
6348 result->this_arg.data.method = result->byval_arg.data.method = sig;
6349 result->this_arg.byref = TRUE;
6350 result->blittable = TRUE;
6351 result->inited = TRUE;
6353 mono_class_setup_supertypes (result);
6355 mono_loader_lock ();
6357 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6360 mono_loader_unlock ();
6364 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6366 classes_size += sizeof (MonoClassPointer);
6367 ++class_pointer_count;
6369 g_hash_table_insert (ptr_hash, sig, result);
6371 mono_loader_unlock ();
6373 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6379 * mono_class_from_mono_type:
6380 * \param type describes the type to return
6381 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6384 mono_class_from_mono_type (MonoType *type)
6386 switch (type->type) {
6387 case MONO_TYPE_OBJECT:
6388 return type->data.klass? type->data.klass: mono_defaults.object_class;
6389 case MONO_TYPE_VOID:
6390 return type->data.klass? type->data.klass: mono_defaults.void_class;
6391 case MONO_TYPE_BOOLEAN:
6392 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6393 case MONO_TYPE_CHAR:
6394 return type->data.klass? type->data.klass: mono_defaults.char_class;
6396 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6398 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6400 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6402 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6404 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6406 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6408 return type->data.klass? type->data.klass: mono_defaults.int_class;
6410 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6412 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6414 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6416 return type->data.klass? type->data.klass: mono_defaults.single_class;
6418 return type->data.klass? type->data.klass: mono_defaults.double_class;
6419 case MONO_TYPE_STRING:
6420 return type->data.klass? type->data.klass: mono_defaults.string_class;
6421 case MONO_TYPE_TYPEDBYREF:
6422 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6423 case MONO_TYPE_ARRAY:
6424 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6426 return mono_ptr_class_get (type->data.type);
6427 case MONO_TYPE_FNPTR:
6428 return mono_fnptr_class_get (type->data.method);
6429 case MONO_TYPE_SZARRAY:
6430 return mono_array_class_get (type->data.klass, 1);
6431 case MONO_TYPE_CLASS:
6432 case MONO_TYPE_VALUETYPE:
6433 return type->data.klass;
6434 case MONO_TYPE_GENERICINST:
6435 return mono_generic_class_get_class (type->data.generic_class);
6436 case MONO_TYPE_MVAR:
6438 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6440 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6441 g_assert_not_reached ();
6444 // Yes, this returns NULL, even if it is documented as not doing so, but there
6445 // is no way for the code to make it this far, due to the assert above.
6450 * mono_type_retrieve_from_typespec
6451 * \param image context where the image is created
6452 * \param type_spec typespec token
6453 * \param context the generic context used to evaluate generic instantiations in
6456 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6458 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6460 *did_inflate = FALSE;
6465 if (context && (context->class_inst || context->method_inst)) {
6466 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6468 if (!mono_error_ok (error)) {
6474 *did_inflate = TRUE;
6481 * mono_class_create_from_typespec
6482 * \param image context where the image is created
6483 * \param type_spec typespec token
6484 * \param context the generic context used to evaluate generic instantiations in
6487 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6490 gboolean inflated = FALSE;
6491 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6492 return_val_if_nok (error, NULL);
6493 ret = mono_class_from_mono_type (t);
6495 mono_metadata_free_type (t);
6500 * mono_bounded_array_class_get:
6501 * \param element_class element class
6502 * \param rank the dimension of the array class
6503 * \param bounded whenever the array has non-zero bounds
6504 * \returns A class object describing the array with element type \p element_type and
6505 * dimension \p rank.
6508 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6511 MonoClass *klass, *cached, *k;
6512 MonoClass *parent = NULL;
6513 GSList *list, *rootlist = NULL;
6517 g_assert (rank <= 255);
6520 /* bounded only matters for one-dimensional arrays */
6523 image = eclass->image;
6527 if (rank == 1 && !bounded) {
6529 * This case is very frequent not just during compilation because of calls
6530 * from mono_class_from_mono_type (), mono_array_new (),
6531 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6533 mono_os_mutex_lock (&image->szarray_cache_lock);
6534 if (!image->szarray_cache)
6535 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6536 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6537 mono_os_mutex_unlock (&image->szarray_cache_lock);
6539 mono_loader_lock ();
6540 if (!image->array_cache)
6541 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6542 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6543 for (list = rootlist; list; list = list->next) {
6544 k = (MonoClass *)list->data;
6545 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6550 mono_loader_unlock ();
6555 parent = mono_defaults.array_class;
6556 if (!parent->inited)
6557 mono_class_init (parent);
6559 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6561 klass->image = image;
6562 klass->name_space = eclass->name_space;
6563 klass->class_kind = MONO_CLASS_ARRAY;
6565 nsize = strlen (eclass->name);
6566 name = (char *)g_malloc (nsize + 2 + rank + 1);
6567 memcpy (name, eclass->name, nsize);
6570 memset (name + nsize + 1, ',', rank - 1);
6572 name [nsize + rank] = '*';
6573 name [nsize + rank + bounded] = ']';
6574 name [nsize + rank + bounded + 1] = 0;
6575 klass->name = mono_image_strdup (image, name);
6578 klass->type_token = 0;
6579 klass->parent = parent;
6580 klass->instance_size = mono_class_instance_size (klass->parent);
6582 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6583 /*Arrays of those two types are invalid.*/
6584 MonoError prepared_error;
6585 error_init (&prepared_error);
6586 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6587 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6588 mono_error_cleanup (&prepared_error);
6589 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6590 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6591 if (!ref_info_handle || eclass->wastypebuilder) {
6592 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6593 g_assert (ref_info_handle && !eclass->wastypebuilder);
6595 /* element_size -1 is ok as this is not an instantitable type*/
6596 klass->sizes.element_size = -1;
6598 klass->sizes.element_size = mono_class_array_element_size (eclass);
6600 mono_class_setup_supertypes (klass);
6602 if (mono_class_is_ginst (eclass))
6603 mono_class_init (eclass);
6604 if (!eclass->size_inited)
6605 mono_class_setup_fields (eclass);
6606 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6607 /*FIXME we fail the array type, but we have to let other fields be set.*/
6609 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6613 if (eclass->enumtype)
6614 klass->cast_class = eclass->element_class;
6616 klass->cast_class = eclass;
6618 switch (klass->cast_class->byval_arg.type) {
6620 klass->cast_class = mono_defaults.byte_class;
6623 klass->cast_class = mono_defaults.int16_class;
6626 #if SIZEOF_VOID_P == 4
6630 klass->cast_class = mono_defaults.int32_class;
6633 #if SIZEOF_VOID_P == 8
6637 klass->cast_class = mono_defaults.int64_class;
6643 klass->element_class = eclass;
6645 if ((rank > 1) || bounded) {
6646 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6647 klass->byval_arg.type = MONO_TYPE_ARRAY;
6648 klass->byval_arg.data.array = at;
6649 at->eklass = eclass;
6651 /* FIXME: complete.... */
6653 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6654 klass->byval_arg.data.klass = eclass;
6656 klass->this_arg = klass->byval_arg;
6657 klass->this_arg.byref = 1;
6660 MonoError prepared_error;
6661 error_init (&prepared_error);
6662 name = mono_type_get_full_name (klass);
6663 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6664 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6665 mono_error_cleanup (&prepared_error);
6669 mono_loader_lock ();
6671 /* Check cache again */
6673 if (rank == 1 && !bounded) {
6674 mono_os_mutex_lock (&image->szarray_cache_lock);
6675 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6676 mono_os_mutex_unlock (&image->szarray_cache_lock);
6678 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6679 for (list = rootlist; list; list = list->next) {
6680 k = (MonoClass *)list->data;
6681 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6688 mono_loader_unlock ();
6692 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6694 classes_size += sizeof (MonoClassArray);
6695 ++class_array_count;
6697 if (rank == 1 && !bounded) {
6698 mono_os_mutex_lock (&image->szarray_cache_lock);
6699 g_hash_table_insert (image->szarray_cache, eclass, klass);
6700 mono_os_mutex_unlock (&image->szarray_cache_lock);
6702 list = g_slist_append (rootlist, klass);
6703 g_hash_table_insert (image->array_cache, eclass, list);
6706 mono_loader_unlock ();
6708 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6714 * mono_array_class_get:
6715 * \param element_class element class
6716 * \param rank the dimension of the array class
6717 * \returns A class object describing the array with element type \p element_type and
6718 * dimension \p rank.
6721 mono_array_class_get (MonoClass *eclass, guint32 rank)
6723 return mono_bounded_array_class_get (eclass, rank, FALSE);
6727 * mono_class_instance_size:
6728 * \param klass a class
6730 * Use to get the size of a class in bytes.
6732 * \returns The size of an object instance
6735 mono_class_instance_size (MonoClass *klass)
6737 if (!klass->size_inited)
6738 mono_class_init (klass);
6740 return klass->instance_size;
6744 * mono_class_min_align:
6745 * \param klass a class
6747 * Use to get the computed minimum alignment requirements for the specified class.
6749 * Returns: minimum alignment requirements
6752 mono_class_min_align (MonoClass *klass)
6754 if (!klass->size_inited)
6755 mono_class_init (klass);
6757 return klass->min_align;
6761 * mono_class_value_size:
6762 * \param klass a class
6764 * This function is used for value types, and return the
6765 * space and the alignment to store that kind of value object.
6767 * \returns the size of a value of kind \p klass
6770 mono_class_value_size (MonoClass *klass, guint32 *align)
6774 /* fixme: check disable, because we still have external revereces to
6775 * mscorlib and Dummy Objects
6777 /*g_assert (klass->valuetype);*/
6779 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6782 *align = klass->min_align;
6788 * mono_class_data_size:
6789 * \param klass a class
6791 * \returns The size of the static class data
6794 mono_class_data_size (MonoClass *klass)
6797 mono_class_init (klass);
6798 /* This can happen with dynamically created types */
6799 if (!klass->fields_inited)
6800 mono_class_setup_fields (klass);
6802 /* in arrays, sizes.class_size is unioned with element_size
6803 * and arrays have no static fields
6807 return klass->sizes.class_size;
6811 * Auxiliary routine to mono_class_get_field
6813 * Takes a field index instead of a field token.
6815 static MonoClassField *
6816 mono_class_get_field_idx (MonoClass *klass, int idx)
6818 mono_class_setup_fields (klass);
6819 if (mono_class_has_failure (klass))
6823 int first_field_idx = mono_class_get_first_field_idx (klass);
6824 int fcount = mono_class_get_field_count (klass);
6825 if (klass->image->uncompressed_metadata) {
6827 * first_field_idx points to the FieldPtr table, while idx points into the
6828 * Field table, so we have to do a search.
6830 /*FIXME this is broken for types with multiple fields with the same name.*/
6831 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6834 for (i = 0; i < fcount; ++i)
6835 if (mono_field_get_name (&klass->fields [i]) == name)
6836 return &klass->fields [i];
6837 g_assert_not_reached ();
6840 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6841 return &klass->fields [idx - first_field_idx];
6845 klass = klass->parent;
6851 * mono_class_get_field:
6852 * \param class the class to lookup the field.
6853 * \param field_token the field token
6855 * \returns A \c MonoClassField representing the type and offset of
6856 * the field, or a NULL value if the field does not belong to this
6860 mono_class_get_field (MonoClass *klass, guint32 field_token)
6862 int idx = mono_metadata_token_index (field_token);
6864 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6866 return mono_class_get_field_idx (klass, idx - 1);
6870 * mono_class_get_field_from_name:
6871 * \param klass the class to lookup the field.
6872 * \param name the field name
6874 * Search the class \p klass and its parents for a field with the name \p name.
6876 * \returns The \c MonoClassField pointer of the named field or NULL
6879 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6881 return mono_class_get_field_from_name_full (klass, name, NULL);
6885 * mono_class_get_field_from_name_full:
6886 * \param klass the class to lookup the field.
6887 * \param name the field name
6888 * \param type the type of the fields. This optional.
6890 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6892 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6893 * of its generic type definition.
6895 * \returns The MonoClassField pointer of the named field or NULL
6898 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6902 mono_class_setup_fields (klass);
6903 if (mono_class_has_failure (klass))
6907 int fcount = mono_class_get_field_count (klass);
6908 for (i = 0; i < fcount; ++i) {
6909 MonoClassField *field = &klass->fields [i];
6911 if (strcmp (name, mono_field_get_name (field)) != 0)
6915 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6916 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6921 klass = klass->parent;
6927 * mono_class_get_field_token:
6928 * \param field the field we need the token of
6930 * Get the token of a field. Note that the tokesn is only valid for the image
6931 * the field was loaded from. Don't use this function for fields in dynamic types.
6933 * \returns The token representing the field in the image it was loaded from.
6936 mono_class_get_field_token (MonoClassField *field)
6938 MonoClass *klass = field->parent;
6941 mono_class_setup_fields (klass);
6946 int first_field_idx = mono_class_get_first_field_idx (klass);
6947 int fcount = mono_class_get_field_count (klass);
6948 for (i = 0; i < fcount; ++i) {
6949 if (&klass->fields [i] == field) {
6950 int idx = first_field_idx + i + 1;
6952 if (klass->image->uncompressed_metadata)
6953 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6954 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6957 klass = klass->parent;
6960 g_assert_not_reached ();
6965 mono_field_get_index (MonoClassField *field)
6967 int index = field - field->parent->fields;
6968 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6974 * mono_class_get_field_default_value:
6976 * Return the default value of the field as a pointer into the metadata blob.
6979 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6982 guint32 constant_cols [MONO_CONSTANT_SIZE];
6984 MonoClass *klass = field->parent;
6985 MonoFieldDefaultValue *def_values;
6987 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6989 def_values = mono_class_get_field_def_values (klass);
6991 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6993 mono_class_set_field_def_values (klass, def_values);
6996 field_index = mono_field_get_index (field);
6998 if (!def_values [field_index].data) {
6999 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7003 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7005 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7006 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7007 mono_memory_barrier ();
7008 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7011 *def_type = def_values [field_index].def_type;
7012 return def_values [field_index].data;
7016 mono_property_get_index (MonoProperty *prop)
7018 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7019 int index = prop - info->properties;
7021 g_assert (index >= 0 && index < info->count);
7027 * mono_class_get_property_default_value:
7029 * Return the default value of the field as a pointer into the metadata blob.
7032 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7035 guint32 constant_cols [MONO_CONSTANT_SIZE];
7036 MonoClass *klass = property->parent;
7038 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7040 * We don't cache here because it is not used by C# so it's quite rare, but
7041 * we still do the lookup in klass->ext because that is where the data
7042 * is stored for dynamic assemblies.
7045 if (image_is_dynamic (klass->image)) {
7046 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7047 int prop_index = mono_property_get_index (property);
7048 if (info->def_values && info->def_values [prop_index].data) {
7049 *def_type = info->def_values [prop_index].def_type;
7050 return info->def_values [prop_index].data;
7054 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7058 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7059 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7060 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7064 * mono_class_get_event_token:
7067 mono_class_get_event_token (MonoEvent *event)
7069 MonoClass *klass = event->parent;
7073 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7075 for (i = 0; i < info->count; ++i) {
7076 if (&info->events [i] == event)
7077 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7080 klass = klass->parent;
7083 g_assert_not_reached ();
7088 * mono_class_get_property_from_name:
7089 * \param klass a class
7090 * \param name name of the property to lookup in the specified class
7092 * Use this method to lookup a property in a class
7093 * \returns the \c MonoProperty with the given name, or NULL if the property
7094 * does not exist on the \p klass.
7097 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7101 gpointer iter = NULL;
7102 while ((p = mono_class_get_properties (klass, &iter))) {
7103 if (! strcmp (name, p->name))
7106 klass = klass->parent;
7112 * mono_class_get_property_token:
7113 * \param prop MonoProperty to query
7115 * \returns The ECMA token for the specified property.
7118 mono_class_get_property_token (MonoProperty *prop)
7120 MonoClass *klass = prop->parent;
7124 gpointer iter = NULL;
7125 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7126 while ((p = mono_class_get_properties (klass, &iter))) {
7127 if (&info->properties [i] == prop)
7128 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7132 klass = klass->parent;
7135 g_assert_not_reached ();
7140 * mono_class_name_from_token:
7143 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7145 const char *name, *nspace;
7146 if (image_is_dynamic (image))
7147 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7149 switch (type_token & 0xff000000){
7150 case MONO_TOKEN_TYPE_DEF: {
7151 guint32 cols [MONO_TYPEDEF_SIZE];
7152 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7153 guint tidx = mono_metadata_token_index (type_token);
7155 if (tidx > tt->rows)
7156 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7158 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7159 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7160 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7161 if (strlen (nspace) == 0)
7162 return g_strdup_printf ("%s", name);
7164 return g_strdup_printf ("%s.%s", nspace, name);
7167 case MONO_TOKEN_TYPE_REF: {
7169 guint32 cols [MONO_TYPEREF_SIZE];
7170 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7171 guint tidx = mono_metadata_token_index (type_token);
7174 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7176 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7177 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7178 mono_error_cleanup (&error);
7182 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7183 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7184 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7185 if (strlen (nspace) == 0)
7186 return g_strdup_printf ("%s", name);
7188 return g_strdup_printf ("%s.%s", nspace, name);
7191 case MONO_TOKEN_TYPE_SPEC:
7192 return g_strdup_printf ("Typespec 0x%08x", type_token);
7194 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7199 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7201 if (image_is_dynamic (image))
7202 return g_strdup_printf ("DynamicAssembly %s", image->name);
7204 switch (type_token & 0xff000000){
7205 case MONO_TOKEN_TYPE_DEF:
7206 if (image->assembly)
7207 return mono_stringify_assembly_name (&image->assembly->aname);
7208 else if (image->assembly_name)
7209 return g_strdup (image->assembly_name);
7210 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7211 case MONO_TOKEN_TYPE_REF: {
7213 MonoAssemblyName aname;
7214 guint32 cols [MONO_TYPEREF_SIZE];
7215 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7216 guint32 idx = mono_metadata_token_index (type_token);
7219 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7221 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7222 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7223 mono_error_cleanup (&error);
7226 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7228 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7229 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7230 case MONO_RESOLUTION_SCOPE_MODULE:
7232 return g_strdup ("");
7233 case MONO_RESOLUTION_SCOPE_MODULEREF:
7235 return g_strdup ("");
7236 case MONO_RESOLUTION_SCOPE_TYPEREF:
7238 return g_strdup ("");
7239 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7240 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7241 return mono_stringify_assembly_name (&aname);
7243 g_assert_not_reached ();
7247 case MONO_TOKEN_TYPE_SPEC:
7249 return g_strdup ("");
7251 g_assert_not_reached ();
7258 * mono_class_get_full:
7259 * \param image the image where the class resides
7260 * \param type_token the token for the class
7261 * \param context the generic context used to evaluate generic instantiations in
7262 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7263 * \returns The \c MonoClass that represents \p type_token in \p image
7266 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7270 klass = mono_class_get_checked (image, type_token, &error);
7272 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7273 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7275 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7281 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7286 klass = mono_class_get_checked (image, type_token, error);
7288 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7289 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7294 * mono_class_get_checked:
7295 * \param image the image where the class resides
7296 * \param type_token the token for the class
7297 * \param error error object to return any error
7299 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7302 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7304 MonoClass *klass = NULL;
7308 if (image_is_dynamic (image)) {
7309 int table = mono_metadata_token_table (type_token);
7311 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7312 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7315 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7319 switch (type_token & 0xff000000){
7320 case MONO_TOKEN_TYPE_DEF:
7321 klass = mono_class_create_from_typedef (image, type_token, error);
7323 case MONO_TOKEN_TYPE_REF:
7324 klass = mono_class_from_typeref_checked (image, type_token, error);
7326 case MONO_TOKEN_TYPE_SPEC:
7327 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7330 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7334 /* Generic case, should be avoided for when a better error is possible. */
7335 if (!klass && mono_error_ok (error)) {
7336 char *name = mono_class_name_from_token (image, type_token);
7337 char *assembly = mono_assembly_name_from_token (image, type_token);
7338 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7346 * mono_type_get_checked:
7347 * \param image the image where the type resides
7348 * \param type_token the token for the type
7349 * \param context the generic context used to evaluate generic instantiations in
7350 * \param error Error handling context
7352 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7354 * \returns The MonoType that represents \p type_token in \p image
7357 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7359 MonoType *type = NULL;
7360 gboolean inflated = FALSE;
7364 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7365 if (image_is_dynamic (image)) {
7366 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7367 return_val_if_nok (error, NULL);
7368 return mono_class_get_type (klass);
7371 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7372 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7379 return mono_class_get_type (klass);
7382 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7389 MonoType *tmp = type;
7390 type = mono_class_get_type (mono_class_from_mono_type (type));
7391 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7392 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7393 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7395 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7397 if (type->type != tmp->type)
7400 mono_metadata_free_type (tmp);
7407 * \param image image where the class token will be looked up.
7408 * \param type_token a type token from the image
7409 * \returns the \c MonoClass with the given \p type_token on the \p image
7412 mono_class_get (MonoImage *image, guint32 type_token)
7414 return mono_class_get_full (image, type_token, NULL);
7418 * mono_image_init_name_cache:
7420 * Initializes the class name cache stored in image->name_cache.
7422 * LOCKING: Acquires the corresponding image lock.
7425 mono_image_init_name_cache (MonoImage *image)
7427 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7428 guint32 cols [MONO_TYPEDEF_SIZE];
7431 guint32 i, visib, nspace_index;
7432 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7434 if (image->name_cache)
7437 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7439 if (image_is_dynamic (image)) {
7440 mono_image_lock (image);
7441 if (image->name_cache) {
7442 /* Somebody initialized it before us */
7443 g_hash_table_destroy (the_name_cache);
7445 mono_atomic_store_release (&image->name_cache, the_name_cache);
7447 mono_image_unlock (image);
7451 /* Temporary hash table to avoid lookups in the nspace_table */
7452 name_cache2 = g_hash_table_new (NULL, NULL);
7454 for (i = 1; i <= t->rows; ++i) {
7455 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7456 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7458 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7459 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7461 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7463 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7464 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7466 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7467 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7468 if (!nspace_table) {
7469 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7470 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7471 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7474 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7477 /* Load type names from EXPORTEDTYPES table */
7479 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7480 guint32 cols [MONO_EXP_TYPE_SIZE];
7483 for (i = 0; i < t->rows; ++i) {
7484 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7486 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7487 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7491 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7492 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7494 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7495 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7496 if (!nspace_table) {
7497 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7498 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7499 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7502 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7506 g_hash_table_destroy (name_cache2);
7508 mono_image_lock (image);
7509 if (image->name_cache) {
7510 /* Somebody initialized it before us */
7511 g_hash_table_destroy (the_name_cache);
7513 mono_atomic_store_release (&image->name_cache, the_name_cache);
7515 mono_image_unlock (image);
7518 /*FIXME Only dynamic assemblies should allow this operation.*/
7520 * mono_image_add_to_name_cache:
7523 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7524 const char *name, guint32 index)
7526 GHashTable *nspace_table;
7527 GHashTable *name_cache;
7530 mono_image_init_name_cache (image);
7531 mono_image_lock (image);
7533 name_cache = image->name_cache;
7534 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7535 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7536 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7539 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7540 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7542 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7544 mono_image_unlock (image);
7553 find_nocase (gpointer key, gpointer value, gpointer user_data)
7555 char *name = (char*)key;
7556 FindUserData *data = (FindUserData*)user_data;
7558 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7559 data->value = value;
7563 * mono_class_from_name_case:
7564 * \param image The MonoImage where the type is looked up in
7565 * \param name_space the type namespace
7566 * \param name the type short name.
7567 * \deprecated use the mono_class_from_name_case_checked variant instead.
7569 * Obtains a \c MonoClass with a given namespace and a given name which
7570 * is located in the given \c MonoImage. The namespace and name
7571 * lookups are case insensitive.
7574 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7577 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7578 mono_error_cleanup (&error);
7584 * mono_class_from_name_case_checked:
7585 * \param image The MonoImage where the type is looked up in
7586 * \param name_space the type namespace
7587 * \param name the type short name.
7590 * Obtains a MonoClass with a given namespace and a given name which
7591 * is located in the given MonoImage. The namespace and name
7592 * lookups are case insensitive.
7594 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7595 * was not found. The \p error object will contain information about the problem
7599 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7601 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7602 guint32 cols [MONO_TYPEDEF_SIZE];
7609 if (image_is_dynamic (image)) {
7611 FindUserData user_data;
7613 mono_image_init_name_cache (image);
7614 mono_image_lock (image);
7616 user_data.key = name_space;
7617 user_data.value = NULL;
7618 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7620 if (user_data.value) {
7621 GHashTable *nspace_table = (GHashTable*)user_data.value;
7623 user_data.key = name;
7624 user_data.value = NULL;
7626 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7628 if (user_data.value)
7629 token = GPOINTER_TO_UINT (user_data.value);
7632 mono_image_unlock (image);
7635 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7641 /* add a cache if needed */
7642 for (i = 1; i <= t->rows; ++i) {
7643 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7644 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7646 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7647 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7649 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7651 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7652 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7653 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7654 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7660 return_nested_in (MonoClass *klass, char *nested)
7663 char *s = strchr (nested, '/');
7664 gpointer iter = NULL;
7671 while ((found = mono_class_get_nested_types (klass, &iter))) {
7672 if (strcmp (found->name, nested) == 0) {
7674 return return_nested_in (found, s);
7682 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7684 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7685 MonoImage *file_image;
7692 * The EXPORTEDTYPES table only contains public types, so have to search the
7694 * Note: image->modules contains the contents of the MODULEREF table, while
7695 * the real module list is in the FILE table.
7697 for (i = 0; i < file_table->rows; i++) {
7698 guint32 cols [MONO_FILE_SIZE];
7699 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7700 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7703 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7705 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7706 if (klass || !is_ok (error))
7715 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7717 GHashTable *nspace_table;
7718 MonoImage *loaded_image;
7727 // Checking visited images avoids stack overflows when cyclic references exist.
7728 if (g_hash_table_lookup (visited_images, image))
7731 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7733 if ((nested = strchr (name, '/'))) {
7734 int pos = nested - name;
7735 int len = strlen (name);
7738 memcpy (buf, name, len + 1);
7740 nested = buf + pos + 1;
7744 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7745 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7746 gboolean res = get_class_from_name (image, name_space, name, &klass);
7749 klass = search_modules (image, name_space, name, error);
7754 return klass ? return_nested_in (klass, nested) : NULL;
7760 mono_image_init_name_cache (image);
7761 mono_image_lock (image);
7763 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7766 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7768 mono_image_unlock (image);
7770 if (!token && image_is_dynamic (image) && image->modules) {
7771 /* Search modules as well */
7772 for (i = 0; i < image->module_count; ++i) {
7773 MonoImage *module = image->modules [i];
7775 klass = mono_class_from_name_checked (module, name_space, name, error);
7776 if (klass || !is_ok (error))
7782 klass = search_modules (image, name_space, name, error);
7783 if (klass || !is_ok (error))
7788 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7789 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7790 guint32 cols [MONO_EXP_TYPE_SIZE];
7793 idx = mono_metadata_token_index (token);
7795 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7797 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7798 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7799 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7802 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7804 return klass ? return_nested_in (klass, nested) : NULL;
7806 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7807 guint32 assembly_idx;
7809 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7811 mono_assembly_load_reference (image, assembly_idx - 1);
7812 g_assert (image->references [assembly_idx - 1]);
7813 if (image->references [assembly_idx - 1] == (gpointer)-1)
7815 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7817 return klass ? return_nested_in (klass, nested) : NULL;
7820 g_assert_not_reached ();
7824 token = MONO_TOKEN_TYPE_DEF | token;
7826 klass = mono_class_get_checked (image, token, error);
7828 return return_nested_in (klass, nested);
7833 * mono_class_from_name_checked:
7834 * \param image The MonoImage where the type is looked up in
7835 * \param name_space the type namespace
7836 * \param name the type short name.
7838 * Obtains a MonoClass with a given namespace and a given name which
7839 * is located in the given MonoImage.
7841 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7842 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7845 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7848 GHashTable *visited_images;
7850 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7852 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7854 g_hash_table_destroy (visited_images);
7860 * mono_class_from_name:
7861 * \param image The \c MonoImage where the type is looked up in
7862 * \param name_space the type namespace
7863 * \param name the type short name.
7865 * Obtains a \c MonoClass with a given namespace and a given name which
7866 * is located in the given \c MonoImage.
7868 * To reference nested classes, use the "/" character as a separator.
7869 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7870 * inside \c Foo, like this: "class Foo { class Bar {} }".
7873 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7878 klass = mono_class_from_name_checked (image, name_space, name, &error);
7879 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7885 * mono_class_load_from_name:
7886 * \param image The MonoImage where the type is looked up in
7887 * \param name_space the type namespace
7888 * \param name the type short name.
7890 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7891 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7892 * If they are missing. Thing of System.Object or System.String.
7895 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7900 klass = mono_class_from_name_checked (image, name_space, name, &error);
7902 g_error ("Runtime critical type %s.%s not found", name_space, name);
7903 if (!mono_error_ok (&error))
7904 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7909 * mono_class_try_load_from_name:
7910 * \param image The MonoImage where the type is looked up in
7911 * \param name_space the type namespace
7912 * \param name the type short name.
7914 * This function tries to load a type, returning the class was found or NULL otherwise.
7915 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7917 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7918 * a type that we would otherwise assume to be available but was not due some error.
7922 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7927 klass = mono_class_from_name_checked (image, name_space, name, &error);
7928 if (!mono_error_ok (&error))
7929 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7935 * mono_class_is_subclass_of:
7936 * \param klass class to probe if it is a subclass of another one
7937 * \param klassc the class we suspect is the base class
7938 * \param check_interfaces whether we should perform interface checks
7940 * This method determines whether \p klass is a subclass of \p klassc.
7942 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7943 * this method return TRUE if the \p klass implements the interface or
7944 * if \p klass is an interface, if one of its base classes is \p klass.
7946 * If \p check_interfaces is false, then if \p klass is not an interface,
7947 * it returns TRUE if the \p klass is a subclass of \p klassc.
7949 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7954 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7955 gboolean check_interfaces)
7957 /* FIXME test for interfaces with variant generic arguments */
7958 mono_class_init (klass);
7959 mono_class_init (klassc);
7961 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7962 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7964 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7967 for (i = 0; i < klass->interface_count; i ++) {
7968 MonoClass *ic = klass->interfaces [i];
7973 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7978 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7981 if (klassc == mono_defaults.object_class)
7988 mono_type_is_generic_argument (MonoType *type)
7990 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7994 mono_class_has_variant_generic_params (MonoClass *klass)
7997 MonoGenericContainer *container;
7999 if (!mono_class_is_ginst (klass))
8002 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8004 for (i = 0; i < container->type_argc; ++i)
8005 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8012 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8014 if (target == candidate)
8017 if (check_for_reference_conv &&
8018 mono_type_is_generic_argument (&target->byval_arg) &&
8019 mono_type_is_generic_argument (&candidate->byval_arg)) {
8020 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8021 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8023 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8026 if (!mono_class_is_assignable_from (target, candidate))
8032 * @container the generic container from the GTD
8033 * @klass: the class to be assigned to
8034 * @oklass: the source class
8036 * Both @klass and @oklass must be instances of the same generic interface.
8038 * Returns: TRUE if @klass can be assigned to a @klass variable
8041 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8044 MonoType **klass_argv, **oklass_argv;
8045 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8046 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8048 if (klass == oklass)
8051 /*Viable candidates are instances of the same generic interface*/
8052 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8055 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8056 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8058 for (j = 0; j < container->type_argc; ++j) {
8059 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8060 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8062 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8066 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8067 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8069 if (param1_class != param2_class) {
8070 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8071 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8073 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8074 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8084 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8086 MonoGenericParam *gparam, *ogparam;
8087 MonoGenericParamInfo *tinfo, *cinfo;
8088 MonoClass **candidate_class;
8089 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8092 if (target == candidate)
8094 if (target->byval_arg.type != candidate->byval_arg.type)
8097 gparam = target->byval_arg.data.generic_param;
8098 ogparam = candidate->byval_arg.data.generic_param;
8099 tinfo = mono_generic_param_info (gparam);
8100 cinfo = mono_generic_param_info (ogparam);
8102 class_constraint_satisfied = FALSE;
8103 valuetype_constraint_satisfied = FALSE;
8105 /*candidate must have a super set of target's special constraints*/
8106 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8107 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8109 if (cinfo->constraints) {
8110 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8111 MonoClass *cc = *candidate_class;
8113 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8114 class_constraint_satisfied = TRUE;
8115 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8116 valuetype_constraint_satisfied = TRUE;
8119 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8120 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8122 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8124 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8126 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8127 valuetype_constraint_satisfied)) {
8132 /*candidate type constraints must be a superset of target's*/
8133 if (tinfo->constraints) {
8134 MonoClass **target_class;
8135 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8136 MonoClass *tc = *target_class;
8139 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8140 * check it's constraints since it satisfy the constraint by itself.
8142 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8145 if (!cinfo->constraints)
8148 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8149 MonoClass *cc = *candidate_class;
8151 if (mono_class_is_assignable_from (tc, cc))
8155 * This happens when we have the following:
8157 * Bar<K> where K : IFace
8158 * Foo<T, U> where T : U where U : IFace
8160 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8163 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8164 if (mono_gparam_is_assignable_from (target, cc))
8168 if (!*candidate_class)
8173 /*candidate itself must have a constraint that satisfy target*/
8174 if (cinfo->constraints) {
8175 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8176 MonoClass *cc = *candidate_class;
8177 if (mono_class_is_assignable_from (target, cc))
8185 * mono_class_is_assignable_from:
8186 * \param klass the class to be assigned to
8187 * \param oklass the source class
8189 * \returns TRUE if an instance of class \p oklass can be assigned to an
8190 * instance of class \p klass
8193 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8196 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8198 mono_class_init (klass);
8200 if (!oklass->inited)
8201 mono_class_init (oklass);
8203 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8206 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8207 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8209 return mono_gparam_is_assignable_from (klass, oklass);
8212 if (MONO_CLASS_IS_INTERFACE (klass)) {
8213 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8214 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8215 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8219 for (i = 0; constraints [i]; ++i) {
8220 if (mono_class_is_assignable_from (klass, constraints [i]))
8228 /* interface_offsets might not be set for dynamic classes */
8229 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8231 * oklass might be a generic type parameter but they have
8232 * interface_offsets set.
8234 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8235 if (!is_ok (&error)) {
8236 mono_error_cleanup (&error);
8241 if (!oklass->interface_bitmap)
8242 /* Happens with generic instances of not-yet created dynamic types */
8244 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8247 if (klass->is_array_special_interface && oklass->rank == 1) {
8248 //XXX we could offset this by having the cast target computed at JIT time
8249 //XXX we could go even further and emit a wrapper that would do the extra type check
8250 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8251 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8253 // 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
8254 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8255 if (iface_klass->valuetype)
8256 iface_klass = iface_klass->cast_class;
8258 //array covariant casts only operates on scalar to scalar
8259 //This is so int[] can't be casted to IComparable<int>[]
8260 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8264 if (mono_class_has_variant_generic_params (klass)) {
8266 mono_class_setup_interfaces (oklass, &error);
8267 if (!mono_error_ok (&error)) {
8268 mono_error_cleanup (&error);
8272 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8273 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8274 MonoClass *iface = oklass->interfaces_packed [i];
8276 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8281 } else if (klass->delegate) {
8282 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8284 }else if (klass->rank) {
8285 MonoClass *eclass, *eoclass;
8287 if (oklass->rank != klass->rank)
8290 /* vectors vs. one dimensional arrays */
8291 if (oklass->byval_arg.type != klass->byval_arg.type)
8294 eclass = klass->cast_class;
8295 eoclass = oklass->cast_class;
8298 * a is b does not imply a[] is b[] when a is a valuetype, and
8299 * b is a reference type.
8302 if (eoclass->valuetype) {
8303 if ((eclass == mono_defaults.enum_class) ||
8304 (eclass == mono_defaults.enum_class->parent) ||
8305 (eclass == mono_defaults.object_class))
8309 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8310 } else if (mono_class_is_nullable (klass)) {
8311 if (mono_class_is_nullable (oklass))
8312 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8314 return mono_class_is_assignable_from (klass->cast_class, oklass);
8315 } else if (klass == mono_defaults.object_class)
8318 return mono_class_has_parent (oklass, klass);
8321 /*Check if @oklass is variant compatible with @klass.*/
8323 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8326 MonoType **klass_argv, **oklass_argv;
8327 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8328 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8330 /*Viable candidates are instances of the same generic interface*/
8331 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8334 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8335 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8337 for (j = 0; j < container->type_argc; ++j) {
8338 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8339 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8341 if (param1_class->valuetype != param2_class->valuetype)
8345 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8346 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8348 if (param1_class != param2_class) {
8349 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8350 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8352 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8353 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8361 /*Check if @candidate implements the interface @target*/
8363 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8367 gboolean is_variant = mono_class_has_variant_generic_params (target);
8369 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8370 if (mono_class_is_variant_compatible_slow (target, candidate))
8375 if (candidate == target)
8378 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8379 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8380 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8382 if (tb && tb->interfaces) {
8383 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8384 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8385 MonoClass *iface_class;
8387 /* we can't realize the type here since it can do pretty much anything. */
8390 iface_class = mono_class_from_mono_type (iface->type);
8391 if (iface_class == target)
8393 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8395 if (mono_class_implement_interface_slow (target, iface_class))
8400 /*setup_interfaces don't mono_class_init anything*/
8401 /*FIXME this doesn't handle primitive type arrays.
8402 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8403 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8405 mono_class_setup_interfaces (candidate, &error);
8406 if (!mono_error_ok (&error)) {
8407 mono_error_cleanup (&error);
8411 for (i = 0; i < candidate->interface_count; ++i) {
8412 if (candidate->interfaces [i] == target)
8415 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8418 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8422 candidate = candidate->parent;
8423 } while (candidate);
8429 * Check if @oklass can be assigned to @klass.
8430 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8433 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8435 if (candidate == target)
8437 if (target == mono_defaults.object_class)
8440 if (mono_class_has_parent (candidate, target))
8443 /*If target is not an interface there is no need to check them.*/
8444 if (MONO_CLASS_IS_INTERFACE (target))
8445 return mono_class_implement_interface_slow (target, candidate);
8447 if (target->delegate && mono_class_has_variant_generic_params (target))
8448 return mono_class_is_variant_compatible (target, candidate, FALSE);
8451 MonoClass *eclass, *eoclass;
8453 if (target->rank != candidate->rank)
8456 /* vectors vs. one dimensional arrays */
8457 if (target->byval_arg.type != candidate->byval_arg.type)
8460 eclass = target->cast_class;
8461 eoclass = candidate->cast_class;
8464 * a is b does not imply a[] is b[] when a is a valuetype, and
8465 * b is a reference type.
8468 if (eoclass->valuetype) {
8469 if ((eclass == mono_defaults.enum_class) ||
8470 (eclass == mono_defaults.enum_class->parent) ||
8471 (eclass == mono_defaults.object_class))
8475 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8477 /*FIXME properly handle nullables */
8478 /*FIXME properly handle (M)VAR */
8483 * mono_class_get_cctor:
8484 * \param klass A MonoClass pointer
8486 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8489 mono_class_get_cctor (MonoClass *klass)
8491 MonoCachedClassInfo cached_info;
8493 if (image_is_dynamic (klass->image)) {
8495 * has_cctor is not set for these classes because mono_class_init () is
8498 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8501 mono_class_init (klass);
8503 if (!klass->has_cctor)
8506 if (mono_class_is_ginst (klass) && !klass->methods)
8507 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8509 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8511 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8512 if (!mono_error_ok (&error))
8513 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8517 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8521 * mono_class_get_finalizer:
8522 * \param klass: The MonoClass pointer
8524 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8527 mono_class_get_finalizer (MonoClass *klass)
8529 MonoCachedClassInfo cached_info;
8532 mono_class_init (klass);
8533 if (!mono_class_has_finalizer (klass))
8536 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8538 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8539 if (!mono_error_ok (&error))
8540 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8543 mono_class_setup_vtable (klass);
8544 return klass->vtable [finalize_slot];
8549 * mono_class_needs_cctor_run:
8550 * \param klass the MonoClass pointer
8551 * \param caller a MonoMethod describing the caller
8553 * Determines whenever the class has a static constructor and whenever it
8554 * needs to be called when executing CALLER.
8557 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8561 method = mono_class_get_cctor (klass);
8563 return (method == caller) ? FALSE : TRUE;
8569 * mono_class_array_element_size:
8572 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8575 mono_class_array_element_size (MonoClass *klass)
8577 MonoType *type = &klass->byval_arg;
8580 switch (type->type) {
8583 case MONO_TYPE_BOOLEAN:
8587 case MONO_TYPE_CHAR:
8596 case MONO_TYPE_CLASS:
8597 case MONO_TYPE_STRING:
8598 case MONO_TYPE_OBJECT:
8599 case MONO_TYPE_SZARRAY:
8600 case MONO_TYPE_ARRAY:
8601 return sizeof (gpointer);
8606 case MONO_TYPE_VALUETYPE:
8607 if (type->data.klass->enumtype) {
8608 type = mono_class_enum_basetype (type->data.klass);
8609 klass = klass->element_class;
8612 return mono_class_instance_size (klass) - sizeof (MonoObject);
8613 case MONO_TYPE_GENERICINST:
8614 type = &type->data.generic_class->container_class->byval_arg;
8617 case MONO_TYPE_MVAR: {
8620 return mono_type_size (type, &align);
8622 case MONO_TYPE_VOID:
8626 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8632 * mono_array_element_size:
8633 * \param ac pointer to a \c MonoArrayClass
8635 * \returns The size of single array element.
8638 mono_array_element_size (MonoClass *ac)
8640 g_assert (ac->rank);
8641 return ac->sizes.element_size;
8648 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8649 MonoGenericContext *context)
8652 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8653 g_assert (mono_error_ok (&error));
8658 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8659 MonoGenericContext *context, MonoError *error)
8663 if (image_is_dynamic (image)) {
8664 MonoClass *tmp_handle_class;
8665 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8667 mono_error_assert_ok (error);
8668 g_assert (tmp_handle_class);
8670 *handle_class = tmp_handle_class;
8672 if (tmp_handle_class == mono_defaults.typehandle_class)
8673 return &((MonoClass*)obj)->byval_arg;
8678 switch (token & 0xff000000) {
8679 case MONO_TOKEN_TYPE_DEF:
8680 case MONO_TOKEN_TYPE_REF:
8681 case MONO_TOKEN_TYPE_SPEC: {
8684 *handle_class = mono_defaults.typehandle_class;
8685 type = mono_type_get_checked (image, token, context, error);
8689 mono_class_init (mono_class_from_mono_type (type));
8690 /* We return a MonoType* as handle */
8693 case MONO_TOKEN_FIELD_DEF: {
8695 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8697 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8701 *handle_class = mono_defaults.fieldhandle_class;
8702 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8706 mono_class_init (klass);
8707 return mono_class_get_field (klass, token);
8709 case MONO_TOKEN_METHOD_DEF:
8710 case MONO_TOKEN_METHOD_SPEC: {
8712 meth = mono_get_method_checked (image, token, NULL, context, error);
8714 *handle_class = mono_defaults.methodhandle_class;
8720 case MONO_TOKEN_MEMBER_REF: {
8721 guint32 cols [MONO_MEMBERREF_SIZE];
8723 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8724 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8725 mono_metadata_decode_blob_size (sig, &sig);
8726 if (*sig == 0x6) { /* it's a field */
8728 MonoClassField *field;
8729 field = mono_field_from_token_checked (image, token, &klass, context, error);
8731 *handle_class = mono_defaults.fieldhandle_class;
8735 meth = mono_get_method_checked (image, token, NULL, context, error);
8737 *handle_class = mono_defaults.methodhandle_class;
8742 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8748 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8750 MonoClass *handle_class;
8752 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8756 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8758 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8761 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8764 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8766 get_cached_class_info = func;
8770 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8772 if (!get_cached_class_info)
8775 return get_cached_class_info (klass, res);
8779 mono_install_get_class_from_name (MonoGetClassFromName func)
8781 get_class_from_name = func;
8785 * mono_class_get_image:
8787 * Use this method to get the \c MonoImage* where this class came from.
8789 * \returns The image where this class is defined.
8792 mono_class_get_image (MonoClass *klass)
8794 return klass->image;
8798 * mono_class_get_element_class:
8799 * \param klass the \c MonoClass to act on
8801 * Use this function to get the element class of an array.
8803 * \returns The element class of an array.
8806 mono_class_get_element_class (MonoClass *klass)
8808 return klass->element_class;
8812 * mono_class_is_valuetype:
8813 * \param klass the \c MonoClass to act on
8815 * Use this method to determine if the provided \c MonoClass* represents a value type,
8816 * or a reference type.
8818 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8821 mono_class_is_valuetype (MonoClass *klass)
8823 return klass->valuetype;
8827 * mono_class_is_enum:
8828 * \param klass the \c MonoClass to act on
8830 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8832 * \returns TRUE if the \c MonoClass represents an enumeration.
8835 mono_class_is_enum (MonoClass *klass)
8837 return klass->enumtype;
8841 * mono_class_enum_basetype:
8842 * \param klass the \c MonoClass to act on
8844 * Use this function to get the underlying type for an enumeration value.
8846 * \returns The underlying type representation for an enumeration.
8849 mono_class_enum_basetype (MonoClass *klass)
8851 if (klass->element_class == klass)
8852 /* SRE or broken types */
8855 return &klass->element_class->byval_arg;
8859 * mono_class_get_parent
8860 * \param klass the \c MonoClass to act on
8862 * \returns The parent class for this class.
8865 mono_class_get_parent (MonoClass *klass)
8867 return klass->parent;
8871 * mono_class_get_nesting_type:
8872 * \param klass the \c MonoClass to act on
8874 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8876 * If the return is NULL, this indicates that this class is not nested.
8878 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8881 mono_class_get_nesting_type (MonoClass *klass)
8883 return klass->nested_in;
8887 * mono_class_get_rank:
8888 * \param klass the MonoClass to act on
8890 * \returns The rank for the array (the number of dimensions).
8893 mono_class_get_rank (MonoClass *klass)
8899 * mono_class_get_name
8900 * \param klass the \c MonoClass to act on
8902 * \returns The name of the class.
8905 mono_class_get_name (MonoClass *klass)
8911 * mono_class_get_namespace:
8912 * \param klass the \c MonoClass to act on
8914 * \returns The namespace of the class.
8917 mono_class_get_namespace (MonoClass *klass)
8919 return klass->name_space;
8923 * mono_class_get_type:
8924 * \param klass the \c MonoClass to act on
8926 * This method returns the internal \c MonoType representation for the class.
8928 * \returns The \c MonoType from the class.
8931 mono_class_get_type (MonoClass *klass)
8933 return &klass->byval_arg;
8937 * mono_class_get_type_token:
8938 * \param klass the \c MonoClass to act on
8940 * This method returns type token for the class.
8942 * \returns The type token for the class.
8945 mono_class_get_type_token (MonoClass *klass)
8947 return klass->type_token;
8951 * mono_class_get_byref_type:
8952 * \param klass the \c MonoClass to act on
8957 mono_class_get_byref_type (MonoClass *klass)
8959 return &klass->this_arg;
8963 * mono_class_num_fields:
8964 * \param klass the \c MonoClass to act on
8966 * \returns The number of static and instance fields in the class.
8969 mono_class_num_fields (MonoClass *klass)
8971 return mono_class_get_field_count (klass);
8975 * mono_class_num_methods:
8976 * \param klass the \c MonoClass to act on
8978 * \returns The number of methods in the class.
8981 mono_class_num_methods (MonoClass *klass)
8983 return mono_class_get_method_count (klass);
8987 * mono_class_num_properties
8988 * \param klass the \c MonoClass to act on
8990 * \returns The number of properties in the class.
8993 mono_class_num_properties (MonoClass *klass)
8995 mono_class_setup_properties (klass);
8997 return mono_class_get_property_info (klass)->count;
9001 * mono_class_num_events:
9002 * \param klass the \c MonoClass to act on
9004 * \returns The number of events in the class.
9007 mono_class_num_events (MonoClass *klass)
9009 mono_class_setup_events (klass);
9011 return mono_class_get_event_info (klass)->count;
9015 * mono_class_get_fields:
9016 * \param klass the \c MonoClass to act on
9018 * This routine is an iterator routine for retrieving the fields in a class.
9020 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9021 * iterate over all of the elements. When no more values are
9022 * available, the return value is NULL.
9024 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9027 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9029 MonoClassField* field;
9033 mono_class_setup_fields (klass);
9034 if (mono_class_has_failure (klass))
9036 /* start from the first */
9037 if (mono_class_get_field_count (klass)) {
9038 *iter = &klass->fields [0];
9039 return &klass->fields [0];
9045 field = (MonoClassField *)*iter;
9047 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9055 * mono_class_get_methods:
9056 * \param klass the \c MonoClass to act on
9058 * This routine is an iterator routine for retrieving the fields in a class.
9060 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9061 * iterate over all of the elements. When no more values are
9062 * available, the return value is NULL.
9064 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9067 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9069 MonoMethod** method;
9073 mono_class_setup_methods (klass);
9076 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9077 * FIXME we should better report this error to the caller
9079 if (!klass->methods)
9081 /* start from the first */
9082 if (mono_class_get_method_count (klass)) {
9083 *iter = &klass->methods [0];
9084 return klass->methods [0];
9090 method = (MonoMethod **)*iter;
9092 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9100 * mono_class_get_virtual_methods:
9102 * Iterate over the virtual methods of KLASS.
9104 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9107 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9109 MonoMethod** method;
9112 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9114 mono_class_setup_methods (klass);
9116 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9117 * FIXME we should better report this error to the caller
9119 if (!klass->methods)
9121 /* start from the first */
9122 method = &klass->methods [0];
9124 method = (MonoMethod **)*iter;
9127 int mcount = mono_class_get_method_count (klass);
9128 while (method < &klass->methods [mcount]) {
9129 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9133 if (method < &klass->methods [mcount]) {
9140 /* Search directly in metadata to avoid calling setup_methods () */
9141 MonoMethod *res = NULL;
9147 start_index = GPOINTER_TO_UINT (*iter);
9150 int first_idx = mono_class_get_first_method_idx (klass);
9151 int mcount = mono_class_get_method_count (klass);
9152 for (i = start_index; i < mcount; ++i) {
9155 /* first_idx points into the methodptr table */
9156 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9158 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9164 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9165 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9167 /* Add 1 here so the if (*iter) check fails */
9168 *iter = GUINT_TO_POINTER (i + 1);
9177 * mono_class_get_properties:
9178 * \param klass the \c MonoClass to act on
9180 * This routine is an iterator routine for retrieving the properties in a class.
9182 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9183 * iterate over all of the elements. When no more values are
9184 * available, the return value is NULL.
9186 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9189 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9191 MonoProperty* property;
9195 mono_class_setup_properties (klass);
9196 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9197 /* start from the first */
9199 *iter = &info->properties [0];
9200 return (MonoProperty *)*iter;
9206 property = (MonoProperty *)*iter;
9208 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9209 if (property < &info->properties [info->count]) {
9211 return (MonoProperty *)*iter;
9217 * mono_class_get_events:
9218 * \param klass the \c MonoClass to act on
9220 * This routine is an iterator routine for retrieving the properties in a class.
9222 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9223 * iterate over all of the elements. When no more values are
9224 * available, the return value is NULL.
9226 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9229 mono_class_get_events (MonoClass* klass, gpointer *iter)
9235 mono_class_setup_events (klass);
9236 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9237 /* start from the first */
9239 *iter = &info->events [0];
9240 return (MonoEvent *)*iter;
9246 event = (MonoEvent *)*iter;
9248 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9249 if (event < &info->events [info->count]) {
9251 return (MonoEvent *)*iter;
9257 * mono_class_get_interfaces
9258 * \param klass the \c MonoClass to act on
9260 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9262 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9263 * iterate over all of the elements. When no more values are
9264 * available, the return value is NULL.
9266 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9269 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9277 mono_class_init (klass);
9278 if (!klass->interfaces_inited) {
9279 mono_class_setup_interfaces (klass, &error);
9280 if (!mono_error_ok (&error)) {
9281 mono_error_cleanup (&error);
9285 /* start from the first */
9286 if (klass->interface_count) {
9287 *iter = &klass->interfaces [0];
9288 return klass->interfaces [0];
9294 iface = (MonoClass **)*iter;
9296 if (iface < &klass->interfaces [klass->interface_count]) {
9304 setup_nested_types (MonoClass *klass)
9307 GList *classes, *nested_classes, *l;
9310 if (klass->nested_classes_inited)
9313 if (!klass->type_token) {
9314 mono_loader_lock ();
9315 klass->nested_classes_inited = TRUE;
9316 mono_loader_unlock ();
9320 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9324 guint32 cols [MONO_NESTED_CLASS_SIZE];
9325 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9326 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9327 if (!mono_error_ok (&error)) {
9328 /*FIXME don't swallow the error message*/
9329 mono_error_cleanup (&error);
9331 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9335 classes = g_list_prepend (classes, nclass);
9337 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9340 nested_classes = NULL;
9341 for (l = classes; l; l = l->next)
9342 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9343 g_list_free (classes);
9345 mono_loader_lock ();
9346 if (!klass->nested_classes_inited) {
9347 mono_class_set_nested_classes_property (klass, nested_classes);
9348 mono_memory_barrier ();
9349 klass->nested_classes_inited = TRUE;
9351 mono_loader_unlock ();
9355 * mono_class_get_nested_types
9356 * \param klass the \c MonoClass to act on
9358 * This routine is an iterator routine for retrieving the nested types of a class.
9359 * This works only if \p klass is non-generic, or a generic type definition.
9361 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9362 * iterate over all of the elements. When no more values are
9363 * available, the return value is NULL.
9365 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9368 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9374 if (!klass->nested_classes_inited)
9375 setup_nested_types (klass);
9378 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9379 /* start from the first */
9380 if (nested_classes) {
9381 *iter = nested_classes;
9382 return (MonoClass *)nested_classes->data;
9384 /* no nested types */
9388 item = (GList *)*iter;
9392 return (MonoClass *)item->data;
9399 * mono_class_is_delegate
9400 * \param klass the \c MonoClass to act on
9402 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9405 mono_class_is_delegate (MonoClass *klass)
9407 return klass->delegate;
9411 * mono_class_implements_interface
9412 * \param klass The MonoClass to act on
9413 * \param interface The interface to check if \p klass implements.
9415 * \returns TRUE if \p klass implements \p interface.
9418 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9420 return mono_class_is_assignable_from (iface, klass);
9424 * mono_field_get_name:
9425 * \param field the \c MonoClassField to act on
9427 * \returns The name of the field.
9430 mono_field_get_name (MonoClassField *field)
9436 * mono_field_get_type:
9437 * \param field the \c MonoClassField to act on
9438 * \returns \c MonoType of the field.
9441 mono_field_get_type (MonoClassField *field)
9444 MonoType *type = mono_field_get_type_checked (field, &error);
9445 if (!mono_error_ok (&error)) {
9446 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9447 mono_error_cleanup (&error);
9454 * mono_field_get_type_checked:
9455 * \param field the \c MonoClassField to act on
9456 * \param error used to return any error found while retrieving \p field type
9458 * \returns \c MonoType of the field.
9461 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9465 mono_field_resolve_type (field, error);
9470 * mono_field_get_parent:
9471 * \param field the \c MonoClassField to act on
9473 * \returns \c MonoClass where the field was defined.
9476 mono_field_get_parent (MonoClassField *field)
9478 return field->parent;
9482 * mono_field_get_flags;
9483 * \param field the \c MonoClassField to act on
9485 * The metadata flags for a field are encoded using the
9486 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9488 * \returns The flags for the field.
9491 mono_field_get_flags (MonoClassField *field)
9494 return mono_field_resolve_flags (field);
9495 return field->type->attrs;
9499 * mono_field_get_offset:
9500 * \param field the \c MonoClassField to act on
9502 * \returns The field offset.
9505 mono_field_get_offset (MonoClassField *field)
9507 return field->offset;
9511 mono_field_get_rva (MonoClassField *field)
9515 MonoClass *klass = field->parent;
9516 MonoFieldDefaultValue *def_values;
9518 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9520 def_values = mono_class_get_field_def_values (klass);
9522 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9524 mono_class_set_field_def_values (klass, def_values);
9527 field_index = mono_field_get_index (field);
9529 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9530 int first_field_idx = mono_class_get_first_field_idx (klass);
9531 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9533 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9534 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9537 return def_values [field_index].data;
9541 * mono_field_get_data:
9542 * \param field the \c MonoClassField to act on
9544 * \returns A pointer to the metadata constant value or to the field
9545 * data if it has an RVA flag.
9548 mono_field_get_data (MonoClassField *field)
9550 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9551 MonoTypeEnum def_type;
9553 return mono_class_get_field_default_value (field, &def_type);
9554 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9555 return mono_field_get_rva (field);
9562 * mono_property_get_name:
9563 * \param prop the \c MonoProperty to act on
9564 * \returns The name of the property
9567 mono_property_get_name (MonoProperty *prop)
9573 * mono_property_get_set_method
9574 * \param prop the \c MonoProperty to act on.
9575 * \returns The setter method of the property, a \c MonoMethod.
9578 mono_property_get_set_method (MonoProperty *prop)
9584 * mono_property_get_get_method
9585 * \param prop the MonoProperty to act on.
9586 * \returns The getter method of the property (A \c MonoMethod)
9589 mono_property_get_get_method (MonoProperty *prop)
9595 * mono_property_get_parent:
9596 * \param prop the \c MonoProperty to act on.
9597 * \returns The \c MonoClass where the property was defined.
9600 mono_property_get_parent (MonoProperty *prop)
9602 return prop->parent;
9606 * mono_property_get_flags:
9607 * \param prop the \c MonoProperty to act on.
9609 * The metadata flags for a property are encoded using the
9610 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9612 * \returns The flags for the property.
9615 mono_property_get_flags (MonoProperty *prop)
9621 * mono_event_get_name:
9622 * \param event the MonoEvent to act on
9623 * \returns The name of the event.
9626 mono_event_get_name (MonoEvent *event)
9632 * mono_event_get_add_method:
9633 * \param event The \c MonoEvent to act on.
9634 * \returns The \c add method for the event, a \c MonoMethod.
9637 mono_event_get_add_method (MonoEvent *event)
9643 * mono_event_get_remove_method:
9644 * \param event The \c MonoEvent to act on.
9645 * \returns The \c remove method for the event, a \c MonoMethod.
9648 mono_event_get_remove_method (MonoEvent *event)
9650 return event->remove;
9654 * mono_event_get_raise_method:
9655 * \param event The \c MonoEvent to act on.
9656 * \returns The \c raise method for the event, a \c MonoMethod.
9659 mono_event_get_raise_method (MonoEvent *event)
9661 return event->raise;
9665 * mono_event_get_parent:
9666 * \param event the MonoEvent to act on.
9667 * \returns The \c MonoClass where the event is defined.
9670 mono_event_get_parent (MonoEvent *event)
9672 return event->parent;
9676 * mono_event_get_flags
9677 * \param event the \c MonoEvent to act on.
9679 * The metadata flags for an event are encoded using the
9680 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9682 * \returns The flags for the event.
9685 mono_event_get_flags (MonoEvent *event)
9687 return event->attrs;
9691 * mono_class_get_method_from_name:
9692 * \param klass where to look for the method
9693 * \param name name of the method
9694 * \param param_count number of parameters. -1 for any number.
9696 * Obtains a \c MonoMethod with a given name and number of parameters.
9697 * It only works if there are no multiple signatures for any given method name.
9700 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9702 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9706 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9708 MonoMethod *res = NULL;
9711 /* Search directly in the metadata to avoid calling setup_methods () */
9712 int first_idx = mono_class_get_first_method_idx (klass);
9713 int mcount = mono_class_get_method_count (klass);
9714 for (i = 0; i < mcount; ++i) {
9716 guint32 cols [MONO_METHOD_SIZE];
9718 MonoMethodSignature *sig;
9720 /* first_idx points into the methodptr table */
9721 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9723 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9724 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9726 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9729 if (param_count == -1) {
9733 sig = mono_method_signature_checked (method, &error);
9735 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9738 if (sig->param_count == param_count) {
9749 * mono_class_get_method_from_name_flags:
9750 * \param klass where to look for the method
9751 * \param name_space name of the method
9752 * \param param_count number of parameters. -1 for any number.
9753 * \param flags flags which must be set in the method
9755 * Obtains a \c MonoMethod with a given name and number of parameters.
9756 * It only works if there are no multiple signatures for any given method name.
9759 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9761 MonoMethod *res = NULL;
9764 mono_class_init (klass);
9766 if (mono_class_is_ginst (klass) && !klass->methods) {
9767 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9770 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9771 if (!mono_error_ok (&error))
9772 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9777 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9778 mono_class_setup_methods (klass);
9780 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9781 See mono/tests/array_load_exception.il
9782 FIXME we should better report this error to the caller
9784 if (!klass->methods)
9786 int mcount = mono_class_get_method_count (klass);
9787 for (i = 0; i < mcount; ++i) {
9788 MonoMethod *method = klass->methods [i];
9790 if (method->name[0] == name [0] &&
9791 !strcmp (name, method->name) &&
9792 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9793 ((method->flags & flags) == flags)) {
9800 res = find_method_in_metadata (klass, name, param_count, flags);
9807 * mono_class_set_failure:
9808 * \param klass class in which the failure was detected
9809 * \param ex_type the kind of exception/error to be thrown (later)
9810 * \param ex_data exception data (specific to each type of exception/error)
9812 * Keep a detected failure informations in the class for later processing.
9813 * Note that only the first failure is kept.
9815 * LOCKING: Acquires the loader lock.
9818 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9820 g_assert (boxed_error != NULL);
9822 if (mono_class_has_failure (klass))
9825 mono_loader_lock ();
9826 klass->has_failure = 1;
9827 mono_class_set_exception_data (klass, boxed_error);
9828 mono_loader_unlock ();
9834 mono_class_has_failure (const MonoClass *klass)
9836 g_assert (klass != NULL);
9837 return klass->has_failure != 0;
9842 * mono_class_set_type_load_failure:
9843 * \param klass class in which the failure was detected
9844 * \param fmt \c printf -style error message string.
9846 * Collect detected failure informaion in the class for later processing.
9847 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9848 * Note that only the first failure is kept.
9850 * LOCKING: Acquires the loader lock.
9852 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9855 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9857 MonoError prepare_error;
9860 if (mono_class_has_failure (klass))
9863 error_init (&prepare_error);
9865 va_start (args, fmt);
9866 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9869 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9870 mono_error_cleanup (&prepare_error);
9871 return mono_class_set_failure (klass, box);
9875 * mono_classes_init:
9877 * Initialize the resources used by this module.
9880 mono_classes_init (void)
9882 mono_os_mutex_init (&classes_mutex);
9884 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9885 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9887 mono_counters_register ("MonoClassDef count",
9888 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9889 mono_counters_register ("MonoClassGtd count",
9890 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9891 mono_counters_register ("MonoClassGenericInst count",
9892 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9893 mono_counters_register ("MonoClassGenericParam count",
9894 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9895 mono_counters_register ("MonoClassArray count",
9896 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9897 mono_counters_register ("MonoClassPointer count",
9898 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9899 mono_counters_register ("Inflated methods size",
9900 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9901 mono_counters_register ("Inflated classes size",
9902 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9903 mono_counters_register ("MonoClass size",
9904 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9908 * mono_classes_cleanup:
9910 * Free the resources used by this module.
9913 mono_classes_cleanup (void)
9915 mono_native_tls_free (setup_fields_tls_id);
9916 mono_native_tls_free (init_pending_tls_id);
9918 if (global_interface_bitset)
9919 mono_bitset_free (global_interface_bitset);
9920 global_interface_bitset = NULL;
9921 mono_os_mutex_destroy (&classes_mutex);
9925 * mono_class_get_exception_for_failure:
9926 * \param klass class in which the failure was detected
9928 * \returns a constructed MonoException than the caller can then throw
9929 * using mono_raise_exception - or NULL if no failure is present (or
9930 * doesn't result in an exception).
9933 mono_class_get_exception_for_failure (MonoClass *klass)
9935 if (!mono_class_has_failure (klass))
9937 MonoError unboxed_error;
9938 error_init (&unboxed_error);
9939 mono_error_set_for_class_failure (&unboxed_error, klass);
9940 return mono_error_convert_to_exception (&unboxed_error);
9944 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9946 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9947 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9949 if (outer_klass == inner_klass)
9951 inner_klass = inner_klass->nested_in;
9952 } while (inner_klass);
9957 mono_class_get_generic_type_definition (MonoClass *klass)
9959 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9960 return gklass ? gklass->container_class : klass;
9964 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9966 * Generic instantiations are ignored for all super types of @klass.
9968 * Visibility checks ignoring generic instantiations.
9971 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9974 klass = mono_class_get_generic_type_definition (klass);
9975 parent = mono_class_get_generic_type_definition (parent);
9976 mono_class_setup_supertypes (klass);
9978 for (i = 0; i < klass->idepth; ++i) {
9979 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9985 * Subtype can only access parent members with family protection if the site object
9986 * is subclass of Subtype. For example:
9987 * class A { protected int x; }
9989 * void valid_access () {
9993 * void invalid_access () {
10000 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10002 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10005 if (context_klass == NULL)
10007 /*if access_klass is not member_klass context_klass must be type compat*/
10008 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10014 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10017 if (accessing == accessed)
10019 if (!accessed || !accessing)
10022 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10023 * anywhere so untrusted friends are not safe to access platform's code internals */
10024 if (mono_security_core_clr_enabled ()) {
10025 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10029 mono_assembly_load_friends (accessed);
10030 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10031 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10032 /* Be conservative with checks */
10033 if (!friend_->name)
10035 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10037 if (friend_->public_key_token [0]) {
10038 if (!accessing->aname.public_key_token [0])
10040 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10049 * If klass is a generic type or if it is derived from a generic type, return the
10050 * MonoClass of the generic definition
10051 * Returns NULL if not found
10054 get_generic_definition_class (MonoClass *klass)
10057 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10058 if (gklass && gklass->container_class)
10059 return gklass->container_class;
10060 klass = klass->parent;
10066 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10069 for (i = 0; i < ginst->type_argc; ++i) {
10070 MonoType *type = ginst->type_argv[i];
10071 switch (type->type) {
10072 case MONO_TYPE_SZARRAY:
10073 if (!can_access_type (access_klass, type->data.klass))
10076 case MONO_TYPE_ARRAY:
10077 if (!can_access_type (access_klass, type->data.array->eklass))
10080 case MONO_TYPE_PTR:
10081 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10084 case MONO_TYPE_CLASS:
10085 case MONO_TYPE_VALUETYPE:
10086 case MONO_TYPE_GENERICINST:
10087 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10097 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10101 if (access_klass == member_klass)
10104 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10107 if (access_klass->element_class && !access_klass->enumtype)
10108 access_klass = access_klass->element_class;
10110 if (member_klass->element_class && !member_klass->enumtype)
10111 member_klass = member_klass->element_class;
10113 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10115 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10118 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10121 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10124 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10127 /*Non nested type with nested visibility. We just fail it.*/
10128 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10131 switch (access_level) {
10132 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10133 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10135 case TYPE_ATTRIBUTE_PUBLIC:
10138 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10141 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10142 return is_nesting_type (member_klass, access_klass);
10144 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10145 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10147 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10148 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10150 case TYPE_ATTRIBUTE_NESTED_FAM_AND_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);
10154 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10155 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10156 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10161 /* FIXME: check visibility of type, too */
10163 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10165 MonoClass *member_generic_def;
10166 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10169 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10170 if (((access_gklass && access_gklass->container_class) ||
10171 mono_class_is_gtd (access_klass)) &&
10172 (member_generic_def = get_generic_definition_class (member_klass))) {
10173 MonoClass *access_container;
10175 if (mono_class_is_gtd (access_klass))
10176 access_container = access_klass;
10178 access_container = access_gklass->container_class;
10180 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10184 /* Partition I 8.5.3.2 */
10185 /* the access level values are the same for fields and methods */
10186 switch (access_level) {
10187 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10188 /* same compilation unit */
10189 return access_klass->image == member_klass->image;
10190 case FIELD_ATTRIBUTE_PRIVATE:
10191 return access_klass == member_klass;
10192 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10193 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10194 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10197 case FIELD_ATTRIBUTE_ASSEMBLY:
10198 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10199 case FIELD_ATTRIBUTE_FAMILY:
10200 if (is_valid_family_access (access_klass, member_klass, context_klass))
10203 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10204 if (is_valid_family_access (access_klass, member_klass, context_klass))
10206 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10207 case FIELD_ATTRIBUTE_PUBLIC:
10214 * mono_method_can_access_field:
10215 * \param method Method that will attempt to access the field
10216 * \param field the field to access
10218 * Used to determine if a method is allowed to access the specified field.
10220 * \returns TRUE if the given \p method is allowed to access the \p field while following
10221 * the accessibility rules of the CLI.
10224 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10226 /* FIXME: check all overlapping fields */
10227 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10229 MonoClass *nested = method->klass->nested_in;
10231 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10234 nested = nested->nested_in;
10241 * mono_method_can_access_method:
10242 * \param method Method that will attempt to access the other method
10243 * \param called the method that we want to probe for accessibility.
10245 * Used to determine if the \p method is allowed to access the specified \p called method.
10247 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10248 * the accessibility rules of the CLI.
10251 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10253 method = mono_method_get_method_definition (method);
10254 called = mono_method_get_method_definition (called);
10255 return mono_method_can_access_method_full (method, called, NULL);
10259 * mono_method_can_access_method_full:
10260 * @method: The caller method
10261 * @called: The called method
10262 * @context_klass: The static type on stack of the owner @called object used
10264 * This function must be used with instance calls, as they have more strict family accessibility.
10265 * It can be used with static methods, but context_klass should be NULL.
10267 * Returns: TRUE if caller have proper visibility and acessibility to @called
10270 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10272 /* Wrappers are except from access checks */
10273 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10276 MonoClass *access_class = method->klass;
10277 MonoClass *member_class = called->klass;
10278 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10280 MonoClass *nested = access_class->nested_in;
10282 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10285 nested = nested->nested_in;
10292 can = can_access_type (access_class, member_class);
10294 MonoClass *nested = access_class->nested_in;
10296 can = can_access_type (nested, member_class);
10299 nested = nested->nested_in;
10306 if (called->is_inflated) {
10307 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10308 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10317 * mono_method_can_access_field_full:
10318 * @method: The caller method
10319 * @field: The accessed field
10320 * @context_klass: The static type on stack of the owner @field object used
10322 * This function must be used with instance fields, as they have more strict family accessibility.
10323 * It can be used with static fields, but context_klass should be NULL.
10325 * Returns: TRUE if caller have proper visibility and acessibility to @field
10328 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10330 MonoClass *access_class = method->klass;
10331 MonoClass *member_class = field->parent;
10332 /* FIXME: check all overlapping fields */
10333 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10335 MonoClass *nested = access_class->nested_in;
10337 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10340 nested = nested->nested_in;
10347 can = can_access_type (access_class, member_class);
10349 MonoClass *nested = access_class->nested_in;
10351 can = can_access_type (nested, member_class);
10354 nested = nested->nested_in;
10364 * mono_class_can_access_class:
10365 * @source_class: The source class
10366 * @target_class: The accessed class
10368 * This function returns is @target_class is visible to @source_class
10370 * Returns: TRUE if source have proper visibility and acessibility to target
10373 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10375 return can_access_type (source_class, target_class);
10379 * mono_type_is_valid_enum_basetype:
10380 * \param type The MonoType to check
10381 * \returns TRUE if the type can be used as the basetype of an enum
10383 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10384 switch (type->type) {
10387 case MONO_TYPE_BOOLEAN:
10390 case MONO_TYPE_CHAR:
10404 * mono_class_is_valid_enum:
10405 * \param klass An enum class to be validated
10407 * This method verify the required properties an enum should have.
10409 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10410 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10411 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10413 * \returns TRUE if the informed enum class is valid
10416 mono_class_is_valid_enum (MonoClass *klass)
10418 MonoClassField * field;
10419 gpointer iter = NULL;
10420 gboolean found_base_field = FALSE;
10422 g_assert (klass->enumtype);
10423 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10424 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10428 if (!mono_class_is_auto_layout (klass))
10431 while ((field = mono_class_get_fields (klass, &iter))) {
10432 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10433 if (found_base_field)
10435 found_base_field = TRUE;
10436 if (!mono_type_is_valid_enum_basetype (field->type))
10441 if (!found_base_field)
10444 if (mono_class_get_method_count (klass) > 0)
10451 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10453 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10457 * mono_class_setup_interface_id:
10459 * Initializes MonoClass::interface_id if required.
10461 * LOCKING: Acquires the loader lock.
10464 mono_class_setup_interface_id (MonoClass *klass)
10466 mono_loader_lock ();
10467 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10468 klass->interface_id = mono_get_unique_iid (klass);
10469 mono_loader_unlock ();
10473 * mono_class_setup_interfaces:
10475 * Initialize klass->interfaces/interfaces_count.
10476 * LOCKING: Acquires the loader lock.
10477 * This function can fail the type.
10480 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10482 int i, interface_count;
10483 MonoClass **interfaces;
10485 error_init (error);
10487 if (klass->interfaces_inited)
10490 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10491 MonoType *args [1];
10493 /* generic IList, ICollection, IEnumerable */
10494 interface_count = 2;
10495 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10497 args [0] = &klass->element_class->byval_arg;
10498 interfaces [0] = mono_class_bind_generic_parameters (
10499 mono_defaults.generic_ilist_class, 1, args, FALSE);
10500 interfaces [1] = mono_class_bind_generic_parameters (
10501 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10502 } else if (mono_class_is_ginst (klass)) {
10503 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10505 mono_class_setup_interfaces (gklass, error);
10506 if (!mono_error_ok (error)) {
10507 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10511 interface_count = gklass->interface_count;
10512 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10513 for (i = 0; i < interface_count; i++) {
10514 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10515 if (!mono_error_ok (error)) {
10516 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10521 interface_count = 0;
10525 mono_loader_lock ();
10526 if (!klass->interfaces_inited) {
10527 klass->interface_count = interface_count;
10528 klass->interfaces = interfaces;
10530 mono_memory_barrier ();
10532 klass->interfaces_inited = TRUE;
10534 mono_loader_unlock ();
10538 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10540 MonoClass *klass = field->parent;
10541 MonoImage *image = klass->image;
10542 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10544 int field_idx = field - klass->fields;
10546 error_init (error);
10549 MonoClassField *gfield = >d->fields [field_idx];
10550 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10551 if (!mono_error_ok (error)) {
10552 char *full_name = mono_type_get_full_name (gtd);
10553 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));
10554 g_free (full_name);
10557 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10558 if (!mono_error_ok (error)) {
10559 char *full_name = mono_type_get_full_name (klass);
10560 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));
10561 g_free (full_name);
10565 guint32 cols [MONO_FIELD_SIZE];
10566 MonoGenericContainer *container = NULL;
10567 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10569 /*FIXME, in theory we do not lazy load SRE fields*/
10570 g_assert (!image_is_dynamic (image));
10572 if (mono_class_is_gtd (klass)) {
10573 container = mono_class_get_generic_container (klass);
10575 container = mono_class_get_generic_container (gtd);
10576 g_assert (container);
10579 /* first_field_idx and idx points into the fieldptr table */
10580 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10582 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10583 char *full_name = mono_type_get_full_name (klass);
10584 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10585 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10586 g_free (full_name);
10590 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10592 mono_metadata_decode_value (sig, &sig);
10593 /* FIELD signature == 0x06 */
10594 g_assert (*sig == 0x06);
10596 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10598 char *full_name = mono_type_get_full_name (klass);
10599 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));
10600 g_free (full_name);
10603 mono_memory_barrier ();
10604 field->type = ftype;
10608 mono_field_resolve_flags (MonoClassField *field)
10610 MonoClass *klass = field->parent;
10611 MonoImage *image = klass->image;
10612 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10613 int field_idx = field - klass->fields;
10616 MonoClassField *gfield = >d->fields [field_idx];
10617 return mono_field_get_flags (gfield);
10619 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10621 /*FIXME, in theory we do not lazy load SRE fields*/
10622 g_assert (!image_is_dynamic (image));
10624 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10629 * mono_class_get_fields_lazy:
10630 * \param klass the MonoClass to act on
10632 * This routine is an iterator routine for retrieving the fields in a class.
10633 * Only minimal information about fields are loaded. Accessors must be used
10634 * for all MonoClassField returned.
10636 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10637 * iterate over all of the elements. When no more values are
10638 * available, the return value is NULL.
10640 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10643 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10645 MonoClassField* field;
10649 mono_class_setup_basic_field_info (klass);
10650 if (!klass->fields)
10652 /* start from the first */
10653 if (mono_class_get_field_count (klass)) {
10654 *iter = &klass->fields [0];
10655 return (MonoClassField *)*iter;
10661 field = (MonoClassField *)*iter;
10663 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10665 return (MonoClassField *)*iter;
10671 mono_class_full_name (MonoClass *klass)
10673 return mono_type_full_name (&klass->byval_arg);
10676 /* Declare all shared lazy type lookup functions */
10677 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10680 * mono_method_get_base_method:
10681 * \param method a method
10682 * \param definition if true, get the definition
10683 * \param error set on failure
10685 * Given a virtual method associated with a subclass, return the corresponding
10686 * method from an ancestor. If \p definition is FALSE, returns the method in the
10687 * superclass of the given method. If \p definition is TRUE, return the method
10688 * in the ancestor class where it was first declared. The type arguments will
10689 * be inflated in the ancestor classes. If the method is not associated with a
10690 * class, or isn't virtual, returns the method itself. On failure returns NULL
10691 * and sets \p error.
10694 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10696 MonoClass *klass, *parent;
10697 MonoGenericContext *generic_inst = NULL;
10698 MonoMethod *result = NULL;
10701 if (method->klass == NULL)
10704 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10705 MONO_CLASS_IS_INTERFACE (method->klass) ||
10706 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10709 slot = mono_method_get_vtable_slot (method);
10713 klass = method->klass;
10714 if (mono_class_is_ginst (klass)) {
10715 generic_inst = mono_class_get_context (klass);
10716 klass = mono_class_get_generic_class (klass)->container_class;
10721 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10722 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10723 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10724 or klass is the generic container class and generic_inst is the instantiation.
10726 when we go to the parent, if the parent is an open constructed type, we need to
10727 replace the type parameters by the definitions from the generic_inst, and then take it
10728 apart again into the klass and the generic_inst.
10730 For cases like this:
10731 class C<T> : B<T, int> {
10732 public override void Foo () { ... }
10734 class B<U,V> : A<HashMap<U,V>> {
10735 public override void Foo () { ... }
10738 public virtual void Foo () { ... }
10741 if at each iteration the parent isn't open, we can skip inflating it. if at some
10742 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10745 MonoGenericContext *parent_inst = NULL;
10746 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10747 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10748 return_val_if_nok (error, NULL);
10750 if (mono_class_is_ginst (parent)) {
10751 parent_inst = mono_class_get_context (parent);
10752 parent = mono_class_get_generic_class (parent)->container_class;
10755 mono_class_setup_vtable (parent);
10756 if (parent->vtable_size <= slot)
10759 generic_inst = parent_inst;
10762 klass = klass->parent;
10765 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10766 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10767 return_val_if_nok (error, NULL);
10769 generic_inst = NULL;
10771 if (mono_class_is_ginst (klass)) {
10772 generic_inst = mono_class_get_context (klass);
10773 klass = mono_class_get_generic_class (klass)->container_class;
10778 if (generic_inst) {
10779 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10780 return_val_if_nok (error, NULL);
10783 if (klass == method->klass)
10786 /*This is possible if definition == FALSE.
10787 * Do it here to be really sure we don't read invalid memory.
10789 if (slot >= klass->vtable_size)
10792 mono_class_setup_vtable (klass);
10794 result = klass->vtable [slot];
10795 if (result == NULL) {
10796 /* It is an abstract method */
10797 gboolean found = FALSE;
10798 gpointer iter = NULL;
10799 while ((result = mono_class_get_methods (klass, &iter))) {
10800 if (result->slot == slot) {
10805 /* found might be FALSE if we looked in an abstract class
10806 * that doesn't override an abstract method of its
10808 * abstract class Base {
10809 * public abstract void Foo ();
10811 * abstract class Derived : Base { }
10812 * class Child : Derived {
10813 * public override void Foo () { }
10816 * if m was Child.Foo and we ask for the base method,
10817 * then we get here with klass == Derived and found == FALSE
10819 /* but it shouldn't be the case that if we're looking
10820 * for the definition and didn't find a result; the
10821 * loop above should've taken us as far as we could
10823 g_assert (!(definition && !found));
10828 g_assert (result != NULL);