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:
618 * \returns The string representation for type as it would be represented in IL code.
621 mono_type_get_name (MonoType *type)
623 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
627 * mono_type_get_underlying_type:
630 * Returns: The MonoType for the underlying integer type if @type
631 * is an enum and byref is false, otherwise the type itself.
634 mono_type_get_underlying_type (MonoType *type)
636 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
637 return mono_class_enum_basetype (type->data.klass);
638 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
639 return mono_class_enum_basetype (type->data.generic_class->container_class);
644 * mono_class_is_open_constructed_type:
647 * \returns TRUE if type represents a generics open constructed type.
648 * IOW, not all type parameters required for the instantiation have
649 * been provided or it's a generic type definition.
651 * An open constructed type means it's a non realizable type. Not to
652 * be mixed up with an abstract type - we can't cast or dispatch to
653 * an open type, for example.
656 mono_class_is_open_constructed_type (MonoType *t)
662 case MONO_TYPE_SZARRAY:
663 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
664 case MONO_TYPE_ARRAY:
665 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
667 return mono_class_is_open_constructed_type (t->data.type);
668 case MONO_TYPE_GENERICINST:
669 return t->data.generic_class->context.class_inst->is_open;
670 case MONO_TYPE_CLASS:
671 case MONO_TYPE_VALUETYPE:
672 return mono_class_is_gtd (t->data.klass);
679 This is a simple function to catch the most common bad instances of generic types.
680 Specially those that might lead to further failures in the runtime.
683 is_valid_generic_argument (MonoType *type)
685 switch (type->type) {
687 //case MONO_TYPE_TYPEDBYREF:
695 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
699 switch (type->type) {
700 case MONO_TYPE_MVAR: {
702 int num = mono_type_get_generic_param_num (type);
703 MonoGenericInst *inst = context->method_inst;
706 if (num >= inst->type_argc) {
707 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
708 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
709 num, info ? info->name : "", inst->type_argc);
713 if (!is_valid_generic_argument (inst->type_argv [num])) {
714 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
715 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
716 num, info ? info->name : "", inst->type_argv [num]->type);
720 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
721 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
722 * ->byref and ->attrs from @type are propagated to the returned type.
724 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
725 nt->byref = type->byref;
726 nt->attrs = type->attrs;
729 case MONO_TYPE_VAR: {
731 int num = mono_type_get_generic_param_num (type);
732 MonoGenericInst *inst = context->class_inst;
735 if (num >= inst->type_argc) {
736 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
737 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
738 num, info ? info->name : "", inst->type_argc);
741 if (!is_valid_generic_argument (inst->type_argv [num])) {
742 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
743 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
744 num, info ? info->name : "", inst->type_argv [num]->type);
747 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
748 nt->byref = type->byref;
749 nt->attrs = type->attrs;
752 case MONO_TYPE_SZARRAY: {
753 MonoClass *eclass = type->data.klass;
754 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
755 if (!inflated || !mono_error_ok (error))
757 nt = mono_metadata_type_dup (image, type);
758 nt->data.klass = mono_class_from_mono_type (inflated);
759 mono_metadata_free_type (inflated);
762 case MONO_TYPE_ARRAY: {
763 MonoClass *eclass = type->data.array->eklass;
764 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
765 if (!inflated || !mono_error_ok (error))
767 nt = mono_metadata_type_dup (image, type);
768 nt->data.array->eklass = mono_class_from_mono_type (inflated);
769 mono_metadata_free_type (inflated);
772 case MONO_TYPE_GENERICINST: {
773 MonoGenericClass *gclass = type->data.generic_class;
774 MonoGenericInst *inst;
776 if (!gclass->context.class_inst->is_open)
779 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
780 return_val_if_nok (error, NULL);
782 if (inst != gclass->context.class_inst)
783 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
785 if (gclass == type->data.generic_class)
788 nt = mono_metadata_type_dup (image, type);
789 nt->data.generic_class = gclass;
792 case MONO_TYPE_CLASS:
793 case MONO_TYPE_VALUETYPE: {
794 MonoClass *klass = type->data.klass;
795 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
796 MonoGenericInst *inst;
797 MonoGenericClass *gclass = NULL;
803 /* We can't use context->class_inst directly, since it can have more elements */
804 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
805 return_val_if_nok (error, NULL);
807 if (inst == container->context.class_inst)
810 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
812 nt = mono_metadata_type_dup (image, type);
813 nt->type = MONO_TYPE_GENERICINST;
814 nt->data.generic_class = gclass;
824 mono_generic_class_get_context (MonoGenericClass *gclass)
826 return &gclass->context;
830 mono_class_get_context (MonoClass *klass)
832 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
833 return gklass ? mono_generic_class_get_context (gklass) : NULL;
837 * mono_class_inflate_generic_type_with_mempool:
838 * @mempool: a mempool
840 * @context: a generics context
841 * @error: error context
843 * The same as mono_class_inflate_generic_type, but allocates the MonoType
844 * from mempool if it is non-NULL. If it is NULL, the MonoType is
845 * allocated on the heap and is owned by the caller.
846 * The returned type can potentially be the same as TYPE, so it should not be
847 * modified by the caller, and it should be freed using mono_metadata_free_type ().
850 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
852 MonoType *inflated = NULL;
856 inflated = inflate_generic_type (image, type, context, error);
857 return_val_if_nok (error, NULL);
860 MonoType *shared = mono_metadata_get_shared_type (type);
865 return mono_metadata_type_dup (image, type);
869 mono_stats.inflated_type_count++;
874 * mono_class_inflate_generic_type:
876 * \param context a generics context
877 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
879 * If \p type is a generic type and \p context is not NULL, instantiate it using the
880 * generics context \p context.
882 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
883 * on the heap and is owned by the caller. Returns NULL on error.
886 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
890 result = mono_class_inflate_generic_type_checked (type, context, &error);
891 mono_error_cleanup (&error);
896 * mono_class_inflate_generic_type:
898 * @context: a generics context
899 * @error: error context to use
901 * If @type is a generic type and @context is not NULL, instantiate it using the
902 * generics context @context.
904 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
905 * on the heap and is owned by the caller.
908 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
910 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
914 * mono_class_inflate_generic_type_no_copy:
916 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
920 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
922 MonoType *inflated = NULL;
926 inflated = inflate_generic_type (image, type, context, error);
927 return_val_if_nok (error, NULL);
933 mono_stats.inflated_type_count++;
938 * mono_class_inflate_generic_class:
940 * Inflate the class @gklass with @context. Set @error on failure.
943 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
948 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
949 return_val_if_nok (error, NULL);
951 res = mono_class_from_mono_type (inflated);
952 mono_metadata_free_type (inflated);
957 static MonoGenericContext
958 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
960 MonoGenericInst *class_inst = NULL;
961 MonoGenericInst *method_inst = NULL;
962 MonoGenericContext res = { NULL, NULL };
966 if (context->class_inst) {
967 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
968 if (!mono_error_ok (error))
972 if (context->method_inst) {
973 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
974 if (!mono_error_ok (error))
978 res.class_inst = class_inst;
979 res.method_inst = method_inst;
985 * mono_class_inflate_generic_method:
986 * \param method a generic method
987 * \param context a generics context
989 * Instantiate the generic method \p method using the generics context \p context.
991 * \returns The new instantiated method
994 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
996 return mono_class_inflate_generic_method_full (method, NULL, context);
1000 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1002 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1006 * mono_class_inflate_generic_method_full:
1008 * Instantiate method \p method with the generic context \p context.
1009 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1010 * Use mono_method_signature() and mono_method_get_header() to get the correct values.
1013 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1016 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1017 if (!mono_error_ok (&error))
1018 /*FIXME do proper error handling - on this case, kill this function. */
1019 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1025 * mono_class_inflate_generic_method_full_checked:
1026 * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1029 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1032 MonoMethodInflated *iresult, *cached;
1033 MonoMethodSignature *sig;
1034 MonoGenericContext tmp_context;
1038 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1039 while (method->is_inflated) {
1040 MonoGenericContext *method_context = mono_method_get_context (method);
1041 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1043 tmp_context = inflate_generic_context (method_context, context, error);
1044 return_val_if_nok (error, NULL);
1046 context = &tmp_context;
1048 if (mono_metadata_generic_context_equal (method_context, context))
1051 method = imethod->declaring;
1055 * A method only needs to be inflated if the context has argument for which it is
1058 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1059 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1062 if (!((method->is_generic && context->method_inst) ||
1063 (mono_class_is_gtd (method->klass) && context->class_inst)))
1066 iresult = g_new0 (MonoMethodInflated, 1);
1067 iresult->context = *context;
1068 iresult->declaring = method;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1075 if (mono_class_is_gtd (iresult->declaring->klass))
1076 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1078 /* This can happen with some callers like mono_object_get_virtual_method () */
1079 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1080 iresult->context.class_inst = NULL;
1082 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1085 mono_image_set_lock (set);
1086 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1087 mono_image_set_unlock (set);
1091 return (MonoMethod*)cached;
1094 mono_stats.inflated_method_count++;
1096 inflated_methods_size += sizeof (MonoMethodInflated);
1098 sig = mono_method_signature (method);
1100 char *name = mono_type_get_full_name (method->klass);
1101 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1107 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1109 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1112 result = (MonoMethod *) iresult;
1113 result->is_inflated = TRUE;
1114 result->is_generic = FALSE;
1115 result->sre_method = FALSE;
1116 result->signature = NULL;
1118 if (method->wrapper_type) {
1119 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1120 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1121 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1123 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1124 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1127 if (iresult->context.method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1138 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1139 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1143 if (mono_class_is_gtd (method->klass))
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1170 mono_image_set_lock (set);
1171 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1173 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1174 iresult->owner = set;
1177 mono_image_set_unlock (set);
1179 return (MonoMethod*)cached;
1187 * mono_get_inflated_method:
1189 * Obsolete. We keep it around since it's mentioned in the public API.
1192 mono_get_inflated_method (MonoMethod *method)
1198 * mono_method_get_context_general:
1200 * @uninflated: handle uninflated methods?
1202 * Returns the generic context of a method or NULL if it doesn't have
1203 * one. For an inflated method that's the context stored in the
1204 * method. Otherwise it's in the method's generic container or in the
1205 * generic container of the method's class.
1208 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1210 if (method->is_inflated) {
1211 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1212 return &imethod->context;
1216 if (method->is_generic)
1217 return &(mono_method_get_generic_container (method)->context);
1218 if (mono_class_is_gtd (method->klass))
1219 return &mono_class_get_generic_container (method->klass)->context;
1224 * mono_method_get_context:
1227 * Returns the generic context for method if it's inflated, otherwise
1231 mono_method_get_context (MonoMethod *method)
1233 return mono_method_get_context_general (method, FALSE);
1237 * mono_method_get_generic_container:
1239 * Returns the generic container of METHOD, which should be a generic method definition.
1240 * Returns NULL if METHOD is not a generic method definition.
1241 * LOCKING: Acquires the loader lock.
1243 MonoGenericContainer*
1244 mono_method_get_generic_container (MonoMethod *method)
1246 MonoGenericContainer *container;
1248 if (!method->is_generic)
1251 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1252 g_assert (container);
1258 * mono_method_set_generic_container:
1260 * Sets the generic container of METHOD to CONTAINER.
1261 * LOCKING: Acquires the image lock.
1264 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1266 g_assert (method->is_generic);
1268 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1272 * mono_class_find_enum_basetype:
1273 * \param class The enum class
1275 * Determine the basetype of an enum by iterating through its fields. We do this
1276 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1279 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1281 MonoGenericContainer *container = NULL;
1282 MonoImage *m = klass->image;
1283 const int top = mono_class_get_field_count (klass);
1284 int i, first_field_idx;
1286 g_assert (klass->enumtype);
1290 container = mono_class_try_get_generic_container (klass);
1291 if (mono_class_is_ginst (klass)) {
1292 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1294 container = mono_class_get_generic_container (gklass);
1295 g_assert (container);
1299 * Fetch all the field information.
1301 first_field_idx = mono_class_get_first_field_idx (klass);
1302 for (i = 0; i < top; i++){
1304 guint32 cols [MONO_FIELD_SIZE];
1305 int idx = first_field_idx + i;
1308 /* first_field_idx and idx points into the fieldptr table */
1309 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1311 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1314 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1315 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1319 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1320 mono_metadata_decode_value (sig, &sig);
1321 /* FIELD signature == 0x06 */
1323 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1327 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1331 if (mono_class_is_ginst (klass)) {
1332 //FIXME do we leak here?
1333 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1334 if (!mono_error_ok (error))
1336 ftype->attrs = cols [MONO_FIELD_FLAGS];
1341 mono_error_set_type_load_class (error, klass, "Could not find base type");
1348 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1351 mono_type_has_exceptions (MonoType *type)
1353 switch (type->type) {
1354 case MONO_TYPE_CLASS:
1355 case MONO_TYPE_VALUETYPE:
1356 case MONO_TYPE_SZARRAY:
1357 return mono_class_has_failure (type->data.klass);
1358 case MONO_TYPE_ARRAY:
1359 return mono_class_has_failure (type->data.array->eklass);
1360 case MONO_TYPE_GENERICINST:
1361 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1368 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1370 g_assert (mono_class_has_failure (klass));
1371 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1372 mono_error_set_from_boxed (oerror, box);
1378 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1382 mono_class_alloc (MonoClass *klass, int size)
1384 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1386 return mono_image_set_alloc (gklass->owner, size);
1388 return mono_image_alloc (klass->image, size);
1392 mono_class_alloc0 (MonoClass *klass, int size)
1396 res = mono_class_alloc (klass, size);
1397 memset (res, 0, size);
1401 #define mono_class_new0(klass,struct_type, n_structs) \
1402 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1405 * mono_class_setup_basic_field_info:
1406 * \param class The class to initialize
1408 * Initializes the following fields in MonoClass:
1409 * * klass->fields (only field->parent and field->name)
1410 * * klass->field.count
1411 * * klass->first_field_idx
1412 * LOCKING: Acquires the loader lock
1415 mono_class_setup_basic_field_info (MonoClass *klass)
1417 MonoGenericClass *gklass;
1418 MonoClassField *field;
1419 MonoClassField *fields;
1427 gklass = mono_class_try_get_generic_class (klass);
1428 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1429 image = klass->image;
1432 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1434 * This happens when a generic instance of an unfinished generic typebuilder
1435 * is used as an element type for creating an array type. We can't initialize
1436 * the fields of this class using the fields of gklass, since gklass is not
1437 * finished yet, fields could be added to it later.
1443 mono_class_setup_basic_field_info (gtd);
1445 mono_loader_lock ();
1446 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1447 mono_loader_unlock ();
1450 top = mono_class_get_field_count (klass);
1452 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1455 * Fetch all the field information.
1457 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1458 for (i = 0; i < top; i++) {
1459 field = &fields [i];
1460 field->parent = klass;
1463 field->name = mono_field_get_name (>d->fields [i]);
1465 int idx = first_field_idx + i;
1466 /* first_field_idx and idx points into the fieldptr table */
1467 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1468 /* The name is needed for fieldrefs */
1469 field->name = mono_metadata_string_heap (image, name_idx);
1473 mono_memory_barrier ();
1475 mono_loader_lock ();
1477 klass->fields = fields;
1478 mono_loader_unlock ();
1482 * mono_class_set_failure_causedby_class:
1483 * \param klass the class that is failing
1484 * \param caused_by the class that caused the failure
1485 * \param msg Why \p klass is failing.
1487 * If \p caused_by has a failure, sets a TypeLoadException failure on
1488 * \p klass with message "\p msg, due to: {\p caused_by message}".
1490 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1493 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1495 if (mono_class_has_failure (caused_by)) {
1496 MonoError cause_error;
1497 error_init (&cause_error);
1498 mono_error_set_for_class_failure (&cause_error, caused_by);
1499 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1500 mono_error_cleanup (&cause_error);
1509 * mono_class_setup_fields:
1510 * \p klass The class to initialize
1512 * Initializes klass->fields, computes class layout and sizes.
1513 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1514 * Sets the following fields in \p klass:
1515 * - all the fields initialized by mono_class_init_sizes ()
1516 * - element_class/cast_class (for enums)
1517 * - field->type/offset for all fields
1520 * LOCKING: Acquires the loader lock.
1523 mono_class_setup_fields (MonoClass *klass)
1526 MonoImage *m = klass->image;
1528 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1530 guint32 real_size = 0;
1531 guint32 packing_size = 0;
1533 gboolean explicit_size;
1534 MonoClassField *field;
1535 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1538 if (klass->fields_inited)
1541 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1543 * This happens when a generic instance of an unfinished generic typebuilder
1544 * is used as an element type for creating an array type. We can't initialize
1545 * the fields of this class using the fields of gklass, since gklass is not
1546 * finished yet, fields could be added to it later.
1551 mono_class_setup_basic_field_info (klass);
1552 top = mono_class_get_field_count (klass);
1555 mono_class_setup_fields (gtd);
1556 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1561 if (klass->parent) {
1562 /* For generic instances, klass->parent might not have been initialized */
1563 mono_class_init (klass->parent);
1564 mono_class_setup_fields (klass->parent);
1565 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1567 instance_size = klass->parent->instance_size;
1569 instance_size = sizeof (MonoObject);
1572 /* Get the real size */
1573 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1575 instance_size += real_size;
1578 * This function can recursively call itself.
1579 * Prevent infinite recursion by using a list in TLS.
1581 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1582 if (g_slist_find (init_list, klass))
1584 init_list = g_slist_prepend (init_list, klass);
1585 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1588 * Fetch all the field information.
1590 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1591 for (i = 0; i < top; i++) {
1592 int idx = first_field_idx + i;
1593 field = &klass->fields [i];
1596 mono_field_resolve_type (field, &error);
1597 if (!mono_error_ok (&error)) {
1598 /*mono_field_resolve_type already failed class*/
1599 mono_error_cleanup (&error);
1603 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604 g_assert (field->type);
1607 if (mono_field_is_deleted (field))
1609 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1611 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1612 int offset = uoffset;
1614 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1618 if (offset < -1) { /*-1 is used to encode special static fields */
1619 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1622 if (mono_class_is_gtd (klass)) {
1623 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1627 if (mono_type_has_exceptions (field->type)) {
1628 char *class_name = mono_type_get_full_name (klass);
1629 char *type_name = mono_type_full_name (field->type);
1631 mono_class_set_type_load_failure (klass, "");
1632 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1633 g_free (class_name);
1637 /* The def_value of fields is compute lazily during vtable creation */
1640 if (!mono_class_has_failure (klass)) {
1641 mono_loader_lock ();
1642 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1643 mono_loader_unlock ();
1646 init_list = g_slist_remove (init_list, klass);
1647 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1651 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1654 mono_loader_lock ();
1655 klass->instance_size = cached_info->instance_size;
1656 klass->sizes.class_size = cached_info->class_size;
1657 klass->packing_size = cached_info->packing_size;
1658 klass->min_align = cached_info->min_align;
1659 klass->blittable = cached_info->blittable;
1660 klass->has_references = cached_info->has_references;
1661 klass->has_static_refs = cached_info->has_static_refs;
1662 klass->no_special_static_fields = cached_info->no_special_static_fields;
1663 mono_loader_unlock ();
1666 if (!klass->size_inited)
1667 mono_class_setup_fields (klass);
1672 * mono_class_init_sizes:
1674 * Initializes the size related fields of @klass without loading all field data if possible.
1675 * Sets the following fields in @klass:
1677 * - sizes.class_size
1684 * Can fail the class.
1686 * LOCKING: Acquires the loader lock.
1689 mono_class_init_sizes (MonoClass *klass)
1691 MonoCachedClassInfo cached_info;
1692 gboolean has_cached_info;
1694 if (klass->size_inited)
1697 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1699 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1703 * mono_type_get_basic_type_from_generic:
1706 * Returns a closed type corresponding to the possibly open type
1710 mono_type_get_basic_type_from_generic (MonoType *type)
1712 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1713 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1714 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1715 return &mono_defaults.object_class->byval_arg;
1720 class_has_references (MonoClass *klass)
1722 mono_class_init_sizes (klass);
1725 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1726 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1729 return klass->has_references;
1733 type_has_references (MonoClass *klass, MonoType *ftype)
1735 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1737 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1738 MonoGenericParam *gparam = ftype->data.generic_param;
1740 if (gparam->gshared_constraint)
1741 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1747 * mono_class_layout_fields:
1749 * @base_instance_size: base instance size
1752 * This contains the common code for computing the layout of classes and sizes.
1753 * This should only be called from mono_class_setup_fields () and
1754 * typebuilder_setup_fields ().
1756 * LOCKING: Acquires the loader lock
1759 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1762 const int top = mono_class_get_field_count (klass);
1763 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1764 guint32 pass, passes, real_size;
1765 gboolean gc_aware_layout = FALSE;
1766 gboolean has_static_fields = FALSE;
1767 gboolean has_references = FALSE;
1768 gboolean has_static_refs = FALSE;
1769 MonoClassField *field;
1771 int instance_size = base_instance_size;
1772 int class_size, min_align;
1774 gboolean *fields_has_references;
1777 * We want to avoid doing complicated work inside locks, so we compute all the required
1778 * information and write it to @klass inside a lock.
1780 if (klass->fields_inited)
1783 if ((packing_size & 0xffffff00) != 0) {
1784 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1788 if (klass->parent) {
1789 min_align = klass->parent->min_align;
1790 /* we use | since it may have been set already */
1791 has_references = klass->has_references | klass->parent->has_references;
1795 /* We can't really enable 16 bytes alignment until the GC supports it.
1796 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1797 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1798 Bug #506144 is an example of this issue.
1800 if (klass->simd_type)
1805 * When we do generic sharing we need to have layout
1806 * information for open generic classes (either with a generic
1807 * context containing type variables or with a generic
1808 * container), so we don't return in that case anymore.
1811 if (klass->enumtype) {
1812 for (i = 0; i < top; i++) {
1813 field = &klass->fields [i];
1814 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1815 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1820 if (!mono_class_enum_basetype (klass)) {
1821 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1827 * Enable GC aware auto layout: in this mode, reference
1828 * fields are grouped together inside objects, increasing collector
1830 * Requires that all classes whose layout is known to native code be annotated
1831 * with [StructLayout (LayoutKind.Sequential)]
1832 * Value types have gc_aware_layout disabled by default, as per
1833 * what the default is for other runtimes.
1835 /* corlib is missing [StructLayout] directives in many places */
1836 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1837 if (!klass->valuetype)
1838 gc_aware_layout = TRUE;
1841 /* Compute klass->blittable */
1844 blittable = klass->parent->blittable;
1845 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1847 for (i = 0; i < top; i++) {
1848 field = &klass->fields [i];
1850 if (mono_field_is_deleted (field))
1852 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1855 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1858 MonoClass *field_class = mono_class_from_mono_type (field->type);
1860 mono_class_setup_fields (field_class);
1861 if (mono_class_has_failure (field_class)) {
1862 MonoError field_error;
1863 error_init (&field_error);
1864 mono_error_set_for_class_failure (&field_error, field_class);
1865 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1866 mono_error_cleanup (&field_error);
1870 if (!field_class || !field_class->blittable)
1874 if (klass->enumtype)
1875 blittable = klass->element_class->blittable;
1877 if (mono_class_has_failure (klass))
1879 if (klass == mono_defaults.string_class)
1882 /* Compute klass->has_references */
1884 * Process non-static fields first, since static fields might recursively
1885 * refer to the class itself.
1887 for (i = 0; i < top; i++) {
1890 field = &klass->fields [i];
1892 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1893 ftype = mono_type_get_underlying_type (field->type);
1894 ftype = mono_type_get_basic_type_from_generic (ftype);
1895 if (type_has_references (klass, ftype))
1896 has_references = TRUE;
1901 * Compute field layout and total size (not considering static fields)
1903 field_offsets = g_new0 (int, top);
1904 fields_has_references = g_new0 (gboolean, top);
1905 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1907 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1908 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1909 if (gc_aware_layout)
1914 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1917 if (klass->parent) {
1918 mono_class_setup_fields (klass->parent);
1919 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1921 real_size = klass->parent->instance_size;
1923 real_size = sizeof (MonoObject);
1926 for (pass = 0; pass < passes; ++pass) {
1927 for (i = 0; i < top; i++){
1932 field = &klass->fields [i];
1934 if (mono_field_is_deleted (field))
1936 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1939 ftype = mono_type_get_underlying_type (field->type);
1940 ftype = mono_type_get_basic_type_from_generic (ftype);
1941 if (gc_aware_layout) {
1942 fields_has_references [i] = type_has_references (klass, ftype);
1943 if (fields_has_references [i]) {
1952 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1953 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1954 /* This field is a hack inserted by MCS to empty structures */
1958 size = mono_type_size (field->type, &align);
1960 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1961 align = packing_size ? MIN (packing_size, align): align;
1962 /* if the field has managed references, we need to force-align it
1965 if (type_has_references (klass, ftype))
1966 align = MAX (align, sizeof (gpointer));
1968 min_align = MAX (align, min_align);
1969 field_offsets [i] = real_size;
1971 field_offsets [i] += align - 1;
1972 field_offsets [i] &= ~(align - 1);
1974 /*TypeBuilders produce all sort of weird things*/
1975 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1976 real_size = field_offsets [i] + size;
1979 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1980 if (klass->simd_type)
1981 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1982 instance_size = MAX (real_size, instance_size);
1984 if (instance_size & (min_align - 1)) {
1985 instance_size += min_align - 1;
1986 instance_size &= ~(min_align - 1);
1990 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1994 for (i = 0; i < top; i++) {
1999 field = &klass->fields [i];
2002 * There must be info about all the fields in a type if it
2003 * uses explicit layout.
2005 if (mono_field_is_deleted (field))
2007 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2010 size = mono_type_size (field->type, &align);
2011 align = packing_size ? MIN (packing_size, align): align;
2012 min_align = MAX (align, min_align);
2015 /* Already set by typebuilder_setup_fields () */
2016 field_offsets [i] = field->offset + sizeof (MonoObject);
2018 int idx = first_field_idx + i;
2020 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2021 field_offsets [i] = offset + sizeof (MonoObject);
2023 ftype = mono_type_get_underlying_type (field->type);
2024 ftype = mono_type_get_basic_type_from_generic (ftype);
2025 if (type_has_references (klass, ftype)) {
2026 if (field_offsets [i] % sizeof (gpointer)) {
2027 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2034 real_size = MAX (real_size, size + field_offsets [i]);
2037 if (klass->has_references) {
2038 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2040 /* Check for overlapping reference and non-reference fields */
2041 for (i = 0; i < top; i++) {
2044 field = &klass->fields [i];
2046 if (mono_field_is_deleted (field))
2048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2050 ftype = mono_type_get_underlying_type (field->type);
2051 if (MONO_TYPE_IS_REFERENCE (ftype))
2052 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2054 for (i = 0; i < top; i++) {
2055 field = &klass->fields [i];
2057 if (mono_field_is_deleted (field))
2059 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2062 // FIXME: Too much code does this
2064 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2065 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]);
2069 g_free (ref_bitmap);
2072 instance_size = MAX (real_size, instance_size);
2073 if (instance_size & (min_align - 1)) {
2074 instance_size += min_align - 1;
2075 instance_size &= ~(min_align - 1);
2081 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2083 * This leads to all kinds of problems with nested structs, so only
2084 * enable it when a MONO_DEBUG property is set.
2086 * For small structs, set min_align to at least the struct size to improve
2087 * performance, and since the JIT memset/memcpy code assumes this and generates
2088 * unaligned accesses otherwise. See #78990 for a testcase.
2090 if (mono_align_small_structs && top) {
2091 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2092 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2096 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2097 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2098 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2099 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2101 /* Publish the data */
2102 mono_loader_lock ();
2103 if (klass->instance_size && !klass->image->dynamic) {
2104 /* Might be already set using cached info */
2105 if (klass->instance_size != instance_size) {
2106 /* Emit info to help debugging */
2107 g_print ("%s\n", mono_class_full_name (klass));
2108 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2109 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2110 g_print ("%d %d\n", klass->min_align, min_align);
2111 for (i = 0; i < top; ++i) {
2112 field = &klass->fields [i];
2113 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2114 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2117 g_assert (klass->instance_size == instance_size);
2119 klass->instance_size = instance_size;
2121 klass->blittable = blittable;
2122 klass->has_references = has_references;
2123 klass->packing_size = packing_size;
2124 klass->min_align = min_align;
2125 for (i = 0; i < top; ++i) {
2126 field = &klass->fields [i];
2127 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2128 klass->fields [i].offset = field_offsets [i];
2131 mono_memory_barrier ();
2132 klass->size_inited = 1;
2133 mono_loader_unlock ();
2136 * Compute static field layout and size
2137 * Static fields can reference the class itself, so this has to be
2138 * done after instance_size etc. are initialized.
2141 for (i = 0; i < top; i++) {
2145 field = &klass->fields [i];
2147 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2149 if (mono_field_is_deleted (field))
2152 if (mono_type_has_exceptions (field->type)) {
2153 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2157 has_static_fields = TRUE;
2159 size = mono_type_size (field->type, &align);
2160 field_offsets [i] = class_size;
2161 /*align is always non-zero here*/
2162 field_offsets [i] += align - 1;
2163 field_offsets [i] &= ~(align - 1);
2164 class_size = field_offsets [i] + size;
2167 if (has_static_fields && class_size == 0)
2168 /* Simplify code which depends on class_size != 0 if the class has static fields */
2171 /* Compute klass->has_static_refs */
2172 has_static_refs = FALSE;
2173 for (i = 0; i < top; i++) {
2176 field = &klass->fields [i];
2178 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2179 ftype = mono_type_get_underlying_type (field->type);
2180 ftype = mono_type_get_basic_type_from_generic (ftype);
2181 if (type_has_references (klass, ftype))
2182 has_static_refs = TRUE;
2186 /*valuetypes can't be neither bigger than 1Mb or empty. */
2187 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2188 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2190 /* Publish the data */
2191 mono_loader_lock ();
2193 klass->sizes.class_size = class_size;
2194 klass->has_static_refs = has_static_refs;
2195 for (i = 0; i < top; ++i) {
2196 field = &klass->fields [i];
2198 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2199 field->offset = field_offsets [i];
2202 mono_memory_barrier ();
2203 klass->fields_inited = 1;
2204 mono_loader_unlock ();
2206 g_free (field_offsets);
2207 g_free (fields_has_references);
2211 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2215 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2216 method->klass = klass;
2217 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2218 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2219 method->signature = sig;
2220 method->name = name;
2223 if (name [0] == '.') {
2224 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2226 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2232 * mono_class_setup_methods:
2235 * Initializes the 'methods' array in CLASS.
2236 * Calling this method should be avoided if possible since it allocates a lot
2237 * of long-living MonoMethod structures.
2238 * Methods belonging to an interface are assigned a sequential slot starting
2241 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2244 mono_class_setup_methods (MonoClass *klass)
2247 MonoMethod **methods;
2252 if (mono_class_is_ginst (klass)) {
2254 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2256 mono_class_init (gklass);
2257 if (!mono_class_has_failure (gklass))
2258 mono_class_setup_methods (gklass);
2259 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2262 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2263 count = mono_class_get_method_count (gklass);
2264 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2266 for (i = 0; i < count; i++) {
2267 methods [i] = mono_class_inflate_generic_method_full_checked (
2268 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2269 if (!mono_error_ok (&error)) {
2270 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2271 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2274 mono_error_cleanup (&error);
2278 } else if (klass->rank) {
2280 MonoMethod *amethod;
2281 MonoMethodSignature *sig;
2282 int count_generic = 0, first_generic = 0;
2284 gboolean jagged_ctor = FALSE;
2286 count = 3 + (klass->rank > 1? 2: 1);
2288 mono_class_setup_interfaces (klass, &error);
2289 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2291 if (klass->rank == 1 && klass->element_class->rank) {
2296 if (klass->interface_count) {
2297 count_generic = generic_array_methods (klass);
2298 first_generic = count;
2299 count += klass->interface_count * count_generic;
2302 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2304 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2305 sig->ret = &mono_defaults.void_class->byval_arg;
2306 sig->pinvoke = TRUE;
2307 sig->hasthis = TRUE;
2308 for (i = 0; i < klass->rank; ++i)
2309 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2311 amethod = create_array_method (klass, ".ctor", sig);
2312 methods [method_num++] = amethod;
2313 if (klass->rank > 1) {
2314 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2315 sig->ret = &mono_defaults.void_class->byval_arg;
2316 sig->pinvoke = TRUE;
2317 sig->hasthis = TRUE;
2318 for (i = 0; i < klass->rank * 2; ++i)
2319 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2321 amethod = create_array_method (klass, ".ctor", sig);
2322 methods [method_num++] = amethod;
2326 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2327 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2328 sig->ret = &mono_defaults.void_class->byval_arg;
2329 sig->pinvoke = TRUE;
2330 sig->hasthis = TRUE;
2331 for (i = 0; i < klass->rank + 1; ++i)
2332 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2333 amethod = create_array_method (klass, ".ctor", sig);
2334 methods [method_num++] = amethod;
2337 /* element Get (idx11, [idx2, ...]) */
2338 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2339 sig->ret = &klass->element_class->byval_arg;
2340 sig->pinvoke = TRUE;
2341 sig->hasthis = TRUE;
2342 for (i = 0; i < klass->rank; ++i)
2343 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2344 amethod = create_array_method (klass, "Get", sig);
2345 methods [method_num++] = amethod;
2346 /* element& Address (idx11, [idx2, ...]) */
2347 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2348 sig->ret = &klass->element_class->this_arg;
2349 sig->pinvoke = TRUE;
2350 sig->hasthis = TRUE;
2351 for (i = 0; i < klass->rank; ++i)
2352 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2353 amethod = create_array_method (klass, "Address", sig);
2354 methods [method_num++] = amethod;
2355 /* void Set (idx11, [idx2, ...], element) */
2356 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2357 sig->ret = &mono_defaults.void_class->byval_arg;
2358 sig->pinvoke = TRUE;
2359 sig->hasthis = TRUE;
2360 for (i = 0; i < klass->rank; ++i)
2361 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2362 sig->params [i] = &klass->element_class->byval_arg;
2363 amethod = create_array_method (klass, "Set", sig);
2364 methods [method_num++] = amethod;
2366 GHashTable *cache = g_hash_table_new (NULL, NULL);
2367 for (i = 0; i < klass->interface_count; i++)
2368 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2369 g_hash_table_destroy (cache);
2370 } else if (mono_class_has_static_metadata (klass)) {
2372 int first_idx = mono_class_get_first_method_idx (klass);
2374 count = mono_class_get_method_count (klass);
2375 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2376 for (i = 0; i < count; ++i) {
2377 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2378 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2380 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2381 mono_error_cleanup (&error);
2385 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2389 if (MONO_CLASS_IS_INTERFACE (klass)) {
2391 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2392 for (i = 0; i < count; ++i) {
2393 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2394 methods [i]->slot = slot++;
2398 mono_image_lock (klass->image);
2400 if (!klass->methods) {
2401 mono_class_set_method_count (klass, count);
2403 /* Needed because of the double-checking locking pattern */
2404 mono_memory_barrier ();
2406 klass->methods = methods;
2409 mono_image_unlock (klass->image);
2413 * mono_class_get_method_by_index:
2415 * Returns klass->methods [index], initializing klass->methods if neccesary.
2417 * LOCKING: Acquires the loader lock.
2420 mono_class_get_method_by_index (MonoClass *klass, int index)
2424 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2425 /* Avoid calling setup_methods () if possible */
2426 if (gklass && !klass->methods) {
2429 m = mono_class_inflate_generic_method_full_checked (
2430 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2431 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2433 * If setup_methods () is called later for this class, no duplicates are created,
2434 * since inflate_generic_method guarantees that only one instance of a method
2435 * is created for each context.
2438 mono_class_setup_methods (klass);
2439 g_assert (m == klass->methods [index]);
2443 mono_class_setup_methods (klass);
2444 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2446 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2447 return klass->methods [index];
2452 * mono_class_get_inflated_method:
2454 * Given an inflated class CLASS and a method METHOD which should be a method of
2455 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2458 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2460 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2463 g_assert (method->klass == gklass);
2465 mono_class_setup_methods (gklass);
2466 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2468 mcount = mono_class_get_method_count (gklass);
2469 for (i = 0; i < mcount; ++i) {
2470 if (gklass->methods [i] == method) {
2471 if (klass->methods) {
2472 return klass->methods [i];
2475 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2476 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2486 * mono_class_get_vtable_entry:
2488 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2489 * LOCKING: Acquires the loader lock.
2492 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2496 if (klass->rank == 1) {
2498 * szarrays do not overwrite any methods of Array, so we can avoid
2499 * initializing their vtables in some cases.
2501 mono_class_setup_vtable (klass->parent);
2502 if (offset < klass->parent->vtable_size)
2503 return klass->parent->vtable [offset];
2506 if (mono_class_is_ginst (klass)) {
2508 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2509 mono_class_setup_vtable (gklass);
2510 m = gklass->vtable [offset];
2512 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2513 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2515 mono_class_setup_vtable (klass);
2516 if (mono_class_has_failure (klass))
2518 m = klass->vtable [offset];
2525 * mono_class_get_vtable_size:
2527 * Return the vtable size for KLASS.
2530 mono_class_get_vtable_size (MonoClass *klass)
2532 mono_class_setup_vtable (klass);
2534 return klass->vtable_size;
2538 * mono_class_setup_properties:
2540 * Initialize klass->ext.property and klass->ext.properties.
2542 * This method can fail the class.
2545 mono_class_setup_properties (MonoClass *klass)
2547 guint startm, endm, i, j;
2548 guint32 cols [MONO_PROPERTY_SIZE];
2549 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2550 MonoProperty *properties;
2553 MonoClassPropertyInfo *info;
2555 info = mono_class_get_property_info (klass);
2559 if (mono_class_is_ginst (klass)) {
2560 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2562 mono_class_init (gklass);
2563 mono_class_setup_properties (gklass);
2564 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2567 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2568 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2570 for (i = 0; i < ginfo->count; i++) {
2572 MonoProperty *prop = &properties [i];
2574 *prop = ginfo->properties [i];
2577 prop->get = mono_class_inflate_generic_method_full_checked (
2578 prop->get, klass, mono_class_get_context (klass), &error);
2580 prop->set = mono_class_inflate_generic_method_full_checked (
2581 prop->set, klass, mono_class_get_context (klass), &error);
2583 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2584 prop->parent = klass;
2587 first = ginfo->first;
2588 count = ginfo->count;
2590 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2591 count = last - first;
2594 mono_class_setup_methods (klass);
2595 if (mono_class_has_failure (klass))
2599 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2600 for (i = first; i < last; ++i) {
2601 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2602 properties [i - first].parent = klass;
2603 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2604 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2606 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2607 int first_idx = mono_class_get_first_method_idx (klass);
2608 for (j = startm; j < endm; ++j) {
2611 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2613 if (klass->image->uncompressed_metadata) {
2615 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2616 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2617 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2619 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2622 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2623 case METHOD_SEMANTIC_SETTER:
2624 properties [i - first].set = method;
2626 case METHOD_SEMANTIC_GETTER:
2627 properties [i - first].get = method;
2636 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2637 info->first = first;
2638 info->count = count;
2639 info->properties = properties;
2640 mono_memory_barrier ();
2642 /* This might leak 'info' which was allocated from the image mempool */
2643 mono_class_set_property_info (klass, info);
2647 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2649 MonoMethod **om, **retval;
2652 for (om = methods, count = 0; *om; ++om, ++count)
2655 retval = g_new0 (MonoMethod*, count + 1);
2657 for (om = methods, count = 0; *om; ++om, ++count) {
2659 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2660 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2666 /*This method can fail the class.*/
2668 mono_class_setup_events (MonoClass *klass)
2671 guint startm, endm, i, j;
2672 guint32 cols [MONO_EVENT_SIZE];
2673 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2677 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2681 if (mono_class_is_ginst (klass)) {
2682 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2683 MonoGenericContext *context = NULL;
2685 mono_class_setup_events (gklass);
2686 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2689 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2690 first = ginfo->first;
2691 count = ginfo->count;
2693 events = mono_class_new0 (klass, MonoEvent, count);
2696 context = mono_class_get_context (klass);
2698 for (i = 0; i < count; i++) {
2700 MonoEvent *event = &events [i];
2701 MonoEvent *gevent = &ginfo->events [i];
2703 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2705 event->parent = klass;
2706 event->name = gevent->name;
2707 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2708 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2709 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2710 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2711 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2712 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2714 #ifndef MONO_SMALL_CONFIG
2715 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2717 event->attrs = gevent->attrs;
2720 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2721 count = last - first;
2724 mono_class_setup_methods (klass);
2725 if (mono_class_has_failure (klass)) {
2730 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2731 for (i = first; i < last; ++i) {
2732 MonoEvent *event = &events [i - first];
2734 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2735 event->parent = klass;
2736 event->attrs = cols [MONO_EVENT_FLAGS];
2737 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2739 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2740 int first_idx = mono_class_get_first_method_idx (klass);
2741 for (j = startm; j < endm; ++j) {
2744 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2746 if (klass->image->uncompressed_metadata) {
2748 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2749 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2750 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2752 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2755 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2756 case METHOD_SEMANTIC_ADD_ON:
2757 event->add = method;
2759 case METHOD_SEMANTIC_REMOVE_ON:
2760 event->remove = method;
2762 case METHOD_SEMANTIC_FIRE:
2763 event->raise = method;
2765 case METHOD_SEMANTIC_OTHER: {
2766 #ifndef MONO_SMALL_CONFIG
2769 if (event->other == NULL) {
2770 event->other = g_new0 (MonoMethod*, 2);
2772 while (event->other [n])
2774 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2776 event->other [n] = method;
2777 /* NULL terminated */
2778 event->other [n + 1] = NULL;
2789 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2790 info->events = events;
2791 info->first = first;
2792 info->count = count;
2794 mono_memory_barrier ();
2796 mono_class_set_event_info (klass, info);
2800 * Global pool of interface IDs, represented as a bitset.
2801 * LOCKING: Protected by the classes lock.
2803 static MonoBitSet *global_interface_bitset = NULL;
2806 * mono_unload_interface_ids:
2807 * @bitset: bit set of interface IDs
2809 * When an image is unloaded, the interface IDs associated with
2810 * the image are put back in the global pool of IDs so the numbers
2814 mono_unload_interface_ids (MonoBitSet *bitset)
2817 mono_bitset_sub (global_interface_bitset, bitset);
2822 mono_unload_interface_id (MonoClass *klass)
2824 if (global_interface_bitset && klass->interface_id) {
2826 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2832 * mono_get_unique_iid:
2833 * \param klass interface
2835 * Assign a unique integer ID to the interface represented by \p klass.
2836 * The ID will positive and as small as possible.
2837 * LOCKING: Acquires the classes lock.
2838 * \returns The new ID.
2841 mono_get_unique_iid (MonoClass *klass)
2845 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2849 if (!global_interface_bitset) {
2850 global_interface_bitset = mono_bitset_new (128, 0);
2853 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2855 int old_size = mono_bitset_size (global_interface_bitset);
2856 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2857 mono_bitset_free (global_interface_bitset);
2858 global_interface_bitset = new_set;
2861 mono_bitset_set (global_interface_bitset, iid);
2862 /* set the bit also in the per-image set */
2863 if (!mono_class_is_ginst (klass)) {
2864 if (klass->image->interface_bitset) {
2865 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2866 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2867 mono_bitset_free (klass->image->interface_bitset);
2868 klass->image->interface_bitset = new_set;
2871 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2873 mono_bitset_set (klass->image->interface_bitset, iid);
2878 #ifndef MONO_SMALL_CONFIG
2879 if (mono_print_vtable) {
2881 char *type_name = mono_type_full_name (&klass->byval_arg);
2882 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2883 if (gklass && !gklass->context.class_inst->is_open) {
2884 generic_id = gklass->context.class_inst->id;
2885 g_assert (generic_id != 0);
2889 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2894 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2895 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2896 g_assert (iid < INT_MAX);
2901 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2906 mono_class_setup_interfaces (klass, error);
2907 return_if_nok (error);
2909 for (i = 0; i < klass->interface_count; i++) {
2910 ic = klass->interfaces [i];
2913 *res = g_ptr_array_new ();
2914 if (*ifaces == NULL)
2915 *ifaces = g_hash_table_new (NULL, NULL);
2916 if (g_hash_table_lookup (*ifaces, ic))
2918 g_ptr_array_add (*res, ic);
2919 g_hash_table_insert (*ifaces, ic, ic);
2920 mono_class_init (ic);
2921 if (mono_class_has_failure (ic)) {
2922 mono_error_set_type_load_class (error, ic, "Error Loading class");
2926 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2927 return_if_nok (error);
2932 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2934 GPtrArray *res = NULL;
2935 GHashTable *ifaces = NULL;
2937 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2939 g_hash_table_destroy (ifaces);
2940 if (!mono_error_ok (error)) {
2942 g_ptr_array_free (res, TRUE);
2949 compare_interface_ids (const void *p_key, const void *p_element)
2951 const MonoClass *key = (const MonoClass *)p_key;
2952 const MonoClass *element = *(const MonoClass **)p_element;
2954 return (key->interface_id - element->interface_id);
2957 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2959 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2961 MonoClass **result = (MonoClass **)mono_binary_search (
2963 klass->interfaces_packed,
2964 klass->interface_offsets_count,
2965 sizeof (MonoClass *),
2966 compare_interface_ids);
2968 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2975 * mono_class_interface_offset_with_variance:
2977 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2978 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2980 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2982 * FIXME figure out MS disambiguation rules and fix this function.
2985 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2987 int i = mono_class_interface_offset (klass, itf);
2988 *non_exact_match = FALSE;
2992 if (itf->is_array_special_interface && klass->rank < 2) {
2993 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2995 for (i = 0; i < klass->interface_offsets_count; i++) {
2996 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2997 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2998 *non_exact_match = TRUE;
2999 return klass->interface_offsets_packed [i];
3004 if (!mono_class_has_variant_generic_params (itf))
3007 for (i = 0; i < klass->interface_offsets_count; i++) {
3008 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3009 *non_exact_match = TRUE;
3010 return klass->interface_offsets_packed [i];
3018 print_implemented_interfaces (MonoClass *klass)
3022 GPtrArray *ifaces = NULL;
3024 int ancestor_level = 0;
3026 name = mono_type_get_full_name (klass);
3027 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3030 for (i = 0; i < klass->interface_offsets_count; i++)
3031 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3032 klass->interfaces_packed [i]->interface_id,
3033 klass->interface_offsets_packed [i],
3034 mono_class_get_method_count (klass->interfaces_packed [i]),
3035 klass->interfaces_packed [i]->name_space,
3036 klass->interfaces_packed [i]->name );
3037 printf ("Interface flags: ");
3038 for (i = 0; i <= klass->max_interface_id; i++)
3039 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3040 printf ("(%d,T)", i);
3042 printf ("(%d,F)", i);
3044 printf ("Dump interface flags:");
3045 #ifdef COMPRESSED_INTERFACE_BITMAP
3047 const uint8_t* p = klass->interface_bitmap;
3048 i = klass->max_interface_id;
3050 printf (" %d x 00 %02X", p [0], p [1]);
3056 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3057 printf (" %02X", klass->interface_bitmap [i]);
3060 while (klass != NULL) {
3061 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3062 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3063 if (!mono_error_ok (&error)) {
3064 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3065 mono_error_cleanup (&error);
3066 } else if (ifaces) {
3067 for (i = 0; i < ifaces->len; i++) {
3068 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3069 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3070 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3072 mono_class_interface_offset (klass, ic),
3073 mono_class_get_method_count (ic),
3077 g_ptr_array_free (ifaces, TRUE);
3080 klass = klass->parent;
3085 * Return the number of virtual methods.
3086 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3087 * Return -1 on failure.
3088 * FIXME It would be nice if this information could be cached somewhere.
3091 count_virtual_methods (MonoClass *klass)
3093 int i, mcount, vcount = 0;
3095 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3097 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3098 mono_class_setup_methods (klass);
3099 if (mono_class_has_failure (klass))
3102 mcount = mono_class_get_method_count (klass);
3103 for (i = 0; i < mcount; ++i) {
3104 flags = klass->methods [i]->flags;
3105 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3109 int first_idx = mono_class_get_first_method_idx (klass);
3110 mcount = mono_class_get_method_count (klass);
3111 for (i = 0; i < mcount; ++i) {
3112 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3114 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3122 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3130 m = (l + num_ifaces) / 2;
3131 if (interfaces_full [m] == ic)
3133 if (l == num_ifaces)
3135 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3144 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3146 int i = find_interface (num_ifaces, interfaces_full, ic);
3150 interface_offsets_full [i] = offset;
3153 for (i = 0; i < num_ifaces; ++i) {
3154 if (interfaces_full [i]) {
3156 if (interfaces_full [i]->interface_id < ic->interface_id)
3159 while (end < num_ifaces && interfaces_full [end]) end++;
3160 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3161 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3163 interfaces_full [i] = ic;
3164 interface_offsets_full [i] = offset;
3170 #ifdef COMPRESSED_INTERFACE_BITMAP
3173 * Compressed interface bitmap design.
3175 * Interface bitmaps take a large amount of memory, because their size is
3176 * linear with the maximum interface id assigned in the process (each interface
3177 * is assigned a unique id as it is loaded). The number of interface classes
3178 * is high because of the many implicit interfaces implemented by arrays (we'll
3179 * need to lazy-load them in the future).
3180 * Most classes implement a very small number of interfaces, so the bitmap is
3181 * sparse. This bitmap needs to be checked by interface casts, so access to the
3182 * needed bit must be fast and doable with few jit instructions.
3184 * The current compression format is as follows:
3185 * *) it is a sequence of one or more two-byte elements
3186 * *) the first byte in the element is the count of empty bitmap bytes
3187 * at the current bitmap position
3188 * *) the second byte in the element is an actual bitmap byte at the current
3191 * As an example, the following compressed bitmap bytes:
3192 * 0x07 0x01 0x00 0x7
3193 * correspond to the following bitmap:
3194 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3196 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3197 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3198 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3202 * mono_compress_bitmap:
3203 * \param dest destination buffer
3204 * \param bitmap bitmap buffer
3205 * \param size size of \p bitmap in bytes
3207 * This is a mono internal function.
3208 * The \p bitmap data is compressed into a format that is small but
3209 * still searchable in few instructions by the JIT and runtime.
3210 * The compressed data is stored in the buffer pointed to by the
3211 * \p dest array. Passing a NULL value for \p dest allows to just compute
3212 * the size of the buffer.
3213 * This compression algorithm assumes the bits set in the bitmap are
3214 * few and far between, like in interface bitmaps.
3215 * \returns The size of the compressed bitmap in bytes.
3218 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3222 const uint8_t *end = bitmap + size;
3223 while (bitmap < end) {
3224 if (*bitmap || numz == 255) {
3248 * mono_class_interface_match:
3249 * \param bitmap a compressed bitmap buffer
3250 * \param id the index to check in the bitmap
3252 * This is a mono internal function.
3253 * Checks if a bit is set in a compressed interface bitmap. \p id must
3254 * be already checked for being smaller than the maximum id encoded in the
3257 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3261 mono_class_interface_match (const uint8_t *bitmap, int id)
3264 id -= bitmap [0] * 8;
3268 return bitmap [1] & (1 << id);
3277 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3278 * LOCKING: Acquires the loader lock.
3281 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3285 int i, j, num_ifaces;
3287 MonoClass **interfaces_full = NULL;
3288 int *interface_offsets_full = NULL;
3290 GPtrArray **ifaces_array = NULL;
3291 int interface_offsets_count;
3293 mono_loader_lock ();
3295 mono_class_setup_supertypes (klass);
3297 /* compute maximum number of slots and maximum interface id */
3299 num_ifaces = 0; /* this can include duplicated ones */
3300 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3301 for (j = 0; j < klass->idepth; j++) {
3302 k = klass->supertypes [j];
3304 num_ifaces += k->interface_count;
3305 for (i = 0; i < k->interface_count; i++) {
3306 ic = k->interfaces [i];
3308 mono_class_init (ic);
3310 if (max_iid < ic->interface_id)
3311 max_iid = ic->interface_id;
3313 ifaces = mono_class_get_implemented_interfaces (k, &error);
3314 if (!mono_error_ok (&error)) {
3315 char *name = mono_type_get_full_name (k);
3316 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3318 mono_error_cleanup (&error);
3323 num_ifaces += ifaces->len;
3324 for (i = 0; i < ifaces->len; ++i) {
3325 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3326 if (max_iid < ic->interface_id)
3327 max_iid = ic->interface_id;
3329 ifaces_array [j] = ifaces;
3333 if (MONO_CLASS_IS_INTERFACE (klass)) {
3335 if (max_iid < klass->interface_id)
3336 max_iid = klass->interface_id;
3339 /* compute vtable offset for interfaces */
3340 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3341 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3343 for (i = 0; i < num_ifaces; i++)
3344 interface_offsets_full [i] = -1;
3346 /* skip the current class */
3347 for (j = 0; j < klass->idepth - 1; j++) {
3348 k = klass->supertypes [j];
3349 ifaces = ifaces_array [j];
3352 for (i = 0; i < ifaces->len; ++i) {
3354 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3356 /*Force the sharing of interface offsets between parent and subtypes.*/
3357 io = mono_class_interface_offset (k, ic);
3359 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3364 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3365 ifaces = ifaces_array [klass->idepth - 1];
3367 for (i = 0; i < ifaces->len; ++i) {
3369 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3370 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3372 count = count_virtual_methods (ic);
3374 char *name = mono_type_get_full_name (ic);
3375 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3384 if (MONO_CLASS_IS_INTERFACE (klass))
3385 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3387 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3388 if (interface_offsets_full [i] != -1)
3389 interface_offsets_count ++;
3392 /* Publish the data */
3393 klass->max_interface_id = max_iid;
3395 * We might get called multiple times:
3396 * - mono_class_init ()
3397 * - mono_class_setup_vtable ().
3398 * - mono_class_setup_interface_offsets ().
3399 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3400 * means we have to overwrite those when called from other places (#4440).
3402 if (klass->interfaces_packed) {
3404 g_assert (klass->interface_offsets_count == interface_offsets_count);
3408 klass->interface_offsets_count = interface_offsets_count;
3409 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3410 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3411 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3412 #ifdef COMPRESSED_INTERFACE_BITMAP
3413 bitmap = g_malloc0 (bsize);
3415 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3417 for (i = 0; i < interface_offsets_count; i++) {
3418 guint32 id = interfaces_full [i]->interface_id;
3419 bitmap [id >> 3] |= (1 << (id & 7));
3420 klass->interfaces_packed [i] = interfaces_full [i];
3421 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3423 #ifdef COMPRESSED_INTERFACE_BITMAP
3424 i = mono_compress_bitmap (NULL, bitmap, bsize);
3425 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3426 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3429 klass->interface_bitmap = bitmap;
3433 mono_loader_unlock ();
3435 g_free (interfaces_full);
3436 g_free (interface_offsets_full);
3437 for (i = 0; i < klass->idepth; i++) {
3438 ifaces = ifaces_array [i];
3440 g_ptr_array_free (ifaces, TRUE);
3442 g_free (ifaces_array);
3444 //printf ("JUST DONE: ");
3445 //print_implemented_interfaces (klass);
3451 * Setup interface offsets for interfaces.
3453 * - klass->max_interface_id
3454 * - klass->interface_offsets_count
3455 * - klass->interfaces_packed
3456 * - klass->interface_offsets_packed
3457 * - klass->interface_bitmap
3459 * This function can fail @class.
3462 mono_class_setup_interface_offsets (MonoClass *klass)
3464 setup_interface_offsets (klass, 0, FALSE);
3467 /*Checks if @klass has @parent as one of it's parents type gtd
3471 * Bar<T> : Foo<Bar<Bar<T>>>
3475 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3477 klass = mono_class_get_generic_type_definition (klass);
3478 parent = mono_class_get_generic_type_definition (parent);
3479 mono_class_setup_supertypes (klass);
3480 mono_class_setup_supertypes (parent);
3482 return klass->idepth >= parent->idepth &&
3483 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3487 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3489 MonoGenericInst *ginst;
3492 if (!mono_class_is_ginst (klass)) {
3493 mono_class_setup_vtable_full (klass, in_setup);
3494 return !mono_class_has_failure (klass);
3497 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3498 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3501 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3502 for (i = 0; i < ginst->type_argc; ++i) {
3504 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3506 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3507 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3508 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3510 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3511 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3519 * mono_class_setup_vtable:
3521 * Creates the generic vtable of CLASS.
3522 * Initializes the following fields in MonoClass:
3525 * Plus all the fields initialized by setup_interface_offsets ().
3526 * If there is an error during vtable construction, klass->has_failure
3527 * is set and details are stored in a MonoErrorBoxed.
3529 * LOCKING: Acquires the loader lock.
3532 mono_class_setup_vtable (MonoClass *klass)
3534 mono_class_setup_vtable_full (klass, NULL);
3538 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3541 MonoMethod **overrides;
3542 MonoGenericContext *context;
3550 if (MONO_CLASS_IS_INTERFACE (klass)) {
3551 /* This sets method->slot for all methods if this is an interface */
3552 mono_class_setup_methods (klass);
3556 if (mono_class_has_failure (klass))
3559 if (g_list_find (in_setup, klass))
3562 mono_loader_lock ();
3564 if (klass->vtable) {
3565 mono_loader_unlock ();
3569 mono_stats.generic_vtable_count ++;
3570 in_setup = g_list_prepend (in_setup, klass);
3572 if (mono_class_is_ginst (klass)) {
3573 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3574 mono_loader_unlock ();
3575 g_list_remove (in_setup, klass);
3579 context = mono_class_get_context (klass);
3580 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3582 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3583 type_token = klass->type_token;
3586 if (image_is_dynamic (klass->image)) {
3587 /* Generic instances can have zero method overrides without causing any harm.
3588 * This is true since we don't do layout all over again for them, we simply inflate
3589 * the layout of the parent.
3591 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3592 if (!is_ok (&error)) {
3593 mono_loader_unlock ();
3594 g_list_remove (in_setup, klass);
3595 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3596 mono_error_cleanup (&error);
3600 /* The following call fails if there are missing methods in the type */
3601 /* FIXME it's probably a good idea to avoid this for generic instances. */
3602 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3606 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3608 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3612 mono_loader_unlock ();
3613 g_list_remove (in_setup, klass);
3618 #define DEBUG_INTERFACE_VTABLE_CODE 0
3619 #define TRACE_INTERFACE_VTABLE_CODE 0
3620 #define VERIFY_INTERFACE_VTABLE_CODE 0
3621 #define VTABLE_SELECTOR (1)
3623 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3624 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3625 if (!(VTABLE_SELECTOR)) break; \
3629 #define DEBUG_INTERFACE_VTABLE(stmt)
3632 #if TRACE_INTERFACE_VTABLE_CODE
3633 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3634 if (!(VTABLE_SELECTOR)) break; \
3638 #define TRACE_INTERFACE_VTABLE(stmt)
3641 #if VERIFY_INTERFACE_VTABLE_CODE
3642 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3643 if (!(VTABLE_SELECTOR)) break; \
3647 #define VERIFY_INTERFACE_VTABLE(stmt)
3651 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3653 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3657 GString *res = g_string_new ("");
3659 g_string_append_c (res, '(');
3660 for (i = 0; i < sig->param_count; ++i) {
3662 g_string_append_c (res, ',');
3663 mono_type_get_desc (res, sig->params [i], include_namespace);
3665 g_string_append (res, ")=>");
3666 if (sig->ret != NULL) {
3667 mono_type_get_desc (res, sig->ret, include_namespace);
3669 g_string_append (res, "NULL");
3672 g_string_free (res, FALSE);
3676 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3677 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3678 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3679 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3687 is_wcf_hack_disabled (void)
3689 static gboolean disabled;
3690 static gboolean inited = FALSE;
3692 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3699 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3701 MonoMethodSignature *cmsig, *imsig;
3702 if (strcmp (im->name, cm->name) == 0) {
3703 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3704 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3707 if (! slot_is_empty) {
3708 if (require_newslot) {
3709 if (! interface_is_explicitly_implemented_by_class) {
3710 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3713 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3714 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3718 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3721 cmsig = mono_method_signature (cm);
3722 imsig = mono_method_signature (im);
3723 if (!cmsig || !imsig) {
3724 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3728 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3729 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3730 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3731 TRACE_INTERFACE_VTABLE (printf ("]"));
3734 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3735 if (mono_security_core_clr_enabled ())
3736 mono_security_core_clr_check_override (klass, cm, im);
3738 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3739 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3740 char *body_name = mono_method_full_name (cm, TRUE);
3741 char *decl_name = mono_method_full_name (im, TRUE);
3742 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3750 MonoClass *ic = im->klass;
3751 const char *ic_name_space = ic->name_space;
3752 const char *ic_name = ic->name;
3755 if (! require_newslot) {
3756 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3759 if (cm->klass->rank == 0) {
3760 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3763 cmsig = mono_method_signature (cm);
3764 imsig = mono_method_signature (im);
3765 if (!cmsig || !imsig) {
3766 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3770 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3771 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3772 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3773 TRACE_INTERFACE_VTABLE (printf ("]"));
3776 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3777 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3780 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3781 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3784 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))) {
3785 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3789 subname = strstr (cm->name, ic_name_space);
3790 if (subname != cm->name) {
3791 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3794 subname += strlen (ic_name_space);
3795 if (subname [0] != '.') {
3796 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3800 if (strstr (subname, ic_name) != subname) {
3801 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3804 subname += strlen (ic_name);
3805 if (subname [0] != '.') {
3806 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3810 if (strcmp (subname, im->name) != 0) {
3811 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3815 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3816 if (mono_security_core_clr_enabled ())
3817 mono_security_core_clr_check_override (klass, cm, im);
3819 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3820 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3821 char *body_name = mono_method_full_name (cm, TRUE);
3822 char *decl_name = mono_method_full_name (im, TRUE);
3823 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3833 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3835 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3836 MonoMethod *method = key;
3837 MonoMethod *override = value;
3838 MonoClass *method_class = mono_method_get_class (method);
3839 MonoClass *override_class = mono_method_get_class (override);
3841 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3842 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3843 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3846 print_overrides (GHashTable *override_map, const char *message) {
3848 printf ("Override map \"%s\" START:\n", message);
3849 g_hash_table_foreach (override_map, foreach_override, NULL);
3850 printf ("Override map \"%s\" END.\n", message);
3852 printf ("Override map \"%s\" EMPTY.\n", message);
3856 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3857 char *full_name = mono_type_full_name (&klass->byval_arg);
3861 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3863 if (print_interfaces) {
3864 print_implemented_interfaces (klass);
3865 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3868 if (klass->parent) {
3869 parent_size = klass->parent->vtable_size;
3873 for (i = 0; i < size; ++i) {
3874 MonoMethod *cm = vtable [i];
3875 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3876 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3878 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3886 #if VERIFY_INTERFACE_VTABLE_CODE
3888 mono_method_try_get_vtable_index (MonoMethod *method)
3890 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3891 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3892 if (imethod->declaring->is_generic)
3893 return imethod->declaring->slot;
3895 return method->slot;
3899 mono_class_verify_vtable (MonoClass *klass)
3902 char *full_name = mono_type_full_name (&klass->byval_arg);
3904 printf ("*** Verifying VTable of class '%s' \n", full_name);
3908 if (!klass->methods)
3911 count = mono_class_method_count (klass);
3912 for (i = 0; i < count; ++i) {
3913 MonoMethod *cm = klass->methods [i];
3916 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3920 full_name = mono_method_full_name (cm, TRUE);
3922 slot = mono_method_try_get_vtable_index (cm);
3924 if (slot >= klass->vtable_size) {
3925 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3929 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3930 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3931 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3932 g_free (other_name);
3935 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3942 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3945 char *method_signature;
3948 for (index = 0; index < onum; ++index) {
3949 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3950 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3952 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3953 type_name = mono_type_full_name (&klass->byval_arg);
3954 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3955 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3956 g_free (method_signature);
3958 mono_class_setup_methods (klass);
3959 if (mono_class_has_failure (klass)) {
3960 char *name = mono_type_get_full_name (klass);
3961 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3965 mcount = mono_class_get_method_count (klass);
3966 for (index = 0; index < mcount; ++index) {
3967 MonoMethod *cm = klass->methods [index];
3968 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3970 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3971 g_free (method_signature);
3976 mono_method_get_method_definition (MonoMethod *method)
3978 while (method->is_inflated)
3979 method = ((MonoMethodInflated*)method)->declaring;
3984 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3988 for (i = 0; i < onum; ++i) {
3989 MonoMethod *decl = overrides [i * 2];
3990 MonoMethod *body = overrides [i * 2 + 1];
3992 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3993 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3997 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3998 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3999 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4001 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4005 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4006 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4007 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4009 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4013 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4014 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4018 body = mono_method_get_method_definition (body);
4019 decl = mono_method_get_method_definition (decl);
4021 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4022 char *body_name = mono_method_full_name (body, TRUE);
4023 char *decl_name = mono_method_full_name (decl, TRUE);
4024 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4034 mono_class_need_stelemref_method (MonoClass *klass)
4036 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4040 * LOCKING: this is supposed to be called with the loader lock held.
4043 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4047 MonoMethod **vtable = NULL;
4048 int i, max_vtsize = 0, cur_slot = 0;
4050 GPtrArray *ifaces = NULL;
4051 GHashTable *override_map = NULL;
4053 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4054 int first_non_interface_slot;
4056 GSList *virt_methods = NULL, *l;
4057 int stelemref_slot = 0;
4062 if (overrides && !verify_class_overrides (klass, overrides, onum))
4065 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4066 if (!mono_error_ok (&error)) {
4067 char *name = mono_type_get_full_name (klass);
4068 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4070 mono_error_cleanup (&error);
4072 } else if (ifaces) {
4073 for (i = 0; i < ifaces->len; i++) {
4074 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4075 max_vtsize += mono_class_get_method_count (ic);
4077 g_ptr_array_free (ifaces, TRUE);
4081 if (klass->parent) {
4082 mono_class_init (klass->parent);
4083 mono_class_setup_vtable_full (klass->parent, in_setup);
4085 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4088 max_vtsize += klass->parent->vtable_size;
4089 cur_slot = klass->parent->vtable_size;
4092 max_vtsize += mono_class_get_method_count (klass);
4094 /*Array have a slot for stelemref*/
4095 if (mono_class_need_stelemref_method (klass)) {
4096 stelemref_slot = cur_slot;
4101 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4103 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4104 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4107 max_iid = klass->max_interface_id;
4108 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4110 /* Optimized version for generic instances */
4111 if (mono_class_is_ginst (klass)) {
4113 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4116 mono_class_setup_vtable_full (gklass, in_setup);
4117 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4120 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4121 klass->vtable_size = gklass->vtable_size;
4122 for (i = 0; i < gklass->vtable_size; ++i)
4123 if (gklass->vtable [i]) {
4124 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4125 if (!mono_error_ok (&error)) {
4126 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4127 mono_error_cleanup (&error);
4131 tmp [i]->slot = gklass->vtable [i]->slot;
4133 mono_memory_barrier ();
4134 klass->vtable = tmp;
4136 /* Have to set method->slot for abstract virtual methods */
4137 if (klass->methods && gklass->methods) {
4138 int mcount = mono_class_get_method_count (klass);
4139 for (i = 0; i < mcount; ++i)
4140 if (klass->methods [i]->slot == -1)
4141 klass->methods [i]->slot = gklass->methods [i]->slot;
4147 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4149 if (klass->parent && klass->parent->vtable_size) {
4150 MonoClass *parent = klass->parent;
4153 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4155 // Also inherit parent interface vtables, just as a starting point.
4156 // This is needed otherwise bug-77127.exe fails when the property methods
4157 // have different names in the iterface and the class, because for child
4158 // classes the ".override" information is not used anymore.
4159 for (i = 0; i < parent->interface_offsets_count; i++) {
4160 MonoClass *parent_interface = parent->interfaces_packed [i];
4161 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4162 /*FIXME this is now dead code as this condition will never hold true.
4163 Since interface offsets are inherited then the offset of an interface implemented
4164 by a parent will never be the out of it's vtable boundary.
4166 if (interface_offset >= parent->vtable_size) {
4167 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4170 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4171 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4172 int mcount = mono_class_get_method_count (parent_interface);
4173 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4174 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4175 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4176 parent_interface_offset + j, parent_interface_offset, j,
4177 interface_offset + j, interface_offset, j));
4184 /*Array have a slot for stelemref*/
4185 if (mono_class_need_stelemref_method (klass)) {
4186 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4188 method->slot = stelemref_slot;
4190 g_assert (method->slot == stelemref_slot);
4192 vtable [stelemref_slot] = method;
4195 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4196 /* override interface methods */
4197 for (i = 0; i < onum; i++) {
4198 MonoMethod *decl = overrides [i*2];
4199 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4201 dslot = mono_method_get_vtable_slot (decl);
4203 mono_class_set_type_load_failure (klass, "");
4207 dslot += mono_class_interface_offset (klass, decl->klass);
4208 vtable [dslot] = overrides [i*2 + 1];
4209 vtable [dslot]->slot = dslot;
4211 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4213 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4215 if (mono_security_core_clr_enabled ())
4216 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4219 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4220 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4223 * Create a list of virtual methods to avoid calling
4224 * mono_class_get_virtual_methods () which is slow because of the metadata
4228 gpointer iter = NULL;
4231 virt_methods = NULL;
4232 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4233 virt_methods = g_slist_prepend (virt_methods, cm);
4235 if (mono_class_has_failure (klass))
4239 // Loop on all implemented interfaces...
4240 for (i = 0; i < klass->interface_offsets_count; i++) {
4241 MonoClass *parent = klass->parent;
4243 gboolean interface_is_explicitly_implemented_by_class;
4246 ic = klass->interfaces_packed [i];
4247 ic_offset = mono_class_interface_offset (klass, ic);
4249 mono_class_setup_methods (ic);
4250 if (mono_class_has_failure (ic))
4253 // Check if this interface is explicitly implemented (instead of just inherited)
4254 if (parent != NULL) {
4255 int implemented_interfaces_index;
4256 interface_is_explicitly_implemented_by_class = FALSE;
4257 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4258 if (ic == klass->interfaces [implemented_interfaces_index]) {
4259 interface_is_explicitly_implemented_by_class = TRUE;
4264 interface_is_explicitly_implemented_by_class = TRUE;
4267 // Loop on all interface methods...
4268 int mcount = mono_class_get_method_count (ic);
4269 for (im_index = 0; im_index < mcount; im_index++) {
4270 MonoMethod *im = ic->methods [im_index];
4271 int im_slot = ic_offset + im->slot;
4272 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4274 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4277 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4279 // If there is an explicit implementation, just use it right away,
4280 // otherwise look for a matching method
4281 if (override_im == NULL) {
4285 // First look for a suitable method among the class methods
4286 for (l = virt_methods; l; l = l->next) {
4287 cm = (MonoMethod *)l->data;
4288 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)));
4289 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4290 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4291 vtable [im_slot] = cm;
4292 /* Why do we need this? */
4297 TRACE_INTERFACE_VTABLE (printf ("\n"));
4298 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4302 // If the slot is still empty, look in all the inherited virtual methods...
4303 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4304 MonoClass *parent = klass->parent;
4305 // Reverse order, so that last added methods are preferred
4306 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4307 MonoMethod *cm = parent->vtable [cm_index];
4309 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));
4310 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4311 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4312 vtable [im_slot] = cm;
4313 /* Why do we need this? */
4319 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4321 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4325 g_assert (vtable [im_slot] == override_im);
4330 // If the class is not abstract, check that all its interface slots are full.
4331 // The check is done here and not directly at the end of the loop above because
4332 // it can happen (for injected generic array interfaces) that the same slot is
4333 // processed multiple times (those interfaces have overlapping slots), and it
4334 // will not always be the first pass the one that fills the slot.
4335 if (!mono_class_is_abstract (klass)) {
4336 for (i = 0; i < klass->interface_offsets_count; i++) {
4340 ic = klass->interfaces_packed [i];
4341 ic_offset = mono_class_interface_offset (klass, ic);
4343 int mcount = mono_class_get_method_count (ic);
4344 for (im_index = 0; im_index < mcount; im_index++) {
4345 MonoMethod *im = ic->methods [im_index];
4346 int im_slot = ic_offset + im->slot;
4348 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4351 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4352 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4353 if (vtable [im_slot] == NULL) {
4354 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4361 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4362 for (l = virt_methods; l; l = l->next) {
4363 cm = (MonoMethod *)l->data;
4365 * If the method is REUSE_SLOT, we must check in the
4366 * base class for a method to override.
4368 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4370 for (k = klass->parent; k ; k = k->parent) {
4375 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4376 MonoMethodSignature *cmsig, *m1sig;
4378 cmsig = mono_method_signature (cm);
4379 m1sig = mono_method_signature (m1);
4381 if (!cmsig || !m1sig) {
4382 /* FIXME proper error message */
4383 mono_class_set_type_load_failure (klass, "");
4387 if (!strcmp(cm->name, m1->name) &&
4388 mono_metadata_signature_equal (cmsig, m1sig)) {
4390 if (mono_security_core_clr_enabled ())
4391 mono_security_core_clr_check_override (klass, cm, m1);
4393 slot = mono_method_get_vtable_slot (m1);
4397 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4398 char *body_name = mono_method_full_name (cm, TRUE);
4399 char *decl_name = mono_method_full_name (m1, TRUE);
4400 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4406 g_assert (cm->slot < max_vtsize);
4408 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4409 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4410 mono_method_full_name (m1, 1), m1,
4411 mono_method_full_name (cm, 1), cm));
4412 g_hash_table_insert (override_map, m1, cm);
4416 if (mono_class_has_failure (k))
4426 /*Non final newslot methods must be given a non-interface vtable slot*/
4427 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4431 cm->slot = cur_slot++;
4433 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4434 vtable [cm->slot] = cm;
4437 /* override non interface methods */
4438 for (i = 0; i < onum; i++) {
4439 MonoMethod *decl = overrides [i*2];
4440 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4441 g_assert (decl->slot != -1);
4442 vtable [decl->slot] = overrides [i*2 + 1];
4443 overrides [i * 2 + 1]->slot = decl->slot;
4445 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4446 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4447 mono_method_full_name (decl, 1), decl,
4448 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4449 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4451 if (mono_security_core_clr_enabled ())
4452 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4457 * If a method occupies more than one place in the vtable, and it is
4458 * overriden, then change the other occurances too.
4463 for (i = 0; i < max_vtsize; ++i)
4465 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4467 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4472 g_hash_table_destroy (override_map);
4473 override_map = NULL;
4476 g_slist_free (virt_methods);
4477 virt_methods = NULL;
4479 g_assert (cur_slot <= max_vtsize);
4481 /* Ensure that all vtable slots are filled with concrete instance methods */
4482 if (!mono_class_is_abstract (klass)) {
4483 for (i = 0; i < cur_slot; ++i) {
4484 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4485 char *type_name = mono_type_get_full_name (klass);
4486 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4487 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4489 g_free (method_name);
4496 if (mono_class_is_ginst (klass)) {
4497 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4499 mono_class_init (gklass);
4501 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4503 /* Check that the vtable_size value computed in mono_class_init () is correct */
4504 if (klass->vtable_size)
4505 g_assert (cur_slot == klass->vtable_size);
4506 klass->vtable_size = cur_slot;
4509 /* Try to share the vtable with our parent. */
4510 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4511 mono_memory_barrier ();
4512 klass->vtable = klass->parent->vtable;
4514 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4515 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4516 mono_memory_barrier ();
4517 klass->vtable = tmp;
4520 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4521 if (mono_print_vtable) {
4524 print_implemented_interfaces (klass);
4526 for (i = 0; i <= max_iid; i++)
4527 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4530 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4531 klass->vtable_size, icount);
4533 for (i = 0; i < cur_slot; ++i) {
4538 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4539 mono_method_full_name (cm, TRUE));
4545 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4546 klass->name, max_iid);
4548 for (i = 0; i < klass->interface_count; i++) {
4549 ic = klass->interfaces [i];
4550 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4551 mono_class_interface_offset (klass, ic),
4552 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4555 for (k = klass->parent; k ; k = k->parent) {
4556 for (i = 0; i < k->interface_count; i++) {
4557 ic = k->interfaces [i];
4558 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4559 mono_class_interface_offset (klass, ic),
4560 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4568 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4573 char *name = mono_type_get_full_name (klass);
4574 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4578 g_hash_table_destroy (override_map);
4580 g_slist_free (virt_methods);
4585 * mono_method_get_vtable_slot:
4587 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4588 * LOCKING: Acquires the loader lock.
4590 * FIXME Use proper MonoError machinery here.
4593 mono_method_get_vtable_slot (MonoMethod *method)
4595 if (method->slot == -1) {
4596 mono_class_setup_vtable (method->klass);
4597 if (mono_class_has_failure (method->klass))
4599 if (method->slot == -1) {
4603 if (!mono_class_is_ginst (method->klass)) {
4604 g_assert (method->is_inflated);
4605 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4608 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4609 g_assert (mono_class_is_ginst (method->klass));
4610 gklass = mono_class_get_generic_class (method->klass)->container_class;
4611 mono_class_setup_methods (method->klass);
4612 g_assert (method->klass->methods);
4613 mcount = mono_class_get_method_count (method->klass);
4614 for (i = 0; i < mcount; ++i) {
4615 if (method->klass->methods [i] == method)
4618 g_assert (i < mcount);
4619 g_assert (gklass->methods);
4620 method->slot = gklass->methods [i]->slot;
4622 g_assert (method->slot != -1);
4624 return method->slot;
4628 * mono_method_get_vtable_index:
4629 * \param method a method
4631 * Returns the index into the runtime vtable to access the method or,
4632 * in the case of a virtual generic method, the virtual generic method
4633 * thunk. Returns -1 on failure.
4635 * FIXME Use proper MonoError machinery here.
4638 mono_method_get_vtable_index (MonoMethod *method)
4640 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4641 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4642 if (imethod->declaring->is_generic)
4643 return mono_method_get_vtable_slot (imethod->declaring);
4645 return mono_method_get_vtable_slot (method);
4648 static MonoMethod *default_ghc = NULL;
4649 static MonoMethod *default_finalize = NULL;
4650 static int finalize_slot = -1;
4651 static int ghc_slot = -1;
4654 initialize_object_slots (MonoClass *klass)
4659 if (klass == mono_defaults.object_class) {
4660 mono_class_setup_vtable (klass);
4661 for (i = 0; i < klass->vtable_size; ++i) {
4662 MonoMethod *cm = klass->vtable [i];
4664 if (!strcmp (cm->name, "GetHashCode"))
4666 else if (!strcmp (cm->name, "Finalize"))
4670 g_assert (ghc_slot > 0);
4671 default_ghc = klass->vtable [ghc_slot];
4673 g_assert (finalize_slot > 0);
4674 default_finalize = klass->vtable [finalize_slot];
4679 MonoMethod *array_method;
4681 } GenericArrayMethodInfo;
4683 static int generic_array_method_num = 0;
4684 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4687 generic_array_methods (MonoClass *klass)
4689 int i, count_generic = 0, mcount;
4690 GList *list = NULL, *tmp;
4691 if (generic_array_method_num)
4692 return generic_array_method_num;
4693 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4694 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4695 mcount = mono_class_get_method_count (klass->parent);
4696 for (i = 0; i < mcount; i++) {
4697 MonoMethod *m = klass->parent->methods [i];
4698 if (!strncmp (m->name, "InternalArray__", 15)) {
4700 list = g_list_prepend (list, m);
4703 list = g_list_reverse (list);
4704 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4706 for (tmp = list; tmp; tmp = tmp->next) {
4707 const char *mname, *iname;
4709 MonoMethod *m = (MonoMethod *)tmp->data;
4710 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4711 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4713 generic_array_method_info [i].array_method = m;
4714 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4715 iname = "System.Collections.Generic.ICollection`1.";
4716 mname = m->name + 27;
4717 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4718 iname = "System.Collections.Generic.IEnumerable`1.";
4719 mname = m->name + 27;
4720 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4721 iname = "System.Collections.Generic.IReadOnlyList`1.";
4722 mname = m->name + strlen (ireadonlylist_prefix);
4723 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4724 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4725 mname = m->name + strlen (ireadonlycollection_prefix);
4726 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4727 iname = "System.Collections.Generic.IList`1.";
4728 mname = m->name + 15;
4730 g_assert_not_reached ();
4733 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4734 strcpy (name, iname);
4735 strcpy (name + strlen (iname), mname);
4736 generic_array_method_info [i].name = name;
4739 /*g_print ("array generic methods: %d\n", count_generic);*/
4741 generic_array_method_num = count_generic;
4743 return generic_array_method_num;
4747 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4749 MonoGenericContext tmp_context;
4752 tmp_context.class_inst = NULL;
4753 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4754 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4756 for (i = 0; i < generic_array_method_num; i++) {
4758 MonoMethod *m = generic_array_method_info [i].array_method;
4759 MonoMethod *inflated, *helper;
4761 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4762 mono_error_assert_ok (&error);
4763 helper = g_hash_table_lookup (cache, inflated);
4765 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4766 g_hash_table_insert (cache, inflated, helper);
4768 methods [pos ++] = helper;
4773 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4775 int null_length = strlen ("(null)");
4776 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4777 char *s = (char *)mono_image_alloc (image, len);
4780 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4781 g_assert (result == len - 1);
4788 * \param klass the class to initialize
4790 * Compute the \c instance_size, \c class_size and other infos that cannot be
4791 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4792 * Initializes the following fields in \p klass:
4793 * - all the fields initialized by \c mono_class_init_sizes
4798 * LOCKING: Acquires the loader lock.
4800 * \returns TRUE on success or FALSE if there was a problem in loading
4801 * the type (incorrect assemblies, missing assemblies, methods, etc).
4804 mono_class_init (MonoClass *klass)
4806 int i, vtable_size = 0, array_method_count = 0;
4807 MonoCachedClassInfo cached_info;
4808 gboolean has_cached_info;
4809 gboolean locked = FALSE;
4810 gboolean ghcimpl = FALSE;
4811 gboolean has_cctor = FALSE;
4812 int first_iface_slot = 0;
4816 /* Double-checking locking pattern */
4817 if (klass->inited || mono_class_has_failure (klass))
4818 return !mono_class_has_failure (klass);
4820 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4823 * This function can recursively call itself.
4825 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4826 if (g_slist_find (init_list, klass)) {
4827 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4830 init_list = g_slist_prepend (init_list, klass);
4831 mono_native_tls_set_value (init_pending_tls_id, init_list);
4834 * We want to avoid doing complicated work inside locks, so we compute all the required
4835 * information and write it to @klass inside a lock.
4838 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4839 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4843 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4844 MonoClass *element_class = klass->element_class;
4845 if (!element_class->inited)
4846 mono_class_init (element_class);
4847 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4851 mono_stats.initialized_class_count++;
4853 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4854 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4856 mono_class_init (gklass);
4857 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4860 mono_class_setup_interface_id (klass);
4863 if (klass->parent && !klass->parent->inited)
4864 mono_class_init (klass->parent);
4866 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4868 /* Compute instance size etc. */
4869 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4870 if (mono_class_has_failure (klass))
4873 mono_class_setup_supertypes (klass);
4876 initialize_object_slots (klass);
4879 * Initialize the rest of the data without creating a generic vtable if possible.
4880 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4881 * also avoid computing a generic vtable.
4883 if (has_cached_info) {
4885 vtable_size = cached_info.vtable_size;
4886 ghcimpl = cached_info.ghcimpl;
4887 has_cctor = cached_info.has_cctor;
4888 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4889 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4890 * The first slot if for array with.
4892 static int szarray_vtable_size[2] = { 0 };
4894 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4897 if (!szarray_vtable_size [slot]) {
4898 mono_class_setup_vtable (klass);
4899 szarray_vtable_size [slot] = klass->vtable_size;
4900 vtable_size = klass->vtable_size;
4902 vtable_size = szarray_vtable_size[slot];
4904 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4905 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4907 /* Generic instance case */
4908 ghcimpl = gklass->ghcimpl;
4909 has_cctor = gklass->has_cctor;
4911 mono_class_setup_vtable (gklass);
4912 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4915 vtable_size = gklass->vtable_size;
4919 /* ghcimpl is not currently used
4921 if (klass->parent) {
4922 MonoMethod *cmethod = klass->vtable [ghc_slot];
4923 if (cmethod->is_inflated)
4924 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4925 if (cmethod == default_ghc) {
4931 /* C# doesn't allow interfaces to have cctors */
4932 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4933 MonoMethod *cmethod = NULL;
4935 if (mono_class_is_ginst (klass)) {
4936 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4938 /* Generic instance case */
4939 ghcimpl = gklass->ghcimpl;
4940 has_cctor = gklass->has_cctor;
4941 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4942 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4943 /* The find_method function ignores the 'flags' argument */
4944 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4947 mono_class_setup_methods (klass);
4948 if (mono_class_has_failure (klass))
4951 int mcount = mono_class_get_method_count (klass);
4952 for (i = 0; i < mcount; ++i) {
4953 MonoMethod *method = klass->methods [i];
4954 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
4955 (strcmp (".cctor", method->name) == 0)) {
4965 array_method_count = 3 + (klass->rank > 1? 2: 1);
4967 if (klass->interface_count) {
4968 int count_generic = generic_array_methods (klass);
4969 array_method_count += klass->interface_count * count_generic;
4973 if (klass->parent) {
4974 if (!klass->parent->vtable_size)
4975 mono_class_setup_vtable (klass->parent);
4976 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
4978 g_assert (klass->parent->vtable_size);
4979 first_iface_slot = klass->parent->vtable_size;
4980 if (mono_class_need_stelemref_method (klass))
4985 * Do the actual changes to @klass inside the loader lock
4987 mono_loader_lock ();
4990 if (klass->inited || mono_class_has_failure (klass)) {
4991 mono_loader_unlock ();
4992 /* Somebody might have gotten in before us */
4993 return !mono_class_has_failure (klass);
4996 mono_stats.initialized_class_count++;
4998 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
4999 mono_stats.generic_class_count++;
5001 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5002 klass->nested_classes_inited = TRUE;
5003 klass->ghcimpl = ghcimpl;
5004 klass->has_cctor = has_cctor;
5006 klass->vtable_size = vtable_size;
5007 if (has_cached_info) {
5008 klass->has_finalize = cached_info.has_finalize;
5009 klass->has_finalize_inited = TRUE;
5012 mono_class_set_method_count (klass, array_method_count);
5014 mono_loader_unlock ();
5017 setup_interface_offsets (klass, first_iface_slot, TRUE);
5019 if (mono_security_core_clr_enabled ())
5020 mono_security_core_clr_check_inheritance (klass);
5022 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5023 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5028 init_list = g_slist_remove (init_list, klass);
5029 mono_native_tls_set_value (init_pending_tls_id, init_list);
5032 mono_loader_unlock ();
5034 /* Leave this for last */
5035 mono_loader_lock ();
5037 mono_loader_unlock ();
5039 return !mono_class_has_failure (klass);
5043 * mono_class_has_finalizer:
5045 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5049 mono_class_has_finalizer (MonoClass *klass)
5051 gboolean has_finalize = FALSE;
5053 if (klass->has_finalize_inited)
5054 return klass->has_finalize;
5056 /* Interfaces and valuetypes are not supposed to have finalizers */
5057 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5058 MonoMethod *cmethod = NULL;
5060 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5061 } else if (mono_class_is_ginst (klass)) {
5062 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5064 has_finalize = mono_class_has_finalizer (gklass);
5065 } else if (klass->parent && klass->parent->has_finalize) {
5066 has_finalize = TRUE;
5068 if (klass->parent) {
5070 * Can't search in metadata for a method named Finalize, because that
5071 * ignores overrides.
5073 mono_class_setup_vtable (klass);
5074 if (mono_class_has_failure (klass))
5077 cmethod = klass->vtable [finalize_slot];
5081 g_assert (klass->vtable_size > finalize_slot);
5083 if (klass->parent) {
5084 if (cmethod->is_inflated)
5085 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5086 if (cmethod != default_finalize)
5087 has_finalize = TRUE;
5093 mono_loader_lock ();
5094 if (!klass->has_finalize_inited) {
5095 klass->has_finalize = has_finalize ? 1 : 0;
5097 mono_memory_barrier ();
5098 klass->has_finalize_inited = TRUE;
5100 mono_loader_unlock ();
5102 return klass->has_finalize;
5106 mono_is_corlib_image (MonoImage *image)
5108 return image == mono_defaults.corlib;
5112 * LOCKING: this assumes the loader lock is held
5115 mono_class_setup_mono_type (MonoClass *klass)
5117 const char *name = klass->name;
5118 const char *nspace = klass->name_space;
5119 gboolean is_corlib = mono_is_corlib_image (klass->image);
5121 klass->this_arg.byref = 1;
5122 klass->this_arg.data.klass = klass;
5123 klass->this_arg.type = MONO_TYPE_CLASS;
5124 klass->byval_arg.data.klass = klass;
5125 klass->byval_arg.type = MONO_TYPE_CLASS;
5127 if (is_corlib && !strcmp (nspace, "System")) {
5128 if (!strcmp (name, "ValueType")) {
5130 * do not set the valuetype bit for System.ValueType.
5131 * klass->valuetype = 1;
5133 klass->blittable = TRUE;
5134 } else if (!strcmp (name, "Enum")) {
5136 * do not set the valuetype bit for System.Enum.
5137 * klass->valuetype = 1;
5139 klass->valuetype = 0;
5140 klass->enumtype = 0;
5141 } else if (!strcmp (name, "Object")) {
5142 klass->byval_arg.type = MONO_TYPE_OBJECT;
5143 klass->this_arg.type = MONO_TYPE_OBJECT;
5144 } else if (!strcmp (name, "String")) {
5145 klass->byval_arg.type = MONO_TYPE_STRING;
5146 klass->this_arg.type = MONO_TYPE_STRING;
5147 } else if (!strcmp (name, "TypedReference")) {
5148 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5149 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5153 if (klass->valuetype) {
5154 int t = MONO_TYPE_VALUETYPE;
5156 if (is_corlib && !strcmp (nspace, "System")) {
5159 if (!strcmp (name, "Boolean")) {
5160 t = MONO_TYPE_BOOLEAN;
5161 } else if (!strcmp(name, "Byte")) {
5163 klass->blittable = TRUE;
5167 if (!strcmp (name, "Char")) {
5172 if (!strcmp (name, "Double")) {
5174 klass->blittable = TRUE;
5178 if (!strcmp (name, "Int32")) {
5180 klass->blittable = TRUE;
5181 } else if (!strcmp(name, "Int16")) {
5183 klass->blittable = TRUE;
5184 } else if (!strcmp(name, "Int64")) {
5186 klass->blittable = TRUE;
5187 } else if (!strcmp(name, "IntPtr")) {
5189 klass->blittable = TRUE;
5193 if (!strcmp (name, "Single")) {
5195 klass->blittable = TRUE;
5196 } else if (!strcmp(name, "SByte")) {
5198 klass->blittable = TRUE;
5202 if (!strcmp (name, "UInt32")) {
5204 klass->blittable = TRUE;
5205 } else if (!strcmp(name, "UInt16")) {
5207 klass->blittable = TRUE;
5208 } else if (!strcmp(name, "UInt64")) {
5210 klass->blittable = TRUE;
5211 } else if (!strcmp(name, "UIntPtr")) {
5213 klass->blittable = TRUE;
5217 if (!strcmp (name, "TypedReference")) {
5218 t = MONO_TYPE_TYPEDBYREF;
5219 klass->blittable = TRUE;
5223 if (!strcmp (name, "Void")) {
5231 klass->byval_arg.type = (MonoTypeEnum)t;
5232 klass->this_arg.type = (MonoTypeEnum)t;
5235 if (MONO_CLASS_IS_INTERFACE (klass)) {
5236 klass->interface_id = mono_get_unique_iid (klass);
5238 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5239 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5240 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5241 * MS returns diferrent types based on which instance is called. For example:
5242 * object obj = new byte[10][];
5243 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5244 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5247 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5248 klass->is_array_special_interface = 1;
5255 * COM initialization is delayed until needed.
5256 * However when a [ComImport] attribute is present on a type it will trigger
5257 * the initialization. This is not a problem unless the BCL being executed
5258 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5261 init_com_from_comimport (MonoClass *klass)
5263 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5264 if (mono_security_core_clr_enabled ()) {
5265 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5266 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5267 /* but it can not be made available for application (i.e. user code) since all COM calls
5268 * are considered native calls. In this case we fail with a TypeLoadException (just like
5269 * Silverlight 2 does */
5270 mono_class_set_type_load_failure (klass, "");
5275 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5277 #endif /*DISABLE_COM*/
5280 * LOCKING: this assumes the loader lock is held
5283 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5285 gboolean system_namespace;
5286 gboolean is_corlib = mono_is_corlib_image (klass->image);
5288 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5290 /* if root of the hierarchy */
5291 if (system_namespace && !strcmp (klass->name, "Object")) {
5292 klass->parent = NULL;
5293 klass->instance_size = sizeof (MonoObject);
5296 if (!strcmp (klass->name, "<Module>")) {
5297 klass->parent = NULL;
5298 klass->instance_size = 0;
5302 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5303 /* Imported COM Objects always derive from __ComObject. */
5305 if (MONO_CLASS_IS_IMPORT (klass)) {
5306 init_com_from_comimport (klass);
5307 if (parent == mono_defaults.object_class)
5308 parent = mono_class_get_com_object_class ();
5312 /* set the parent to something useful and safe, but mark the type as broken */
5313 parent = mono_defaults.object_class;
5314 mono_class_set_type_load_failure (klass, "");
5318 klass->parent = parent;
5320 if (mono_class_is_ginst (parent) && !parent->name) {
5322 * If the parent is a generic instance, we may get
5323 * called before it is fully initialized, especially
5324 * before it has its name.
5329 #ifndef DISABLE_REMOTING
5330 klass->marshalbyref = parent->marshalbyref;
5331 klass->contextbound = parent->contextbound;
5334 klass->delegate = parent->delegate;
5336 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5337 mono_class_set_is_com_object (klass);
5339 if (system_namespace) {
5340 #ifndef DISABLE_REMOTING
5341 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5342 klass->marshalbyref = 1;
5344 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5345 klass->contextbound = 1;
5347 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5348 klass->delegate = 1;
5351 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5352 (strcmp (klass->parent->name_space, "System") == 0)))
5353 klass->valuetype = 1;
5354 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5355 klass->valuetype = klass->enumtype = 1;
5357 /*klass->enumtype = klass->parent->enumtype; */
5359 /* initialize com types if COM interfaces are present */
5361 if (MONO_CLASS_IS_IMPORT (klass))
5362 init_com_from_comimport (klass);
5364 klass->parent = NULL;
5370 * mono_class_setup_supertypes:
5373 * Build the data structure needed to make fast type checks work.
5374 * This currently sets two fields in @class:
5375 * - idepth: distance between @class and System.Object in the type
5377 * - supertypes: array of classes: each element has a class in the hierarchy
5378 * starting from @class up to System.Object
5380 * LOCKING: Acquires the loader lock.
5383 mono_class_setup_supertypes (MonoClass *klass)
5386 MonoClass **supertypes;
5388 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5392 if (klass->parent && !klass->parent->supertypes)
5393 mono_class_setup_supertypes (klass->parent);
5395 idepth = klass->parent->idepth + 1;
5399 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5400 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5402 if (klass->parent) {
5403 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5406 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5407 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5409 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5412 mono_memory_barrier ();
5414 mono_loader_lock ();
5415 klass->idepth = idepth;
5416 /* Needed so idepth is visible before supertypes is set */
5417 mono_memory_barrier ();
5418 klass->supertypes = supertypes;
5419 mono_loader_unlock ();
5423 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5425 return mono_class_get_generic_class (gclass)->container_class == user_data;
5429 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5431 MonoClass *gtd = (MonoClass*)user_data;
5432 /* Only try to fix generic instances of @gtd */
5433 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5436 /* Check if the generic instance has no parent. */
5437 if (gtd->parent && !gclass->parent)
5438 mono_generic_class_setup_parent (gclass, gtd);
5444 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5446 mono_class_set_type_load_failure (klass, "%s", msg);
5447 mono_error_set_type_load_class (error, klass, "%s", msg);
5451 * mono_class_create_from_typedef:
5452 * \param image: image where the token is valid
5453 * \param type_token: typedef token
5454 * \param error: used to return any error found while creating the type
5456 * Create the MonoClass* representing the specified type token.
5457 * \p type_token must be a TypeDef token.
5459 * FIXME: don't return NULL on failure, just the the caller figure it out.
5462 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5464 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5465 MonoClass *klass, *parent = NULL;
5466 guint32 cols [MONO_TYPEDEF_SIZE];
5467 guint32 cols_next [MONO_TYPEDEF_SIZE];
5468 guint tidx = mono_metadata_token_index (type_token);
5469 MonoGenericContext *context = NULL;
5470 const char *name, *nspace;
5472 MonoClass **interfaces;
5473 guint32 field_last, method_last;
5474 guint32 nesting_tokeen;
5478 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5479 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5483 mono_loader_lock ();
5485 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5486 mono_loader_unlock ();
5490 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5492 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5493 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5495 if (mono_metadata_has_generic_params (image, type_token)) {
5496 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5497 klass->class_kind = MONO_CLASS_GTD;
5498 classes_size += sizeof (MonoClassGtd);
5501 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5502 klass->class_kind = MONO_CLASS_DEF;
5503 classes_size += sizeof (MonoClassDef);
5508 klass->name_space = nspace;
5510 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5512 klass->image = image;
5513 klass->type_token = type_token;
5514 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5516 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5519 * Check whether we're a generic type definition.
5521 if (mono_class_is_gtd (klass)) {
5522 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5523 generic_container->owner.klass = klass;
5524 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5525 context = &generic_container->context;
5526 mono_class_set_generic_container (klass, generic_container);
5527 enable_gclass_recording ();
5530 if (cols [MONO_TYPEDEF_EXTENDS]) {
5532 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5534 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5535 /*WARNING: this must satisfy mono_metadata_type_hash*/
5536 klass->this_arg.byref = 1;
5537 klass->this_arg.data.klass = klass;
5538 klass->this_arg.type = MONO_TYPE_CLASS;
5539 klass->byval_arg.data.klass = klass;
5540 klass->byval_arg.type = MONO_TYPE_CLASS;
5542 parent = mono_class_get_checked (image, parent_token, error);
5543 if (parent && context) /* Always inflate */
5544 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5546 if (parent == NULL) {
5547 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5548 goto parent_failure;
5551 for (tmp = parent; tmp; tmp = tmp->parent) {
5553 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5554 goto parent_failure;
5556 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5557 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5558 goto parent_failure;
5563 mono_class_setup_parent (klass, parent);
5565 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5566 mono_class_setup_mono_type (klass);
5568 if (mono_class_is_gtd (klass))
5569 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5572 * This might access klass->byval_arg for recursion generated by generic constraints,
5573 * so it has to come after setup_mono_type ().
5575 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5576 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5577 if (!mono_error_ok (error)) {
5578 /*FIXME implement a mono_class_set_failure_from_mono_error */
5579 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5580 mono_loader_unlock ();
5581 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5586 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5590 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5594 klass->cast_class = klass->element_class = klass;
5595 if (mono_is_corlib_image (klass->image)) {
5596 switch (klass->byval_arg.type) {
5598 if (mono_defaults.byte_class)
5599 klass->cast_class = mono_defaults.byte_class;
5602 if (mono_defaults.sbyte_class)
5603 mono_defaults.sbyte_class = klass;
5606 if (mono_defaults.uint16_class)
5607 mono_defaults.uint16_class = klass;
5610 if (mono_defaults.int16_class)
5611 klass->cast_class = mono_defaults.int16_class;
5614 if (mono_defaults.uint32_class)
5615 mono_defaults.uint32_class = klass;
5618 if (mono_defaults.int32_class)
5619 klass->cast_class = mono_defaults.int32_class;
5622 if (mono_defaults.uint64_class)
5623 mono_defaults.uint64_class = klass;
5626 if (mono_defaults.int64_class)
5627 klass->cast_class = mono_defaults.int64_class;
5632 if (!klass->enumtype) {
5633 if (!mono_metadata_interfaces_from_typedef_full (
5634 image, type_token, &interfaces, &icount, FALSE, context, 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);
5642 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5643 g_assert(icount <= 65535);
5645 klass->interfaces = interfaces;
5646 klass->interface_count = icount;
5647 klass->interfaces_inited = 1;
5650 /*g_print ("Load class %s\n", name);*/
5653 * Compute the field and method lists
5655 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5656 mono_class_set_first_field_idx (klass, first_field_idx);
5657 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5658 mono_class_set_first_method_idx (klass, first_method_idx);
5660 if (tt->rows > tidx){
5661 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5662 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5663 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5665 field_last = image->tables [MONO_TABLE_FIELD].rows;
5666 method_last = image->tables [MONO_TABLE_METHOD].rows;
5669 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5670 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5671 mono_class_set_field_count (klass, field_last - first_field_idx);
5672 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5673 mono_class_set_method_count (klass, method_last - first_method_idx);
5675 /* reserve space to store vector pointer in arrays */
5676 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5677 klass->instance_size += 2 * sizeof (gpointer);
5678 g_assert (mono_class_get_field_count (klass) == 0);
5681 if (klass->enumtype) {
5682 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5683 if (!enum_basetype) {
5684 /*set it to a default value as the whole runtime can't handle this to be null*/
5685 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5686 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5687 mono_loader_unlock ();
5688 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5691 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5695 * If we're a generic type definition, load the constraints.
5696 * We must do this after the class has been constructed to make certain recursive scenarios
5699 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5700 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5701 mono_loader_unlock ();
5702 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5706 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5707 if (!strncmp (name, "Vector", 6))
5708 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");
5709 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5710 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5711 klass->simd_type = 1;
5714 mono_loader_unlock ();
5716 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5721 if (mono_class_is_gtd (klass))
5722 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5724 mono_class_setup_mono_type (klass);
5725 mono_loader_unlock ();
5726 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5730 /** Is klass a Nullable<T> ginst? */
5732 mono_class_is_nullable (MonoClass *klass)
5734 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5735 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5739 /** if klass is T? return T */
5741 mono_class_get_nullable_param (MonoClass *klass)
5743 g_assert (mono_class_is_nullable (klass));
5744 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5748 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5752 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5754 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5755 if (!mono_error_ok (&error)) {
5756 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5757 klass->parent = mono_defaults.object_class;
5758 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5759 mono_error_cleanup (&error);
5762 mono_loader_lock ();
5764 mono_class_setup_parent (klass, klass->parent);
5766 if (klass->enumtype) {
5767 klass->cast_class = gtd->cast_class;
5768 klass->element_class = gtd->element_class;
5770 mono_loader_unlock ();
5774 mono_type_is_primitive (MonoType *type)
5776 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5777 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5781 * Create the `MonoClass' for an instantiation of a generic type.
5782 * We only do this if we actually need it.
5785 mono_generic_class_get_class (MonoGenericClass *gclass)
5787 MonoClass *klass, *gklass;
5789 if (gclass->cached_class)
5790 return gclass->cached_class;
5792 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5794 gklass = gclass->container_class;
5796 if (gklass->nested_in) {
5797 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5798 klass->nested_in = gklass->nested_in;
5801 klass->name = gklass->name;
5802 klass->name_space = gklass->name_space;
5804 klass->image = gklass->image;
5805 klass->type_token = gklass->type_token;
5807 klass->class_kind = MONO_CLASS_GINST;
5809 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5811 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5812 klass->this_arg.type = klass->byval_arg.type;
5813 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5814 klass->this_arg.byref = TRUE;
5815 klass->enumtype = gklass->enumtype;
5816 klass->valuetype = gklass->valuetype;
5819 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5820 g_assert (gclass->context.class_inst);
5821 g_assert (gclass->context.class_inst->type_argc > 0);
5822 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5823 klass->simd_type = 1;
5825 klass->is_array_special_interface = gklass->is_array_special_interface;
5827 klass->cast_class = klass->element_class = klass;
5829 if (gclass->is_dynamic) {
5831 * 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.
5832 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5833 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5835 if (!gklass->wastypebuilder)
5838 if (klass->enumtype) {
5840 * For enums, gklass->fields might not been set, but instance_size etc. is
5841 * already set in mono_reflection_create_internal_class (). For non-enums,
5842 * these will be computed normally in mono_class_layout_fields ().
5844 klass->instance_size = gklass->instance_size;
5845 klass->sizes.class_size = gklass->sizes.class_size;
5846 klass->size_inited = 1;
5850 mono_loader_lock ();
5852 if (gclass->cached_class) {
5853 mono_loader_unlock ();
5854 return gclass->cached_class;
5857 if (record_gclass_instantiation > 0)
5858 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5860 if (mono_class_is_nullable (klass))
5861 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5863 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5865 mono_generic_class_setup_parent (klass, gklass);
5867 if (gclass->is_dynamic)
5868 mono_class_setup_supertypes (klass);
5870 mono_memory_barrier ();
5871 gclass->cached_class = klass;
5873 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5875 ++class_ginst_count;
5876 inflated_classes_size += sizeof (MonoClassGenericInst);
5878 mono_loader_unlock ();
5884 get_image_for_container (MonoGenericContainer *container)
5887 if (container->is_anonymous) {
5888 result = container->owner.image;
5891 if (container->is_method) {
5892 MonoMethod *method = container->owner.method;
5893 g_assert_checked (method);
5894 klass = method->klass;
5896 klass = container->owner.klass;
5898 g_assert_checked (klass);
5899 result = klass->image;
5906 get_image_for_generic_param (MonoGenericParam *param)
5908 MonoGenericContainer *container = mono_generic_param_owner (param);
5909 g_assert_checked (container);
5910 return get_image_for_container (container);
5913 // Make a string in the designated image consisting of a single integer.
5914 #define INT_STRING_SIZE 16
5916 make_generic_name_string (MonoImage *image, int num)
5918 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5919 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5923 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5924 // pinfo is derived from param by the caller for us.
5926 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5928 MonoClass *klass, **ptr;
5930 MonoGenericContainer *container = mono_generic_param_owner (param);
5931 g_assert_checked (container);
5933 MonoImage *image = get_image_for_container (container);
5934 gboolean is_mvar = container->is_method;
5935 gboolean is_anonymous = container->is_anonymous;
5937 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5938 klass->class_kind = MONO_CLASS_GPARAM;
5939 classes_size += sizeof (MonoClassGenericParam);
5940 ++class_gparam_count;
5943 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5945 int n = mono_generic_param_num (param);
5946 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5950 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
5951 } else if (is_mvar) {
5952 MonoMethod *omethod = container->owner.method;
5953 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
5955 MonoClass *oklass = container->owner.klass;
5956 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
5959 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5961 // Count non-NULL items in pinfo->constraints
5964 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5968 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5969 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
5971 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
5972 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
5974 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
5977 if (count - pos > 0) {
5978 klass->interface_count = count - pos;
5979 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
5980 klass->interfaces_inited = TRUE;
5981 for (i = pos; i < count; i++)
5982 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
5985 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
5987 klass->inited = TRUE;
5988 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
5989 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
5991 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5992 klass->this_arg.type = klass->byval_arg.type;
5993 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
5994 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
5995 klass->this_arg.byref = TRUE;
5997 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5998 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6000 /*Init these fields to sane values*/
6001 klass->min_align = 1;
6003 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6004 * constrained to, the JIT depends on this.
6006 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6007 mono_memory_barrier ();
6008 klass->size_inited = 1;
6010 mono_class_setup_supertypes (klass);
6012 if (count - pos > 0) {
6013 mono_class_setup_vtable (klass->parent);
6014 if (mono_class_has_failure (klass->parent))
6015 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6017 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6023 #define FAST_CACHE_SIZE 16
6026 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6027 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6028 * we cache the MonoClasses.
6029 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6030 * LOCKING: Takes the image lock depending on @take_lock.
6033 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6035 int n = mono_generic_param_num (param);
6036 MonoImage *image = get_image_for_generic_param (param);
6037 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6038 MonoClass *klass = NULL;
6043 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6044 // For high numbers or constraints we have to use pointer hashes.
6045 if (param->gshared_constraint) {
6046 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6049 mono_image_lock (image);
6050 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6052 mono_image_unlock (image);
6057 if (n < FAST_CACHE_SIZE) {
6059 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6061 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6063 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6066 mono_image_lock (image);
6067 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6069 mono_image_unlock (image);
6076 * LOCKING: Image lock (param->image) must be held
6079 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6081 int n = mono_generic_param_num (param);
6082 MonoImage *image = get_image_for_generic_param (param);
6083 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6087 if (param->gshared_constraint) {
6088 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6090 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6091 mono_memory_barrier ();
6093 image->mvar_cache_constrained = ht;
6095 image->var_cache_constrained = ht;
6097 g_hash_table_insert (ht, param, klass);
6098 } else if (n < FAST_CACHE_SIZE) {
6100 /* Requires locking to avoid droping an already published class */
6101 if (!image->mvar_cache_fast)
6102 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6103 image->mvar_cache_fast [n] = klass;
6105 if (!image->var_cache_fast)
6106 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6107 image->var_cache_fast [n] = klass;
6110 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6112 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6114 ht = g_hash_table_new (NULL, NULL);
6115 mono_memory_barrier ();
6117 image->mvar_cache_slow = ht;
6119 image->var_cache_slow = ht;
6122 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6127 * LOCKING: Acquires the image lock (@image).
6130 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6132 MonoImage *image = get_image_for_generic_param (param);
6133 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6134 MonoClass *klass, *klass2;
6136 // If a klass already exists for this object and is cached, return it.
6137 if (pinfo) // Non-anonymous
6138 klass = pinfo->pklass;
6140 klass = get_anon_gparam_class (param, TRUE);
6145 // Create a new klass
6146 klass = make_generic_param_class (param, pinfo);
6148 // Now we need to cache the klass we created.
6149 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6150 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6151 // and allow our newly-created klass object to just leak.
6152 mono_memory_barrier ();
6154 mono_image_lock (image);
6156 // Here "klass2" refers to the klass potentially created by the other thread.
6157 if (pinfo) // Repeat check from above
6158 klass2 = pinfo->pklass;
6160 klass2 = get_anon_gparam_class (param, FALSE);
6167 pinfo->pklass = klass;
6169 set_anon_gparam_class (param, klass);
6171 mono_image_unlock (image);
6173 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6175 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6177 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6183 * mono_class_from_generic_parameter:
6184 * \param param Parameter to find/construct a class for.
6185 * \param arg2 Is ignored.
6186 * \param arg3 Is ignored.
6189 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6191 return mono_class_from_generic_parameter_internal (param);
6195 mono_ptr_class_get (MonoType *type)
6198 MonoClass *el_class;
6202 el_class = mono_class_from_mono_type (type);
6203 image = el_class->image;
6205 mono_image_lock (image);
6206 if (image->ptr_cache) {
6207 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6208 mono_image_unlock (image);
6212 mono_image_unlock (image);
6214 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6216 classes_size += sizeof (MonoClassPointer);
6217 ++class_pointer_count;
6219 result->parent = NULL; /* no parent for PTR types */
6220 result->name_space = el_class->name_space;
6221 name = g_strdup_printf ("%s*", el_class->name);
6222 result->name = mono_image_strdup (image, name);
6223 result->class_kind = MONO_CLASS_POINTER;
6226 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6228 result->image = el_class->image;
6229 result->inited = TRUE;
6230 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6231 result->cast_class = result->element_class = el_class;
6232 result->blittable = TRUE;
6234 result->byval_arg.type = MONO_TYPE_PTR;
6235 result->this_arg.type = result->byval_arg.type;
6236 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6237 result->this_arg.byref = TRUE;
6239 mono_class_setup_supertypes (result);
6241 mono_image_lock (image);
6242 if (image->ptr_cache) {
6244 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6245 mono_image_unlock (image);
6246 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6250 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6252 g_hash_table_insert (image->ptr_cache, el_class, result);
6253 mono_image_unlock (image);
6255 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6261 mono_fnptr_class_get (MonoMethodSignature *sig)
6263 MonoClass *result, *cached;
6264 static GHashTable *ptr_hash = NULL;
6266 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6268 mono_loader_lock ();
6270 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6271 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6272 mono_loader_unlock ();
6276 result = g_new0 (MonoClass, 1);
6278 result->parent = NULL; /* no parent for PTR types */
6279 result->name_space = "System";
6280 result->name = "MonoFNPtrFakeClass";
6281 result->class_kind = MONO_CLASS_POINTER;
6283 result->image = mono_defaults.corlib; /* need to fix... */
6284 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6285 result->cast_class = result->element_class = result;
6286 result->byval_arg.type = MONO_TYPE_FNPTR;
6287 result->this_arg.type = result->byval_arg.type;
6288 result->this_arg.data.method = result->byval_arg.data.method = sig;
6289 result->this_arg.byref = TRUE;
6290 result->blittable = TRUE;
6291 result->inited = TRUE;
6293 mono_class_setup_supertypes (result);
6295 mono_loader_lock ();
6297 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6300 mono_loader_unlock ();
6304 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6306 classes_size += sizeof (MonoClassPointer);
6307 ++class_pointer_count;
6309 g_hash_table_insert (ptr_hash, sig, result);
6311 mono_loader_unlock ();
6313 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6319 * mono_class_from_mono_type:
6320 * \param type describes the type to return
6321 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6324 mono_class_from_mono_type (MonoType *type)
6326 switch (type->type) {
6327 case MONO_TYPE_OBJECT:
6328 return type->data.klass? type->data.klass: mono_defaults.object_class;
6329 case MONO_TYPE_VOID:
6330 return type->data.klass? type->data.klass: mono_defaults.void_class;
6331 case MONO_TYPE_BOOLEAN:
6332 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6333 case MONO_TYPE_CHAR:
6334 return type->data.klass? type->data.klass: mono_defaults.char_class;
6336 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6338 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6340 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6342 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6344 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6346 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6348 return type->data.klass? type->data.klass: mono_defaults.int_class;
6350 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6352 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6354 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6356 return type->data.klass? type->data.klass: mono_defaults.single_class;
6358 return type->data.klass? type->data.klass: mono_defaults.double_class;
6359 case MONO_TYPE_STRING:
6360 return type->data.klass? type->data.klass: mono_defaults.string_class;
6361 case MONO_TYPE_TYPEDBYREF:
6362 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6363 case MONO_TYPE_ARRAY:
6364 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6366 return mono_ptr_class_get (type->data.type);
6367 case MONO_TYPE_FNPTR:
6368 return mono_fnptr_class_get (type->data.method);
6369 case MONO_TYPE_SZARRAY:
6370 return mono_array_class_get (type->data.klass, 1);
6371 case MONO_TYPE_CLASS:
6372 case MONO_TYPE_VALUETYPE:
6373 return type->data.klass;
6374 case MONO_TYPE_GENERICINST:
6375 return mono_generic_class_get_class (type->data.generic_class);
6376 case MONO_TYPE_MVAR:
6378 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6380 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6381 g_assert_not_reached ();
6384 // Yes, this returns NULL, even if it is documented as not doing so, but there
6385 // is no way for the code to make it this far, due to the assert above.
6390 * mono_type_retrieve_from_typespec
6391 * \param image context where the image is created
6392 * \param type_spec typespec token
6393 * \param context the generic context used to evaluate generic instantiations in
6396 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6398 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6400 *did_inflate = FALSE;
6405 if (context && (context->class_inst || context->method_inst)) {
6406 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6408 if (!mono_error_ok (error)) {
6414 *did_inflate = TRUE;
6421 * mono_class_create_from_typespec
6422 * \param image context where the image is created
6423 * \param type_spec typespec token
6424 * \param context the generic context used to evaluate generic instantiations in
6427 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6430 gboolean inflated = FALSE;
6431 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6432 return_val_if_nok (error, NULL);
6433 ret = mono_class_from_mono_type (t);
6435 mono_metadata_free_type (t);
6440 * mono_bounded_array_class_get:
6441 * \param element_class element class
6442 * \param rank the dimension of the array class
6443 * \param bounded whenever the array has non-zero bounds
6445 * \returns A class object describing the array with element type \p element_type and
6446 * dimension \p rank.
6449 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6452 MonoClass *klass, *cached, *k;
6453 MonoClass *parent = NULL;
6454 GSList *list, *rootlist = NULL;
6458 g_assert (rank <= 255);
6461 /* bounded only matters for one-dimensional arrays */
6464 image = eclass->image;
6468 if (rank == 1 && !bounded) {
6470 * This case is very frequent not just during compilation because of calls
6471 * from mono_class_from_mono_type (), mono_array_new (),
6472 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6474 mono_os_mutex_lock (&image->szarray_cache_lock);
6475 if (!image->szarray_cache)
6476 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6477 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6478 mono_os_mutex_unlock (&image->szarray_cache_lock);
6480 mono_loader_lock ();
6481 if (!image->array_cache)
6482 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6483 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6484 for (list = rootlist; list; list = list->next) {
6485 k = (MonoClass *)list->data;
6486 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6491 mono_loader_unlock ();
6496 parent = mono_defaults.array_class;
6497 if (!parent->inited)
6498 mono_class_init (parent);
6500 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6502 klass->image = image;
6503 klass->name_space = eclass->name_space;
6504 klass->class_kind = MONO_CLASS_ARRAY;
6506 nsize = strlen (eclass->name);
6507 name = (char *)g_malloc (nsize + 2 + rank + 1);
6508 memcpy (name, eclass->name, nsize);
6511 memset (name + nsize + 1, ',', rank - 1);
6513 name [nsize + rank] = '*';
6514 name [nsize + rank + bounded] = ']';
6515 name [nsize + rank + bounded + 1] = 0;
6516 klass->name = mono_image_strdup (image, name);
6519 klass->type_token = 0;
6520 klass->parent = parent;
6521 klass->instance_size = mono_class_instance_size (klass->parent);
6523 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6524 /*Arrays of those two types are invalid.*/
6525 MonoError prepared_error;
6526 error_init (&prepared_error);
6527 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6528 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6529 mono_error_cleanup (&prepared_error);
6530 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6531 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6532 if (!ref_info_handle || eclass->wastypebuilder) {
6533 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6534 g_assert (ref_info_handle && !eclass->wastypebuilder);
6536 /* element_size -1 is ok as this is not an instantitable type*/
6537 klass->sizes.element_size = -1;
6539 klass->sizes.element_size = mono_class_array_element_size (eclass);
6541 mono_class_setup_supertypes (klass);
6543 if (mono_class_is_ginst (eclass))
6544 mono_class_init (eclass);
6545 if (!eclass->size_inited)
6546 mono_class_setup_fields (eclass);
6547 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6548 /*FIXME we fail the array type, but we have to let other fields be set.*/
6550 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6554 if (eclass->enumtype)
6555 klass->cast_class = eclass->element_class;
6557 klass->cast_class = eclass;
6559 switch (klass->cast_class->byval_arg.type) {
6561 klass->cast_class = mono_defaults.byte_class;
6564 klass->cast_class = mono_defaults.int16_class;
6567 #if SIZEOF_VOID_P == 4
6571 klass->cast_class = mono_defaults.int32_class;
6574 #if SIZEOF_VOID_P == 8
6578 klass->cast_class = mono_defaults.int64_class;
6584 klass->element_class = eclass;
6586 if ((rank > 1) || bounded) {
6587 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6588 klass->byval_arg.type = MONO_TYPE_ARRAY;
6589 klass->byval_arg.data.array = at;
6590 at->eklass = eclass;
6592 /* FIXME: complete.... */
6594 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6595 klass->byval_arg.data.klass = eclass;
6597 klass->this_arg = klass->byval_arg;
6598 klass->this_arg.byref = 1;
6601 MonoError prepared_error;
6602 error_init (&prepared_error);
6603 name = mono_type_get_full_name (klass);
6604 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6605 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6606 mono_error_cleanup (&prepared_error);
6610 mono_loader_lock ();
6612 /* Check cache again */
6614 if (rank == 1 && !bounded) {
6615 mono_os_mutex_lock (&image->szarray_cache_lock);
6616 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6617 mono_os_mutex_unlock (&image->szarray_cache_lock);
6619 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6620 for (list = rootlist; list; list = list->next) {
6621 k = (MonoClass *)list->data;
6622 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6629 mono_loader_unlock ();
6633 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6635 classes_size += sizeof (MonoClassArray);
6636 ++class_array_count;
6638 if (rank == 1 && !bounded) {
6639 mono_os_mutex_lock (&image->szarray_cache_lock);
6640 g_hash_table_insert (image->szarray_cache, eclass, klass);
6641 mono_os_mutex_unlock (&image->szarray_cache_lock);
6643 list = g_slist_append (rootlist, klass);
6644 g_hash_table_insert (image->array_cache, eclass, list);
6647 mono_loader_unlock ();
6649 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6655 * mono_array_class_get:
6656 * \param element_class element class
6657 * \param rank the dimension of the array class
6659 * \returns A class object describing the array with element type \p element_type and
6660 * dimension \p rank.
6663 mono_array_class_get (MonoClass *eclass, guint32 rank)
6665 return mono_bounded_array_class_get (eclass, rank, FALSE);
6669 * mono_class_instance_size:
6670 * \param klass a class
6672 * Use to get the size of a class in bytes.
6674 * \returns The size of an object instance
6677 mono_class_instance_size (MonoClass *klass)
6679 if (!klass->size_inited)
6680 mono_class_init (klass);
6682 return klass->instance_size;
6686 * mono_class_min_align:
6687 * \param klass a class
6689 * Use to get the computed minimum alignment requirements for the specified class.
6691 * Returns: minimum alignment requirements
6694 mono_class_min_align (MonoClass *klass)
6696 if (!klass->size_inited)
6697 mono_class_init (klass);
6699 return klass->min_align;
6703 * mono_class_value_size:
6704 * \param klass a class
6706 * This function is used for value types, and return the
6707 * space and the alignment to store that kind of value object.
6709 * \returns the size of a value of kind \p klass
6712 mono_class_value_size (MonoClass *klass, guint32 *align)
6716 /* fixme: check disable, because we still have external revereces to
6717 * mscorlib and Dummy Objects
6719 /*g_assert (klass->valuetype);*/
6721 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6724 *align = klass->min_align;
6730 * mono_class_data_size:
6731 * \param klass a class
6733 * \returns The size of the static class data
6736 mono_class_data_size (MonoClass *klass)
6739 mono_class_init (klass);
6740 /* This can happen with dynamically created types */
6741 if (!klass->fields_inited)
6742 mono_class_setup_fields (klass);
6744 /* in arrays, sizes.class_size is unioned with element_size
6745 * and arrays have no static fields
6749 return klass->sizes.class_size;
6753 * Auxiliary routine to mono_class_get_field
6755 * Takes a field index instead of a field token.
6757 static MonoClassField *
6758 mono_class_get_field_idx (MonoClass *klass, int idx)
6760 mono_class_setup_fields (klass);
6761 if (mono_class_has_failure (klass))
6765 int first_field_idx = mono_class_get_first_field_idx (klass);
6766 int fcount = mono_class_get_field_count (klass);
6767 if (klass->image->uncompressed_metadata) {
6769 * first_field_idx points to the FieldPtr table, while idx points into the
6770 * Field table, so we have to do a search.
6772 /*FIXME this is broken for types with multiple fields with the same name.*/
6773 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6776 for (i = 0; i < fcount; ++i)
6777 if (mono_field_get_name (&klass->fields [i]) == name)
6778 return &klass->fields [i];
6779 g_assert_not_reached ();
6782 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6783 return &klass->fields [idx - first_field_idx];
6787 klass = klass->parent;
6793 * mono_class_get_field:
6794 * \param class the class to lookup the field.
6795 * \param field_token the field token
6797 * \returns A \c MonoClassField representing the type and offset of
6798 * the field, or a NULL value if the field does not belong to this
6802 mono_class_get_field (MonoClass *klass, guint32 field_token)
6804 int idx = mono_metadata_token_index (field_token);
6806 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6808 return mono_class_get_field_idx (klass, idx - 1);
6812 * mono_class_get_field_from_name:
6813 * \param klass the class to lookup the field.
6814 * \param name the field name
6816 * Search the class \p klass and its parents for a field with the name \p name.
6818 * \returns The \c MonoClassField pointer of the named field or NULL
6821 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6823 return mono_class_get_field_from_name_full (klass, name, NULL);
6827 * mono_class_get_field_from_name_full:
6828 * \param klass the class to lookup the field.
6829 * \param name the field name
6830 * \param type the type of the fields. This optional.
6832 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6834 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6835 * of its generic type definition.
6837 * \returns The MonoClassField pointer of the named field or NULL
6840 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6844 mono_class_setup_fields (klass);
6845 if (mono_class_has_failure (klass))
6849 int fcount = mono_class_get_field_count (klass);
6850 for (i = 0; i < fcount; ++i) {
6851 MonoClassField *field = &klass->fields [i];
6853 if (strcmp (name, mono_field_get_name (field)) != 0)
6857 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6858 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6863 klass = klass->parent;
6869 * mono_class_get_field_token:
6870 * \param field the field we need the token of
6872 * Get the token of a field. Note that the tokesn is only valid for the image
6873 * the field was loaded from. Don't use this function for fields in dynamic types.
6875 * \returns The token representing the field in the image it was loaded from.
6878 mono_class_get_field_token (MonoClassField *field)
6880 MonoClass *klass = field->parent;
6883 mono_class_setup_fields (klass);
6888 int first_field_idx = mono_class_get_first_field_idx (klass);
6889 int fcount = mono_class_get_field_count (klass);
6890 for (i = 0; i < fcount; ++i) {
6891 if (&klass->fields [i] == field) {
6892 int idx = first_field_idx + i + 1;
6894 if (klass->image->uncompressed_metadata)
6895 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6896 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6899 klass = klass->parent;
6902 g_assert_not_reached ();
6907 mono_field_get_index (MonoClassField *field)
6909 int index = field - field->parent->fields;
6910 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6916 * mono_class_get_field_default_value:
6918 * Return the default value of the field as a pointer into the metadata blob.
6921 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6924 guint32 constant_cols [MONO_CONSTANT_SIZE];
6926 MonoClass *klass = field->parent;
6927 MonoFieldDefaultValue *def_values;
6929 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6931 def_values = mono_class_get_field_def_values (klass);
6933 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6935 mono_class_set_field_def_values (klass, def_values);
6938 field_index = mono_field_get_index (field);
6940 if (!def_values [field_index].data) {
6941 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6945 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6947 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6948 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6949 mono_memory_barrier ();
6950 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6953 *def_type = def_values [field_index].def_type;
6954 return def_values [field_index].data;
6958 mono_property_get_index (MonoProperty *prop)
6960 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6961 int index = prop - info->properties;
6963 g_assert (index >= 0 && index < info->count);
6969 * mono_class_get_property_default_value:
6971 * Return the default value of the field as a pointer into the metadata blob.
6974 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6977 guint32 constant_cols [MONO_CONSTANT_SIZE];
6978 MonoClass *klass = property->parent;
6980 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6982 * We don't cache here because it is not used by C# so it's quite rare, but
6983 * we still do the lookup in klass->ext because that is where the data
6984 * is stored for dynamic assemblies.
6987 if (image_is_dynamic (klass->image)) {
6988 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
6989 int prop_index = mono_property_get_index (property);
6990 if (info->def_values && info->def_values [prop_index].data) {
6991 *def_type = info->def_values [prop_index].def_type;
6992 return info->def_values [prop_index].data;
6996 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7000 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7001 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7002 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7006 * mono_class_get_event_token:
7009 mono_class_get_event_token (MonoEvent *event)
7011 MonoClass *klass = event->parent;
7015 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7017 for (i = 0; i < info->count; ++i) {
7018 if (&info->events [i] == event)
7019 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7022 klass = klass->parent;
7025 g_assert_not_reached ();
7030 * mono_class_get_property_from_name:
7031 * \param klass a class
7032 * \param name name of the property to lookup in the specified class
7034 * Use this method to lookup a property in a class
7035 * \returns the \c MonoProperty with the given name, or NULL if the property
7036 * does not exist on the \p klass.
7039 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7043 gpointer iter = NULL;
7044 while ((p = mono_class_get_properties (klass, &iter))) {
7045 if (! strcmp (name, p->name))
7048 klass = klass->parent;
7054 * mono_class_get_property_token:
7055 * \param prop MonoProperty to query
7057 * \returns The ECMA token for the specified property.
7060 mono_class_get_property_token (MonoProperty *prop)
7062 MonoClass *klass = prop->parent;
7066 gpointer iter = NULL;
7067 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7068 while ((p = mono_class_get_properties (klass, &iter))) {
7069 if (&info->properties [i] == prop)
7070 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7074 klass = klass->parent;
7077 g_assert_not_reached ();
7082 * mono_class_name_from_token:
7085 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7087 const char *name, *nspace;
7088 if (image_is_dynamic (image))
7089 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7091 switch (type_token & 0xff000000){
7092 case MONO_TOKEN_TYPE_DEF: {
7093 guint32 cols [MONO_TYPEDEF_SIZE];
7094 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7095 guint tidx = mono_metadata_token_index (type_token);
7097 if (tidx > tt->rows)
7098 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7100 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7101 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7102 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7103 if (strlen (nspace) == 0)
7104 return g_strdup_printf ("%s", name);
7106 return g_strdup_printf ("%s.%s", nspace, name);
7109 case MONO_TOKEN_TYPE_REF: {
7111 guint32 cols [MONO_TYPEREF_SIZE];
7112 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7113 guint tidx = mono_metadata_token_index (type_token);
7116 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7118 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7119 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7120 mono_error_cleanup (&error);
7124 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7125 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7126 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7127 if (strlen (nspace) == 0)
7128 return g_strdup_printf ("%s", name);
7130 return g_strdup_printf ("%s.%s", nspace, name);
7133 case MONO_TOKEN_TYPE_SPEC:
7134 return g_strdup_printf ("Typespec 0x%08x", type_token);
7136 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7141 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7143 if (image_is_dynamic (image))
7144 return g_strdup_printf ("DynamicAssembly %s", image->name);
7146 switch (type_token & 0xff000000){
7147 case MONO_TOKEN_TYPE_DEF:
7148 if (image->assembly)
7149 return mono_stringify_assembly_name (&image->assembly->aname);
7150 else if (image->assembly_name)
7151 return g_strdup (image->assembly_name);
7152 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7153 case MONO_TOKEN_TYPE_REF: {
7155 MonoAssemblyName aname;
7156 guint32 cols [MONO_TYPEREF_SIZE];
7157 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7158 guint32 idx = mono_metadata_token_index (type_token);
7161 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7163 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7164 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7165 mono_error_cleanup (&error);
7168 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7170 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7171 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7172 case MONO_RESOLUTION_SCOPE_MODULE:
7174 return g_strdup ("");
7175 case MONO_RESOLUTION_SCOPE_MODULEREF:
7177 return g_strdup ("");
7178 case MONO_RESOLUTION_SCOPE_TYPEREF:
7180 return g_strdup ("");
7181 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7182 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7183 return mono_stringify_assembly_name (&aname);
7185 g_assert_not_reached ();
7189 case MONO_TOKEN_TYPE_SPEC:
7191 return g_strdup ("");
7193 g_assert_not_reached ();
7200 * mono_class_get_full:
7201 * \param image the image where the class resides
7202 * \param type_token the token for the class
7203 * \param context the generic context used to evaluate generic instantiations in
7204 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7205 * \returns The \c MonoClass that represents \p type_token in \p image
7208 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7212 klass = mono_class_get_checked (image, type_token, &error);
7214 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7215 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7217 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7223 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7228 klass = mono_class_get_checked (image, type_token, error);
7230 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7231 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7236 * mono_class_get_checked:
7237 * \param image the image where the class resides
7238 * \param type_token the token for the class
7239 * \param error error object to return any error
7241 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7244 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7246 MonoClass *klass = NULL;
7250 if (image_is_dynamic (image)) {
7251 int table = mono_metadata_token_table (type_token);
7253 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7254 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7257 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7261 switch (type_token & 0xff000000){
7262 case MONO_TOKEN_TYPE_DEF:
7263 klass = mono_class_create_from_typedef (image, type_token, error);
7265 case MONO_TOKEN_TYPE_REF:
7266 klass = mono_class_from_typeref_checked (image, type_token, error);
7268 case MONO_TOKEN_TYPE_SPEC:
7269 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7272 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7276 /* Generic case, should be avoided for when a better error is possible. */
7277 if (!klass && mono_error_ok (error)) {
7278 char *name = mono_class_name_from_token (image, type_token);
7279 char *assembly = mono_assembly_name_from_token (image, type_token);
7280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7288 * mono_type_get_checked:
7289 * \param image the image where the type resides
7290 * \param type_token the token for the type
7291 * \param context the generic context used to evaluate generic instantiations in
7292 * \param error Error handling context
7294 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7296 * \returns The MonoType that represents \p type_token in \p image
7299 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7301 MonoType *type = NULL;
7302 gboolean inflated = FALSE;
7306 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7307 if (image_is_dynamic (image)) {
7308 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7309 return_val_if_nok (error, NULL);
7310 return mono_class_get_type (klass);
7313 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7314 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7321 return mono_class_get_type (klass);
7324 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7331 MonoType *tmp = type;
7332 type = mono_class_get_type (mono_class_from_mono_type (type));
7333 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7334 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7335 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7337 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7339 if (type->type != tmp->type)
7342 mono_metadata_free_type (tmp);
7349 * \param image image where the class token will be looked up.
7350 * \param type_token a type token from the image
7351 * \returns the \c MonoClass with the given \p type_token on the \p image
7354 mono_class_get (MonoImage *image, guint32 type_token)
7356 return mono_class_get_full (image, type_token, NULL);
7360 * mono_image_init_name_cache:
7362 * Initializes the class name cache stored in image->name_cache.
7364 * LOCKING: Acquires the corresponding image lock.
7367 mono_image_init_name_cache (MonoImage *image)
7369 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7370 guint32 cols [MONO_TYPEDEF_SIZE];
7373 guint32 i, visib, nspace_index;
7374 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7376 if (image->name_cache)
7379 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7381 if (image_is_dynamic (image)) {
7382 mono_image_lock (image);
7383 if (image->name_cache) {
7384 /* Somebody initialized it before us */
7385 g_hash_table_destroy (the_name_cache);
7387 mono_atomic_store_release (&image->name_cache, the_name_cache);
7389 mono_image_unlock (image);
7393 /* Temporary hash table to avoid lookups in the nspace_table */
7394 name_cache2 = g_hash_table_new (NULL, NULL);
7396 for (i = 1; i <= t->rows; ++i) {
7397 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7398 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7400 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7401 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7403 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7405 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7406 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7408 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7409 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7410 if (!nspace_table) {
7411 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7412 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7413 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7416 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7419 /* Load type names from EXPORTEDTYPES table */
7421 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7422 guint32 cols [MONO_EXP_TYPE_SIZE];
7425 for (i = 0; i < t->rows; ++i) {
7426 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7428 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7429 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7433 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7434 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7436 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7437 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7438 if (!nspace_table) {
7439 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7440 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7441 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7444 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7448 g_hash_table_destroy (name_cache2);
7450 mono_image_lock (image);
7451 if (image->name_cache) {
7452 /* Somebody initialized it before us */
7453 g_hash_table_destroy (the_name_cache);
7455 mono_atomic_store_release (&image->name_cache, the_name_cache);
7457 mono_image_unlock (image);
7460 /*FIXME Only dynamic assemblies should allow this operation.*/
7462 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7463 const char *name, guint32 index)
7465 GHashTable *nspace_table;
7466 GHashTable *name_cache;
7469 mono_image_init_name_cache (image);
7470 mono_image_lock (image);
7472 name_cache = image->name_cache;
7473 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7474 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7475 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7478 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7479 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7481 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7483 mono_image_unlock (image);
7492 find_nocase (gpointer key, gpointer value, gpointer user_data)
7494 char *name = (char*)key;
7495 FindUserData *data = (FindUserData*)user_data;
7497 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7498 data->value = value;
7502 * mono_class_from_name_case:
7503 * \param image The MonoImage where the type is looked up in
7504 * \param name_space the type namespace
7505 * \param name the type short name.
7506 * \deprecated use the mono_class_from_name_case_checked variant instead.
7508 * Obtains a \c MonoClass with a given namespace and a given name which
7509 * is located in the given \c MonoImage. The namespace and name
7510 * lookups are case insensitive.
7513 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7516 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7517 mono_error_cleanup (&error);
7523 * mono_class_from_name_case_checked:
7524 * \param image The MonoImage where the type is looked up in
7525 * \param name_space the type namespace
7526 * \param name the type short name.
7529 * Obtains a MonoClass with a given namespace and a given name which
7530 * is located in the given MonoImage. The namespace and name
7531 * lookups are case insensitive.
7533 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7534 * was not found. The \p error object will contain information about the problem
7538 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7540 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7541 guint32 cols [MONO_TYPEDEF_SIZE];
7548 if (image_is_dynamic (image)) {
7550 FindUserData user_data;
7552 mono_image_init_name_cache (image);
7553 mono_image_lock (image);
7555 user_data.key = name_space;
7556 user_data.value = NULL;
7557 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7559 if (user_data.value) {
7560 GHashTable *nspace_table = (GHashTable*)user_data.value;
7562 user_data.key = name;
7563 user_data.value = NULL;
7565 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7567 if (user_data.value)
7568 token = GPOINTER_TO_UINT (user_data.value);
7571 mono_image_unlock (image);
7574 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7580 /* add a cache if needed */
7581 for (i = 1; i <= t->rows; ++i) {
7582 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7583 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7585 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7586 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7588 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7590 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7591 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7592 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7593 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7599 return_nested_in (MonoClass *klass, char *nested)
7602 char *s = strchr (nested, '/');
7603 gpointer iter = NULL;
7610 while ((found = mono_class_get_nested_types (klass, &iter))) {
7611 if (strcmp (found->name, nested) == 0) {
7613 return return_nested_in (found, s);
7621 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7623 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7624 MonoImage *file_image;
7631 * The EXPORTEDTYPES table only contains public types, so have to search the
7633 * Note: image->modules contains the contents of the MODULEREF table, while
7634 * the real module list is in the FILE table.
7636 for (i = 0; i < file_table->rows; i++) {
7637 guint32 cols [MONO_FILE_SIZE];
7638 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7639 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7642 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7644 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7645 if (klass || !is_ok (error))
7654 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7656 GHashTable *nspace_table;
7657 MonoImage *loaded_image;
7666 // Checking visited images avoids stack overflows when cyclic references exist.
7667 if (g_hash_table_lookup (visited_images, image))
7670 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7672 if ((nested = strchr (name, '/'))) {
7673 int pos = nested - name;
7674 int len = strlen (name);
7677 memcpy (buf, name, len + 1);
7679 nested = buf + pos + 1;
7683 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7684 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7685 gboolean res = get_class_from_name (image, name_space, name, &klass);
7688 klass = search_modules (image, name_space, name, error);
7693 return klass ? return_nested_in (klass, nested) : NULL;
7699 mono_image_init_name_cache (image);
7700 mono_image_lock (image);
7702 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7705 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7707 mono_image_unlock (image);
7709 if (!token && image_is_dynamic (image) && image->modules) {
7710 /* Search modules as well */
7711 for (i = 0; i < image->module_count; ++i) {
7712 MonoImage *module = image->modules [i];
7714 klass = mono_class_from_name_checked (module, name_space, name, error);
7715 if (klass || !is_ok (error))
7721 klass = search_modules (image, name_space, name, error);
7722 if (klass || !is_ok (error))
7727 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7728 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7729 guint32 cols [MONO_EXP_TYPE_SIZE];
7732 idx = mono_metadata_token_index (token);
7734 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7736 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7737 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7738 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7741 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7743 return klass ? return_nested_in (klass, nested) : NULL;
7745 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7746 guint32 assembly_idx;
7748 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7750 mono_assembly_load_reference (image, assembly_idx - 1);
7751 g_assert (image->references [assembly_idx - 1]);
7752 if (image->references [assembly_idx - 1] == (gpointer)-1)
7754 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7756 return klass ? return_nested_in (klass, nested) : NULL;
7759 g_assert_not_reached ();
7763 token = MONO_TOKEN_TYPE_DEF | token;
7765 klass = mono_class_get_checked (image, token, error);
7767 return return_nested_in (klass, nested);
7772 * mono_class_from_name_checked:
7773 * \param image The MonoImage where the type is looked up in
7774 * \param name_space the type namespace
7775 * \param name the type short name.
7777 * Obtains a MonoClass with a given namespace and a given name which
7778 * is located in the given MonoImage.
7780 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7781 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7784 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7787 GHashTable *visited_images;
7789 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7791 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7793 g_hash_table_destroy (visited_images);
7799 * mono_class_from_name:
7800 * \param image The \c MonoImage where the type is looked up in
7801 * \param name_space the type namespace
7802 * \param name the type short name.
7804 * Obtains a \c MonoClass with a given namespace and a given name which
7805 * is located in the given \c MonoImage.
7807 * To reference nested classes, use the "/" character as a separator.
7808 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7809 * inside \c Foo, like this: "class Foo { class Bar {} }".
7812 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7817 klass = mono_class_from_name_checked (image, name_space, name, &error);
7818 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7824 * mono_class_load_from_name:
7825 * \param image The MonoImage where the type is looked up in
7826 * \param name_space the type namespace
7827 * \param name the type short name.
7829 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7830 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7831 * If they are missing. Thing of System.Object or System.String.
7834 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7839 klass = mono_class_from_name_checked (image, name_space, name, &error);
7841 g_error ("Runtime critical type %s.%s not found", name_space, name);
7842 if (!mono_error_ok (&error))
7843 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7848 * mono_class_try_load_from_name:
7849 * \param image The MonoImage where the type is looked up in
7850 * \param name_space the type namespace
7851 * \param name the type short name.
7853 * This function tries to load a type, returning the class was found or NULL otherwise.
7854 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7856 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7857 * a type that we would otherwise assume to be available but was not due some error.
7861 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7866 klass = mono_class_from_name_checked (image, name_space, name, &error);
7867 if (!mono_error_ok (&error))
7868 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7874 * mono_class_is_subclass_of:
7875 * \param klass class to probe if it is a subclass of another one
7876 * \param klassc the class we suspect is the base class
7877 * \param check_interfaces whether we should perform interface checks
7879 * This method determines whether \p klass is a subclass of \p klassc.
7881 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7882 * this method return TRUE if the \p klass implements the interface or
7883 * if \p klass is an interface, if one of its base classes is \p klass.
7885 * If \p check_interfaces is false, then if \p klass is not an interface,
7886 * it returns TRUE if the \p klass is a subclass of \p klassc.
7888 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7893 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7894 gboolean check_interfaces)
7896 /* FIXME test for interfaces with variant generic arguments */
7897 mono_class_init (klass);
7898 mono_class_init (klassc);
7900 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7901 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7903 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7906 for (i = 0; i < klass->interface_count; i ++) {
7907 MonoClass *ic = klass->interfaces [i];
7912 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7917 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7920 if (klassc == mono_defaults.object_class)
7927 mono_type_is_generic_argument (MonoType *type)
7929 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7933 mono_class_has_variant_generic_params (MonoClass *klass)
7936 MonoGenericContainer *container;
7938 if (!mono_class_is_ginst (klass))
7941 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7943 for (i = 0; i < container->type_argc; ++i)
7944 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7951 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7953 if (target == candidate)
7956 if (check_for_reference_conv &&
7957 mono_type_is_generic_argument (&target->byval_arg) &&
7958 mono_type_is_generic_argument (&candidate->byval_arg)) {
7959 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7960 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7962 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7965 if (!mono_class_is_assignable_from (target, candidate))
7971 * @container the generic container from the GTD
7972 * @klass: the class to be assigned to
7973 * @oklass: the source class
7975 * Both @klass and @oklass must be instances of the same generic interface.
7977 * Returns: TRUE if @klass can be assigned to a @klass variable
7980 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7983 MonoType **klass_argv, **oklass_argv;
7984 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7985 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
7987 if (klass == oklass)
7990 /*Viable candidates are instances of the same generic interface*/
7991 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7994 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
7995 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
7997 for (j = 0; j < container->type_argc; ++j) {
7998 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7999 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8001 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8005 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8006 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8008 if (param1_class != param2_class) {
8009 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8010 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8012 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8013 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8023 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8025 MonoGenericParam *gparam, *ogparam;
8026 MonoGenericParamInfo *tinfo, *cinfo;
8027 MonoClass **candidate_class;
8028 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8031 if (target == candidate)
8033 if (target->byval_arg.type != candidate->byval_arg.type)
8036 gparam = target->byval_arg.data.generic_param;
8037 ogparam = candidate->byval_arg.data.generic_param;
8038 tinfo = mono_generic_param_info (gparam);
8039 cinfo = mono_generic_param_info (ogparam);
8041 class_constraint_satisfied = FALSE;
8042 valuetype_constraint_satisfied = FALSE;
8044 /*candidate must have a super set of target's special constraints*/
8045 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8046 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8048 if (cinfo->constraints) {
8049 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8050 MonoClass *cc = *candidate_class;
8052 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8053 class_constraint_satisfied = TRUE;
8054 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8055 valuetype_constraint_satisfied = TRUE;
8058 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8059 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8061 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8063 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8065 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8066 valuetype_constraint_satisfied)) {
8071 /*candidate type constraints must be a superset of target's*/
8072 if (tinfo->constraints) {
8073 MonoClass **target_class;
8074 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8075 MonoClass *tc = *target_class;
8078 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8079 * check it's constraints since it satisfy the constraint by itself.
8081 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8084 if (!cinfo->constraints)
8087 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8088 MonoClass *cc = *candidate_class;
8090 if (mono_class_is_assignable_from (tc, cc))
8094 * This happens when we have the following:
8096 * Bar<K> where K : IFace
8097 * Foo<T, U> where T : U where U : IFace
8099 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8102 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8103 if (mono_gparam_is_assignable_from (target, cc))
8107 if (!*candidate_class)
8112 /*candidate itself must have a constraint that satisfy target*/
8113 if (cinfo->constraints) {
8114 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8115 MonoClass *cc = *candidate_class;
8116 if (mono_class_is_assignable_from (target, cc))
8124 * mono_class_is_assignable_from:
8125 * \param klass the class to be assigned to
8126 * \param oklass the source class
8128 * \returns TRUE if an instance of class \p oklass can be assigned to an
8129 * instance of class \p klass
8132 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8135 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8137 mono_class_init (klass);
8139 if (!oklass->inited)
8140 mono_class_init (oklass);
8142 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8145 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8146 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8148 return mono_gparam_is_assignable_from (klass, oklass);
8151 if (MONO_CLASS_IS_INTERFACE (klass)) {
8152 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8153 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8154 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8158 for (i = 0; constraints [i]; ++i) {
8159 if (mono_class_is_assignable_from (klass, constraints [i]))
8167 /* interface_offsets might not be set for dynamic classes */
8168 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8170 * oklass might be a generic type parameter but they have
8171 * interface_offsets set.
8173 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8174 if (!is_ok (&error)) {
8175 mono_error_cleanup (&error);
8180 if (!oklass->interface_bitmap)
8181 /* Happens with generic instances of not-yet created dynamic types */
8183 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8186 if (klass->is_array_special_interface && oklass->rank == 1) {
8187 //XXX we could offset this by having the cast target computed at JIT time
8188 //XXX we could go even further and emit a wrapper that would do the extra type check
8189 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8190 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8192 // 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
8193 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8194 if (iface_klass->valuetype)
8195 iface_klass = iface_klass->cast_class;
8197 //array covariant casts only operates on scalar to scalar
8198 //This is so int[] can't be casted to IComparable<int>[]
8199 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8203 if (mono_class_has_variant_generic_params (klass)) {
8205 mono_class_setup_interfaces (oklass, &error);
8206 if (!mono_error_ok (&error)) {
8207 mono_error_cleanup (&error);
8211 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8212 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8213 MonoClass *iface = oklass->interfaces_packed [i];
8215 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8220 } else if (klass->delegate) {
8221 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8223 }else if (klass->rank) {
8224 MonoClass *eclass, *eoclass;
8226 if (oklass->rank != klass->rank)
8229 /* vectors vs. one dimensional arrays */
8230 if (oklass->byval_arg.type != klass->byval_arg.type)
8233 eclass = klass->cast_class;
8234 eoclass = oklass->cast_class;
8237 * a is b does not imply a[] is b[] when a is a valuetype, and
8238 * b is a reference type.
8241 if (eoclass->valuetype) {
8242 if ((eclass == mono_defaults.enum_class) ||
8243 (eclass == mono_defaults.enum_class->parent) ||
8244 (eclass == mono_defaults.object_class))
8248 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8249 } else if (mono_class_is_nullable (klass)) {
8250 if (mono_class_is_nullable (oklass))
8251 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8253 return mono_class_is_assignable_from (klass->cast_class, oklass);
8254 } else if (klass == mono_defaults.object_class)
8257 return mono_class_has_parent (oklass, klass);
8260 /*Check if @oklass is variant compatible with @klass.*/
8262 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8265 MonoType **klass_argv, **oklass_argv;
8266 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8267 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8269 /*Viable candidates are instances of the same generic interface*/
8270 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8273 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8274 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8276 for (j = 0; j < container->type_argc; ++j) {
8277 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8278 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8280 if (param1_class->valuetype != param2_class->valuetype)
8284 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8285 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8287 if (param1_class != param2_class) {
8288 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8289 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8291 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8292 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8300 /*Check if @candidate implements the interface @target*/
8302 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8306 gboolean is_variant = mono_class_has_variant_generic_params (target);
8308 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8309 if (mono_class_is_variant_compatible_slow (target, candidate))
8314 if (candidate == target)
8317 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8318 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8319 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8321 if (tb && tb->interfaces) {
8322 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8323 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8324 MonoClass *iface_class;
8326 /* we can't realize the type here since it can do pretty much anything. */
8329 iface_class = mono_class_from_mono_type (iface->type);
8330 if (iface_class == target)
8332 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8334 if (mono_class_implement_interface_slow (target, iface_class))
8339 /*setup_interfaces don't mono_class_init anything*/
8340 /*FIXME this doesn't handle primitive type arrays.
8341 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8342 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8344 mono_class_setup_interfaces (candidate, &error);
8345 if (!mono_error_ok (&error)) {
8346 mono_error_cleanup (&error);
8350 for (i = 0; i < candidate->interface_count; ++i) {
8351 if (candidate->interfaces [i] == target)
8354 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8357 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8361 candidate = candidate->parent;
8362 } while (candidate);
8368 * Check if @oklass can be assigned to @klass.
8369 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8372 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8374 if (candidate == target)
8376 if (target == mono_defaults.object_class)
8379 if (mono_class_has_parent (candidate, target))
8382 /*If target is not an interface there is no need to check them.*/
8383 if (MONO_CLASS_IS_INTERFACE (target))
8384 return mono_class_implement_interface_slow (target, candidate);
8386 if (target->delegate && mono_class_has_variant_generic_params (target))
8387 return mono_class_is_variant_compatible (target, candidate, FALSE);
8390 MonoClass *eclass, *eoclass;
8392 if (target->rank != candidate->rank)
8395 /* vectors vs. one dimensional arrays */
8396 if (target->byval_arg.type != candidate->byval_arg.type)
8399 eclass = target->cast_class;
8400 eoclass = candidate->cast_class;
8403 * a is b does not imply a[] is b[] when a is a valuetype, and
8404 * b is a reference type.
8407 if (eoclass->valuetype) {
8408 if ((eclass == mono_defaults.enum_class) ||
8409 (eclass == mono_defaults.enum_class->parent) ||
8410 (eclass == mono_defaults.object_class))
8414 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8416 /*FIXME properly handle nullables */
8417 /*FIXME properly handle (M)VAR */
8422 * mono_class_get_cctor:
8423 * \param klass A MonoClass pointer
8425 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8428 mono_class_get_cctor (MonoClass *klass)
8430 MonoCachedClassInfo cached_info;
8432 if (image_is_dynamic (klass->image)) {
8434 * has_cctor is not set for these classes because mono_class_init () is
8437 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8440 mono_class_init (klass);
8442 if (!klass->has_cctor)
8445 if (mono_class_is_ginst (klass) && !klass->methods)
8446 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8448 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8450 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8451 if (!mono_error_ok (&error))
8452 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8456 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8460 * mono_class_get_finalizer:
8461 * \param klass: The MonoClass pointer
8463 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8466 mono_class_get_finalizer (MonoClass *klass)
8468 MonoCachedClassInfo cached_info;
8471 mono_class_init (klass);
8472 if (!mono_class_has_finalizer (klass))
8475 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8477 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8478 if (!mono_error_ok (&error))
8479 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8482 mono_class_setup_vtable (klass);
8483 return klass->vtable [finalize_slot];
8488 * mono_class_needs_cctor_run:
8489 * \param klass the MonoClass pointer
8490 * \param caller a MonoMethod describing the caller
8492 * Determines whenever the class has a static constructor and whenever it
8493 * needs to be called when executing CALLER.
8496 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8500 method = mono_class_get_cctor (klass);
8502 return (method == caller) ? FALSE : TRUE;
8508 * mono_class_array_element_size:
8511 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8514 mono_class_array_element_size (MonoClass *klass)
8516 MonoType *type = &klass->byval_arg;
8519 switch (type->type) {
8522 case MONO_TYPE_BOOLEAN:
8526 case MONO_TYPE_CHAR:
8535 case MONO_TYPE_CLASS:
8536 case MONO_TYPE_STRING:
8537 case MONO_TYPE_OBJECT:
8538 case MONO_TYPE_SZARRAY:
8539 case MONO_TYPE_ARRAY:
8540 return sizeof (gpointer);
8545 case MONO_TYPE_VALUETYPE:
8546 if (type->data.klass->enumtype) {
8547 type = mono_class_enum_basetype (type->data.klass);
8548 klass = klass->element_class;
8551 return mono_class_instance_size (klass) - sizeof (MonoObject);
8552 case MONO_TYPE_GENERICINST:
8553 type = &type->data.generic_class->container_class->byval_arg;
8556 case MONO_TYPE_MVAR: {
8559 return mono_type_size (type, &align);
8561 case MONO_TYPE_VOID:
8565 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8571 * mono_array_element_size:
8572 * \param ac pointer to a \c MonoArrayClass
8574 * \returns The size of single array element.
8577 mono_array_element_size (MonoClass *ac)
8579 g_assert (ac->rank);
8580 return ac->sizes.element_size;
8584 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8585 MonoGenericContext *context)
8588 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8589 g_assert (mono_error_ok (&error));
8594 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8595 MonoGenericContext *context, MonoError *error)
8599 if (image_is_dynamic (image)) {
8600 MonoClass *tmp_handle_class;
8601 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8603 mono_error_assert_ok (error);
8604 g_assert (tmp_handle_class);
8606 *handle_class = tmp_handle_class;
8608 if (tmp_handle_class == mono_defaults.typehandle_class)
8609 return &((MonoClass*)obj)->byval_arg;
8614 switch (token & 0xff000000) {
8615 case MONO_TOKEN_TYPE_DEF:
8616 case MONO_TOKEN_TYPE_REF:
8617 case MONO_TOKEN_TYPE_SPEC: {
8620 *handle_class = mono_defaults.typehandle_class;
8621 type = mono_type_get_checked (image, token, context, error);
8625 mono_class_init (mono_class_from_mono_type (type));
8626 /* We return a MonoType* as handle */
8629 case MONO_TOKEN_FIELD_DEF: {
8631 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8633 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8637 *handle_class = mono_defaults.fieldhandle_class;
8638 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8642 mono_class_init (klass);
8643 return mono_class_get_field (klass, token);
8645 case MONO_TOKEN_METHOD_DEF:
8646 case MONO_TOKEN_METHOD_SPEC: {
8648 meth = mono_get_method_checked (image, token, NULL, context, error);
8650 *handle_class = mono_defaults.methodhandle_class;
8656 case MONO_TOKEN_MEMBER_REF: {
8657 guint32 cols [MONO_MEMBERREF_SIZE];
8659 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8660 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8661 mono_metadata_decode_blob_size (sig, &sig);
8662 if (*sig == 0x6) { /* it's a field */
8664 MonoClassField *field;
8665 field = mono_field_from_token_checked (image, token, &klass, context, error);
8667 *handle_class = mono_defaults.fieldhandle_class;
8671 meth = mono_get_method_checked (image, token, NULL, context, error);
8673 *handle_class = mono_defaults.methodhandle_class;
8678 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8684 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8686 MonoClass *handle_class;
8688 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8692 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8694 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8697 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8700 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8702 get_cached_class_info = func;
8706 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8708 if (!get_cached_class_info)
8711 return get_cached_class_info (klass, res);
8715 mono_install_get_class_from_name (MonoGetClassFromName func)
8717 get_class_from_name = func;
8721 * mono_class_get_image:
8723 * Use this method to get the \c MonoImage* where this class came from.
8725 * \returns The image where this class is defined.
8728 mono_class_get_image (MonoClass *klass)
8730 return klass->image;
8734 * mono_class_get_element_class:
8735 * \param klass the \c MonoClass to act on
8737 * Use this function to get the element class of an array.
8739 * \returns The element class of an array.
8742 mono_class_get_element_class (MonoClass *klass)
8744 return klass->element_class;
8748 * mono_class_is_valuetype:
8749 * \param klass the \c MonoClass to act on
8751 * Use this method to determine if the provided \c MonoClass* represents a value type,
8752 * or a reference type.
8754 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8757 mono_class_is_valuetype (MonoClass *klass)
8759 return klass->valuetype;
8763 * mono_class_is_enum:
8764 * \param klass the \c MonoClass to act on
8766 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8768 * \returns TRUE if the \c MonoClass represents an enumeration.
8771 mono_class_is_enum (MonoClass *klass)
8773 return klass->enumtype;
8777 * mono_class_enum_basetype:
8778 * \param klass the \c MonoClass to act on
8780 * Use this function to get the underlying type for an enumeration value.
8782 * \returns The underlying type representation for an enumeration.
8785 mono_class_enum_basetype (MonoClass *klass)
8787 if (klass->element_class == klass)
8788 /* SRE or broken types */
8791 return &klass->element_class->byval_arg;
8795 * mono_class_get_parent
8796 * \param klass the \c MonoClass to act on
8798 * \returns The parent class for this class.
8801 mono_class_get_parent (MonoClass *klass)
8803 return klass->parent;
8807 * mono_class_get_nesting_type:
8808 * \param klass the \c MonoClass to act on
8810 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8812 * If the return is NULL, this indicates that this class is not nested.
8814 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8817 mono_class_get_nesting_type (MonoClass *klass)
8819 return klass->nested_in;
8823 * mono_class_get_rank:
8824 * \param klass the MonoClass to act on
8826 * \returns The rank for the array (the number of dimensions).
8829 mono_class_get_rank (MonoClass *klass)
8835 * mono_class_get_name
8836 * \param klass the \c MonoClass to act on
8838 * \returns The name of the class.
8841 mono_class_get_name (MonoClass *klass)
8847 * mono_class_get_namespace:
8848 * \param klass the \c MonoClass to act on
8850 * \returns The namespace of the class.
8853 mono_class_get_namespace (MonoClass *klass)
8855 return klass->name_space;
8859 * mono_class_get_type:
8860 * \param klass the \c MonoClass to act on
8862 * This method returns the internal \c MonoType representation for the class.
8864 * \returns The \c MonoType from the class.
8867 mono_class_get_type (MonoClass *klass)
8869 return &klass->byval_arg;
8873 * mono_class_get_type_token:
8874 * \param klass the \c MonoClass to act on
8876 * This method returns type token for the class.
8878 * \returns The type token for the class.
8881 mono_class_get_type_token (MonoClass *klass)
8883 return klass->type_token;
8887 * mono_class_get_byref_type:
8888 * \param klass the \c MonoClass to act on
8893 mono_class_get_byref_type (MonoClass *klass)
8895 return &klass->this_arg;
8899 * mono_class_num_fields:
8900 * \param klass the \c MonoClass to act on
8902 * \returns The number of static and instance fields in the class.
8905 mono_class_num_fields (MonoClass *klass)
8907 return mono_class_get_field_count (klass);
8911 * mono_class_num_methods:
8912 * \param klass the \c MonoClass to act on
8914 * \returns The number of methods in the class.
8917 mono_class_num_methods (MonoClass *klass)
8919 return mono_class_get_method_count (klass);
8923 * mono_class_num_properties
8924 * \param klass the \c MonoClass to act on
8926 * \returns The number of properties in the class.
8929 mono_class_num_properties (MonoClass *klass)
8931 mono_class_setup_properties (klass);
8933 return mono_class_get_property_info (klass)->count;
8937 * mono_class_num_events:
8938 * \param klass the \c MonoClass to act on
8940 * \returns The number of events in the class.
8943 mono_class_num_events (MonoClass *klass)
8945 mono_class_setup_events (klass);
8947 return mono_class_get_event_info (klass)->count;
8951 * mono_class_get_fields:
8952 * \param klass the \c MonoClass to act on
8954 * This routine is an iterator routine for retrieving the fields in a class.
8956 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
8957 * iterate over all of the elements. When no more values are
8958 * available, the return value is NULL.
8960 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
8963 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8965 MonoClassField* field;
8969 mono_class_setup_fields (klass);
8970 if (mono_class_has_failure (klass))
8972 /* start from the first */
8973 if (mono_class_get_field_count (klass)) {
8974 *iter = &klass->fields [0];
8975 return &klass->fields [0];
8981 field = (MonoClassField *)*iter;
8983 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
8991 * mono_class_get_methods:
8992 * \param klass the \c MonoClass to act on
8994 * This routine is an iterator routine for retrieving the fields in a class.
8996 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
8997 * iterate over all of the elements. When no more values are
8998 * available, the return value is NULL.
9000 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9003 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9005 MonoMethod** method;
9009 mono_class_setup_methods (klass);
9012 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9013 * FIXME we should better report this error to the caller
9015 if (!klass->methods)
9017 /* start from the first */
9018 if (mono_class_get_method_count (klass)) {
9019 *iter = &klass->methods [0];
9020 return klass->methods [0];
9026 method = (MonoMethod **)*iter;
9028 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9036 * mono_class_get_virtual_methods:
9038 * Iterate over the virtual methods of KLASS.
9040 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9043 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9045 MonoMethod** method;
9048 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9050 mono_class_setup_methods (klass);
9052 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9053 * FIXME we should better report this error to the caller
9055 if (!klass->methods)
9057 /* start from the first */
9058 method = &klass->methods [0];
9060 method = (MonoMethod **)*iter;
9063 int mcount = mono_class_get_method_count (klass);
9064 while (method < &klass->methods [mcount]) {
9065 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9069 if (method < &klass->methods [mcount]) {
9076 /* Search directly in metadata to avoid calling setup_methods () */
9077 MonoMethod *res = NULL;
9083 start_index = GPOINTER_TO_UINT (*iter);
9086 int first_idx = mono_class_get_first_method_idx (klass);
9087 int mcount = mono_class_get_method_count (klass);
9088 for (i = start_index; i < mcount; ++i) {
9091 /* first_idx points into the methodptr table */
9092 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9094 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9100 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9101 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9103 /* Add 1 here so the if (*iter) check fails */
9104 *iter = GUINT_TO_POINTER (i + 1);
9113 * mono_class_get_properties:
9114 * \param klass the \c MonoClass to act on
9116 * This routine is an iterator routine for retrieving the properties in a class.
9118 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9119 * iterate over all of the elements. When no more values are
9120 * available, the return value is NULL.
9122 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9125 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9127 MonoProperty* property;
9131 mono_class_setup_properties (klass);
9132 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9133 /* start from the first */
9135 *iter = &info->properties [0];
9136 return (MonoProperty *)*iter;
9142 property = (MonoProperty *)*iter;
9144 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9145 if (property < &info->properties [info->count]) {
9147 return (MonoProperty *)*iter;
9153 * mono_class_get_events:
9154 * \param klass the \c MonoClass to act on
9156 * This routine is an iterator routine for retrieving the properties in a class.
9158 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9159 * iterate over all of the elements. When no more values are
9160 * available, the return value is NULL.
9162 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9165 mono_class_get_events (MonoClass* klass, gpointer *iter)
9171 mono_class_setup_events (klass);
9172 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9173 /* start from the first */
9175 *iter = &info->events [0];
9176 return (MonoEvent *)*iter;
9182 event = (MonoEvent *)*iter;
9184 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9185 if (event < &info->events [info->count]) {
9187 return (MonoEvent *)*iter;
9193 * mono_class_get_interfaces
9194 * \param klass the \c MonoClass to act on
9196 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9198 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9199 * iterate over all of the elements. When no more values are
9200 * available, the return value is NULL.
9202 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9205 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9213 mono_class_init (klass);
9214 if (!klass->interfaces_inited) {
9215 mono_class_setup_interfaces (klass, &error);
9216 if (!mono_error_ok (&error)) {
9217 mono_error_cleanup (&error);
9221 /* start from the first */
9222 if (klass->interface_count) {
9223 *iter = &klass->interfaces [0];
9224 return klass->interfaces [0];
9230 iface = (MonoClass **)*iter;
9232 if (iface < &klass->interfaces [klass->interface_count]) {
9240 setup_nested_types (MonoClass *klass)
9243 GList *classes, *nested_classes, *l;
9246 if (klass->nested_classes_inited)
9249 if (!klass->type_token) {
9250 mono_loader_lock ();
9251 klass->nested_classes_inited = TRUE;
9252 mono_loader_unlock ();
9256 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9260 guint32 cols [MONO_NESTED_CLASS_SIZE];
9261 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9262 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9263 if (!mono_error_ok (&error)) {
9264 /*FIXME don't swallow the error message*/
9265 mono_error_cleanup (&error);
9267 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9271 classes = g_list_prepend (classes, nclass);
9273 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9276 nested_classes = NULL;
9277 for (l = classes; l; l = l->next)
9278 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9279 g_list_free (classes);
9281 mono_loader_lock ();
9282 if (!klass->nested_classes_inited) {
9283 mono_class_set_nested_classes_property (klass, nested_classes);
9284 mono_memory_barrier ();
9285 klass->nested_classes_inited = TRUE;
9287 mono_loader_unlock ();
9291 * mono_class_get_nested_types
9292 * \param klass the \c MonoClass to act on
9294 * This routine is an iterator routine for retrieving the nested types of a class.
9295 * This works only if \p klass is non-generic, or a generic type definition.
9297 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9298 * iterate over all of the elements. When no more values are
9299 * available, the return value is NULL.
9301 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9304 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9310 if (!klass->nested_classes_inited)
9311 setup_nested_types (klass);
9314 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9315 /* start from the first */
9316 if (nested_classes) {
9317 *iter = nested_classes;
9318 return (MonoClass *)nested_classes->data;
9320 /* no nested types */
9324 item = (GList *)*iter;
9328 return (MonoClass *)item->data;
9335 * mono_class_is_delegate
9336 * \param klass the \c MonoClass to act on
9338 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9341 mono_class_is_delegate (MonoClass *klass)
9343 return klass->delegate;
9347 * mono_class_implements_interface
9348 * \param klass The MonoClass to act on
9349 * \param interface The interface to check if \p klass implements.
9351 * \returns TRUE if \p klass implements \p interface.
9354 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9356 return mono_class_is_assignable_from (iface, klass);
9360 * mono_field_get_name:
9361 * \param field the \c MonoClassField to act on
9363 * \returns The name of the field.
9366 mono_field_get_name (MonoClassField *field)
9372 * mono_field_get_type:
9373 * \param field the \c MonoClassField to act on
9375 * \returns \c MonoType of the field.
9378 mono_field_get_type (MonoClassField *field)
9381 MonoType *type = mono_field_get_type_checked (field, &error);
9382 if (!mono_error_ok (&error)) {
9383 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9384 mono_error_cleanup (&error);
9391 * mono_field_get_type_checked:
9392 * \param field the \c MonoClassField to act on
9393 * \param error used to return any error found while retrieving \p field type
9395 * \returns \c MonoType of the field.
9398 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9402 mono_field_resolve_type (field, error);
9407 * mono_field_get_parent:
9408 * \param field the \c MonoClassField to act on
9410 * \returns \c MonoClass where the field was defined.
9413 mono_field_get_parent (MonoClassField *field)
9415 return field->parent;
9419 * mono_field_get_flags;
9420 * @field: the MonoClassField to act on
9422 * The metadata flags for a field are encoded using the
9423 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9425 * Returns: The flags for the field.
9428 mono_field_get_flags (MonoClassField *field)
9431 return mono_field_resolve_flags (field);
9432 return field->type->attrs;
9436 * mono_field_get_offset:
9437 * \param field the \c MonoClassField to act on
9439 * \returns The field offset.
9442 mono_field_get_offset (MonoClassField *field)
9444 return field->offset;
9448 mono_field_get_rva (MonoClassField *field)
9452 MonoClass *klass = field->parent;
9453 MonoFieldDefaultValue *def_values;
9455 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9457 def_values = mono_class_get_field_def_values (klass);
9459 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9461 mono_class_set_field_def_values (klass, def_values);
9464 field_index = mono_field_get_index (field);
9466 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9467 int first_field_idx = mono_class_get_first_field_idx (klass);
9468 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9470 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9471 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9474 return def_values [field_index].data;
9478 * mono_field_get_data:
9479 * \param field the \c MonoClassField to act on
9481 * \returns A pointer to the metadata constant value or to the field
9482 * data if it has an RVA flag.
9485 mono_field_get_data (MonoClassField *field)
9487 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9488 MonoTypeEnum def_type;
9490 return mono_class_get_field_default_value (field, &def_type);
9491 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9492 return mono_field_get_rva (field);
9499 * mono_property_get_name:
9500 * @prop: the MonoProperty to act on
9502 * Returns: The name of the property
9505 mono_property_get_name (MonoProperty *prop)
9511 * mono_property_get_set_method
9512 * \param prop the \c MonoProperty to act on.
9514 * \returns The setter method of the property (A MonoMethod)
9517 mono_property_get_set_method (MonoProperty *prop)
9523 * mono_property_get_get_method
9524 * \param prop the MonoProperty to act on.
9526 * \returns The setter method of the property (A \c MonoMethod)
9529 mono_property_get_get_method (MonoProperty *prop)
9535 * mono_property_get_parent:
9536 * \param prop the MonoProperty to act on.
9538 * \returns The \c MonoClass where the property was defined.
9541 mono_property_get_parent (MonoProperty *prop)
9543 return prop->parent;
9547 * mono_property_get_flags:
9548 * \param prop the \c MonoProperty to act on.
9550 * The metadata flags for a property are encoded using the
9551 * \c PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9553 * \returns The flags for the property.
9556 mono_property_get_flags (MonoProperty *prop)
9562 * mono_event_get_name:
9563 * \param event the MonoEvent to act on
9565 * \returns The name of the event.
9568 mono_event_get_name (MonoEvent *event)
9574 * mono_event_get_add_method:
9575 * \param event The \c MonoEvent to act on.
9577 * \returns The \c add method for the event (a \c MonoMethod).
9580 mono_event_get_add_method (MonoEvent *event)
9586 * mono_event_get_remove_method:
9587 * \param event The \c MonoEvent to act on.
9589 * \returns The \c remove method for the event (a \c MonoMethod).
9592 mono_event_get_remove_method (MonoEvent *event)
9594 return event->remove;
9598 * mono_event_get_raise_method:
9599 * \param event The \c MonoEvent to act on.
9601 * \returns The \c raise method for the event (a \c MonoMethod).
9604 mono_event_get_raise_method (MonoEvent *event)
9606 return event->raise;
9610 * mono_event_get_parent:
9611 * \param event the MonoEvent to act on.
9612 * \returns The \c MonoClass where the event is defined.
9615 mono_event_get_parent (MonoEvent *event)
9617 return event->parent;
9621 * mono_event_get_flags
9622 * \param event the \c MonoEvent to act on.
9624 * The metadata flags for an event are encoded using the
9625 * \c EVENT_* constants. See the tabledefs.h file for details.
9627 * \returns The flags for the event.
9630 mono_event_get_flags (MonoEvent *event)
9632 return event->attrs;
9636 * mono_class_get_method_from_name:
9637 * \param klass where to look for the method
9638 * \param name name of the method
9639 * \param param_count number of parameters. -1 for any number.
9641 * Obtains a \c MonoMethod with a given name and number of parameters.
9642 * It only works if there are no multiple signatures for any given method name.
9645 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9647 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9651 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9653 MonoMethod *res = NULL;
9656 /* Search directly in the metadata to avoid calling setup_methods () */
9657 int first_idx = mono_class_get_first_method_idx (klass);
9658 int mcount = mono_class_get_method_count (klass);
9659 for (i = 0; i < mcount; ++i) {
9661 guint32 cols [MONO_METHOD_SIZE];
9663 MonoMethodSignature *sig;
9665 /* first_idx points into the methodptr table */
9666 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9668 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9669 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9671 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9674 if (param_count == -1) {
9678 sig = mono_method_signature_checked (method, &error);
9680 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9683 if (sig->param_count == param_count) {
9694 * mono_class_get_method_from_name_flags:
9695 * \param klass where to look for the method
9696 * \param name_space name of the method
9697 * \param param_count number of parameters. -1 for any number.
9698 * \param flags flags which must be set in the method
9700 * Obtains a \c MonoMethod with a given name and number of parameters.
9701 * It only works if there are no multiple signatures for any given method name.
9704 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9706 MonoMethod *res = NULL;
9709 mono_class_init (klass);
9711 if (mono_class_is_ginst (klass) && !klass->methods) {
9712 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9715 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9716 if (!mono_error_ok (&error))
9717 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9722 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9723 mono_class_setup_methods (klass);
9725 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9726 See mono/tests/array_load_exception.il
9727 FIXME we should better report this error to the caller
9729 if (!klass->methods)
9731 int mcount = mono_class_get_method_count (klass);
9732 for (i = 0; i < mcount; ++i) {
9733 MonoMethod *method = klass->methods [i];
9735 if (method->name[0] == name [0] &&
9736 !strcmp (name, method->name) &&
9737 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9738 ((method->flags & flags) == flags)) {
9745 res = find_method_in_metadata (klass, name, param_count, flags);
9752 * mono_class_set_failure:
9753 * \param klass class in which the failure was detected
9754 * \param ex_type the kind of exception/error to be thrown (later)
9755 * \param ex_data exception data (specific to each type of exception/error)
9757 * Keep a detected failure informations in the class for later processing.
9758 * Note that only the first failure is kept.
9760 * LOCKING: Acquires the loader lock.
9763 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9765 g_assert (boxed_error != NULL);
9767 if (mono_class_has_failure (klass))
9770 mono_loader_lock ();
9771 klass->has_failure = 1;
9772 mono_class_set_exception_data (klass, boxed_error);
9773 mono_loader_unlock ();
9779 mono_class_has_failure (const MonoClass *klass)
9781 g_assert (klass != NULL);
9782 return klass->has_failure != 0;
9787 * mono_class_set_type_load_failure:
9788 * \param klass class in which the failure was detected
9789 * \param fmt \c printf -style error message string.
9791 * Collect detected failure informaion in the class for later processing.
9792 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9793 * Note that only the first failure is kept.
9795 * LOCKING: Acquires the loader lock.
9797 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9800 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9802 MonoError prepare_error;
9805 if (mono_class_has_failure (klass))
9808 error_init (&prepare_error);
9810 va_start (args, fmt);
9811 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9814 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9815 mono_error_cleanup (&prepare_error);
9816 return mono_class_set_failure (klass, box);
9820 * mono_classes_init:
9822 * Initialize the resources used by this module.
9825 mono_classes_init (void)
9827 mono_os_mutex_init (&classes_mutex);
9829 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9830 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9832 mono_counters_register ("MonoClassDef count",
9833 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9834 mono_counters_register ("MonoClassGtd count",
9835 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9836 mono_counters_register ("MonoClassGenericInst count",
9837 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9838 mono_counters_register ("MonoClassGenericParam count",
9839 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9840 mono_counters_register ("MonoClassArray count",
9841 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9842 mono_counters_register ("MonoClassPointer count",
9843 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9844 mono_counters_register ("Inflated methods size",
9845 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9846 mono_counters_register ("Inflated classes size",
9847 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9848 mono_counters_register ("MonoClass size",
9849 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9853 * mono_classes_cleanup:
9855 * Free the resources used by this module.
9858 mono_classes_cleanup (void)
9860 mono_native_tls_free (setup_fields_tls_id);
9861 mono_native_tls_free (init_pending_tls_id);
9863 if (global_interface_bitset)
9864 mono_bitset_free (global_interface_bitset);
9865 global_interface_bitset = NULL;
9866 mono_os_mutex_destroy (&classes_mutex);
9870 * mono_class_get_exception_for_failure:
9871 * \param klass class in which the failure was detected
9873 * \returns a constructed MonoException than the caller can then throw
9874 * using mono_raise_exception - or NULL if no failure is present (or
9875 * doesn't result in an exception).
9878 mono_class_get_exception_for_failure (MonoClass *klass)
9880 if (!mono_class_has_failure (klass))
9882 MonoError unboxed_error;
9883 error_init (&unboxed_error);
9884 mono_error_set_for_class_failure (&unboxed_error, klass);
9885 return mono_error_convert_to_exception (&unboxed_error);
9889 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9891 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9892 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9894 if (outer_klass == inner_klass)
9896 inner_klass = inner_klass->nested_in;
9897 } while (inner_klass);
9902 mono_class_get_generic_type_definition (MonoClass *klass)
9904 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9905 return gklass ? gklass->container_class : klass;
9909 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9911 * Generic instantiations are ignored for all super types of @klass.
9913 * Visibility checks ignoring generic instantiations.
9916 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9919 klass = mono_class_get_generic_type_definition (klass);
9920 parent = mono_class_get_generic_type_definition (parent);
9921 mono_class_setup_supertypes (klass);
9923 for (i = 0; i < klass->idepth; ++i) {
9924 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9930 * Subtype can only access parent members with family protection if the site object
9931 * is subclass of Subtype. For example:
9932 * class A { protected int x; }
9934 * void valid_access () {
9938 * void invalid_access () {
9945 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9947 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9950 if (context_klass == NULL)
9952 /*if access_klass is not member_klass context_klass must be type compat*/
9953 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9959 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9962 if (accessing == accessed)
9964 if (!accessed || !accessing)
9967 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9968 * anywhere so untrusted friends are not safe to access platform's code internals */
9969 if (mono_security_core_clr_enabled ()) {
9970 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9974 mono_assembly_load_friends (accessed);
9975 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9976 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
9977 /* Be conservative with checks */
9980 if (strcmp (accessing->aname.name, friend_->name))
9982 if (friend_->public_key_token [0]) {
9983 if (!accessing->aname.public_key_token [0])
9985 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
9994 * If klass is a generic type or if it is derived from a generic type, return the
9995 * MonoClass of the generic definition
9996 * Returns NULL if not found
9999 get_generic_definition_class (MonoClass *klass)
10002 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10003 if (gklass && gklass->container_class)
10004 return gklass->container_class;
10005 klass = klass->parent;
10011 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10014 for (i = 0; i < ginst->type_argc; ++i) {
10015 MonoType *type = ginst->type_argv[i];
10016 switch (type->type) {
10017 case MONO_TYPE_SZARRAY:
10018 if (!can_access_type (access_klass, type->data.klass))
10021 case MONO_TYPE_ARRAY:
10022 if (!can_access_type (access_klass, type->data.array->eklass))
10025 case MONO_TYPE_PTR:
10026 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10029 case MONO_TYPE_CLASS:
10030 case MONO_TYPE_VALUETYPE:
10031 case MONO_TYPE_GENERICINST:
10032 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10042 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10046 if (access_klass == member_klass)
10049 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10052 if (access_klass->element_class && !access_klass->enumtype)
10053 access_klass = access_klass->element_class;
10055 if (member_klass->element_class && !member_klass->enumtype)
10056 member_klass = member_klass->element_class;
10058 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10060 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10063 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10066 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10069 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10072 /*Non nested type with nested visibility. We just fail it.*/
10073 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10076 switch (access_level) {
10077 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10078 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10080 case TYPE_ATTRIBUTE_PUBLIC:
10083 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10086 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10087 return is_nesting_type (member_klass, access_klass);
10089 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10090 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10092 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10093 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10095 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10096 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10097 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10099 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10100 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10101 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10106 /* FIXME: check visibility of type, too */
10108 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10110 MonoClass *member_generic_def;
10111 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10114 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10115 if (((access_gklass && access_gklass->container_class) ||
10116 mono_class_is_gtd (access_klass)) &&
10117 (member_generic_def = get_generic_definition_class (member_klass))) {
10118 MonoClass *access_container;
10120 if (mono_class_is_gtd (access_klass))
10121 access_container = access_klass;
10123 access_container = access_gklass->container_class;
10125 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10129 /* Partition I 8.5.3.2 */
10130 /* the access level values are the same for fields and methods */
10131 switch (access_level) {
10132 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10133 /* same compilation unit */
10134 return access_klass->image == member_klass->image;
10135 case FIELD_ATTRIBUTE_PRIVATE:
10136 return access_klass == member_klass;
10137 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10138 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10139 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10142 case FIELD_ATTRIBUTE_ASSEMBLY:
10143 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10144 case FIELD_ATTRIBUTE_FAMILY:
10145 if (is_valid_family_access (access_klass, member_klass, context_klass))
10148 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10149 if (is_valid_family_access (access_klass, member_klass, context_klass))
10151 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10152 case FIELD_ATTRIBUTE_PUBLIC:
10159 * mono_method_can_access_field:
10160 * \param method Method that will attempt to access the field
10161 * \param field the field to access
10163 * Used to determine if a method is allowed to access the specified field.
10165 * \returns TRUE if the given \p method is allowed to access the \p field while following
10166 * the accessibility rules of the CLI.
10169 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10171 /* FIXME: check all overlapping fields */
10172 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10174 MonoClass *nested = method->klass->nested_in;
10176 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10179 nested = nested->nested_in;
10186 * mono_method_can_access_method:
10187 * \param method Method that will attempt to access the other method
10188 * \param called the method that we want to probe for accessibility.
10190 * Used to determine if the \p method is allowed to access the specified \p called method.
10192 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10193 * the accessibility rules of the CLI.
10196 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10198 method = mono_method_get_method_definition (method);
10199 called = mono_method_get_method_definition (called);
10200 return mono_method_can_access_method_full (method, called, NULL);
10204 * mono_method_can_access_method_full:
10205 * @method: The caller method
10206 * @called: The called method
10207 * @context_klass: The static type on stack of the owner @called object used
10209 * This function must be used with instance calls, as they have more strict family accessibility.
10210 * It can be used with static methods, but context_klass should be NULL.
10212 * Returns: TRUE if caller have proper visibility and acessibility to @called
10215 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10217 /* Wrappers are except from access checks */
10218 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10221 MonoClass *access_class = method->klass;
10222 MonoClass *member_class = called->klass;
10223 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10225 MonoClass *nested = access_class->nested_in;
10227 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10230 nested = nested->nested_in;
10237 can = can_access_type (access_class, member_class);
10239 MonoClass *nested = access_class->nested_in;
10241 can = can_access_type (nested, member_class);
10244 nested = nested->nested_in;
10251 if (called->is_inflated) {
10252 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10253 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10262 * mono_method_can_access_field_full:
10263 * @method: The caller method
10264 * @field: The accessed field
10265 * @context_klass: The static type on stack of the owner @field object used
10267 * This function must be used with instance fields, as they have more strict family accessibility.
10268 * It can be used with static fields, but context_klass should be NULL.
10270 * Returns: TRUE if caller have proper visibility and acessibility to @field
10273 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10275 MonoClass *access_class = method->klass;
10276 MonoClass *member_class = field->parent;
10277 /* FIXME: check all overlapping fields */
10278 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10280 MonoClass *nested = access_class->nested_in;
10282 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_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;
10309 * mono_class_can_access_class:
10310 * @source_class: The source class
10311 * @target_class: The accessed class
10313 * This function returns is @target_class is visible to @source_class
10315 * Returns: TRUE if source have proper visibility and acessibility to target
10318 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10320 return can_access_type (source_class, target_class);
10324 * mono_type_is_valid_enum_basetype:
10325 * \param type The MonoType to check
10326 * \returns TRUE if the type can be used as the basetype of an enum
10328 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10329 switch (type->type) {
10332 case MONO_TYPE_BOOLEAN:
10335 case MONO_TYPE_CHAR:
10349 * mono_class_is_valid_enum:
10350 * \param klass An enum class to be validated
10352 * This method verify the required properties an enum should have.
10354 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10355 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10356 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10358 * \returns TRUE if the informed enum class is valid
10361 mono_class_is_valid_enum (MonoClass *klass)
10363 MonoClassField * field;
10364 gpointer iter = NULL;
10365 gboolean found_base_field = FALSE;
10367 g_assert (klass->enumtype);
10368 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10369 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10373 if (!mono_class_is_auto_layout (klass))
10376 while ((field = mono_class_get_fields (klass, &iter))) {
10377 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10378 if (found_base_field)
10380 found_base_field = TRUE;
10381 if (!mono_type_is_valid_enum_basetype (field->type))
10386 if (!found_base_field)
10389 if (mono_class_get_method_count (klass) > 0)
10396 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10398 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10402 * mono_class_setup_interface_id:
10404 * Initializes MonoClass::interface_id if required.
10406 * LOCKING: Acquires the loader lock.
10409 mono_class_setup_interface_id (MonoClass *klass)
10411 mono_loader_lock ();
10412 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10413 klass->interface_id = mono_get_unique_iid (klass);
10414 mono_loader_unlock ();
10418 * mono_class_setup_interfaces:
10420 * Initialize klass->interfaces/interfaces_count.
10421 * LOCKING: Acquires the loader lock.
10422 * This function can fail the type.
10425 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10427 int i, interface_count;
10428 MonoClass **interfaces;
10430 error_init (error);
10432 if (klass->interfaces_inited)
10435 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10436 MonoType *args [1];
10438 /* generic IList, ICollection, IEnumerable */
10439 interface_count = 2;
10440 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10442 args [0] = &klass->element_class->byval_arg;
10443 interfaces [0] = mono_class_bind_generic_parameters (
10444 mono_defaults.generic_ilist_class, 1, args, FALSE);
10445 interfaces [1] = mono_class_bind_generic_parameters (
10446 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10447 } else if (mono_class_is_ginst (klass)) {
10448 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10450 mono_class_setup_interfaces (gklass, error);
10451 if (!mono_error_ok (error)) {
10452 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10456 interface_count = gklass->interface_count;
10457 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10458 for (i = 0; i < interface_count; i++) {
10459 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10460 if (!mono_error_ok (error)) {
10461 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10466 interface_count = 0;
10470 mono_loader_lock ();
10471 if (!klass->interfaces_inited) {
10472 klass->interface_count = interface_count;
10473 klass->interfaces = interfaces;
10475 mono_memory_barrier ();
10477 klass->interfaces_inited = TRUE;
10479 mono_loader_unlock ();
10483 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10485 MonoClass *klass = field->parent;
10486 MonoImage *image = klass->image;
10487 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10489 int field_idx = field - klass->fields;
10491 error_init (error);
10494 MonoClassField *gfield = >d->fields [field_idx];
10495 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10496 if (!mono_error_ok (error)) {
10497 char *full_name = mono_type_get_full_name (gtd);
10498 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));
10499 g_free (full_name);
10502 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10503 if (!mono_error_ok (error)) {
10504 char *full_name = mono_type_get_full_name (klass);
10505 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));
10506 g_free (full_name);
10510 guint32 cols [MONO_FIELD_SIZE];
10511 MonoGenericContainer *container = NULL;
10512 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10514 /*FIXME, in theory we do not lazy load SRE fields*/
10515 g_assert (!image_is_dynamic (image));
10517 if (mono_class_is_gtd (klass)) {
10518 container = mono_class_get_generic_container (klass);
10520 container = mono_class_get_generic_container (gtd);
10521 g_assert (container);
10524 /* first_field_idx and idx points into the fieldptr table */
10525 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10527 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10528 char *full_name = mono_type_get_full_name (klass);
10529 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10530 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10531 g_free (full_name);
10535 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10537 mono_metadata_decode_value (sig, &sig);
10538 /* FIELD signature == 0x06 */
10539 g_assert (*sig == 0x06);
10541 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10543 char *full_name = mono_type_get_full_name (klass);
10544 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));
10545 g_free (full_name);
10548 mono_memory_barrier ();
10549 field->type = ftype;
10553 mono_field_resolve_flags (MonoClassField *field)
10555 MonoClass *klass = field->parent;
10556 MonoImage *image = klass->image;
10557 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10558 int field_idx = field - klass->fields;
10561 MonoClassField *gfield = >d->fields [field_idx];
10562 return mono_field_get_flags (gfield);
10564 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10566 /*FIXME, in theory we do not lazy load SRE fields*/
10567 g_assert (!image_is_dynamic (image));
10569 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10574 * mono_class_get_fields_lazy:
10575 * \param klass the MonoClass to act on
10577 * This routine is an iterator routine for retrieving the fields in a class.
10578 * Only minimal information about fields are loaded. Accessors must be used
10579 * for all MonoClassField returned.
10581 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10582 * iterate over all of the elements. When no more values are
10583 * available, the return value is NULL.
10585 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10588 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10590 MonoClassField* field;
10594 mono_class_setup_basic_field_info (klass);
10595 if (!klass->fields)
10597 /* start from the first */
10598 if (mono_class_get_field_count (klass)) {
10599 *iter = &klass->fields [0];
10600 return (MonoClassField *)*iter;
10606 field = (MonoClassField *)*iter;
10608 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10610 return (MonoClassField *)*iter;
10616 mono_class_full_name (MonoClass *klass)
10618 return mono_type_full_name (&klass->byval_arg);
10621 /* Declare all shared lazy type lookup functions */
10622 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10625 * mono_method_get_base_method:
10626 * \param method a method
10627 * \param definition if true, get the definition
10628 * \param error set on failure
10630 * Given a virtual method associated with a subclass, return the corresponding
10631 * method from an ancestor. If \p definition is FALSE, returns the method in the
10632 * superclass of the given method. If \p definition is TRUE, return the method
10633 * in the ancestor class where it was first declared. The type arguments will
10634 * be inflated in the ancestor classes. If the method is not associated with a
10635 * class, or isn't virtual, returns the method itself. On failure returns NULL
10636 * and sets \p error.
10639 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10641 MonoClass *klass, *parent;
10642 MonoGenericContext *generic_inst = NULL;
10643 MonoMethod *result = NULL;
10646 if (method->klass == NULL)
10649 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10650 MONO_CLASS_IS_INTERFACE (method->klass) ||
10651 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10654 slot = mono_method_get_vtable_slot (method);
10658 klass = method->klass;
10659 if (mono_class_is_ginst (klass)) {
10660 generic_inst = mono_class_get_context (klass);
10661 klass = mono_class_get_generic_class (klass)->container_class;
10666 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10667 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10668 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10669 or klass is the generic container class and generic_inst is the instantiation.
10671 when we go to the parent, if the parent is an open constructed type, we need to
10672 replace the type parameters by the definitions from the generic_inst, and then take it
10673 apart again into the klass and the generic_inst.
10675 For cases like this:
10676 class C<T> : B<T, int> {
10677 public override void Foo () { ... }
10679 class B<U,V> : A<HashMap<U,V>> {
10680 public override void Foo () { ... }
10683 public virtual void Foo () { ... }
10686 if at each iteration the parent isn't open, we can skip inflating it. if at some
10687 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10690 MonoGenericContext *parent_inst = NULL;
10691 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10692 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10693 return_val_if_nok (error, NULL);
10695 if (mono_class_is_ginst (parent)) {
10696 parent_inst = mono_class_get_context (parent);
10697 parent = mono_class_get_generic_class (parent)->container_class;
10700 mono_class_setup_vtable (parent);
10701 if (parent->vtable_size <= slot)
10704 generic_inst = parent_inst;
10707 klass = klass->parent;
10710 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10711 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10712 return_val_if_nok (error, NULL);
10714 generic_inst = NULL;
10716 if (mono_class_is_ginst (klass)) {
10717 generic_inst = mono_class_get_context (klass);
10718 klass = mono_class_get_generic_class (klass)->container_class;
10723 if (generic_inst) {
10724 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10725 return_val_if_nok (error, NULL);
10728 if (klass == method->klass)
10731 /*This is possible if definition == FALSE.
10732 * Do it here to be really sure we don't read invalid memory.
10734 if (slot >= klass->vtable_size)
10737 mono_class_setup_vtable (klass);
10739 result = klass->vtable [slot];
10740 if (result == NULL) {
10741 /* It is an abstract method */
10742 gboolean found = FALSE;
10743 gpointer iter = NULL;
10744 while ((result = mono_class_get_methods (klass, &iter))) {
10745 if (result->slot == slot) {
10750 /* found might be FALSE if we looked in an abstract class
10751 * that doesn't override an abstract method of its
10753 * abstract class Base {
10754 * public abstract void Foo ();
10756 * abstract class Derived : Base { }
10757 * class Child : Derived {
10758 * public override void Foo () { }
10761 * if m was Child.Foo and we ask for the base method,
10762 * then we get here with klass == Derived and found == FALSE
10764 /* but it shouldn't be the case that if we're looking
10765 * for the definition and didn't find a result; the
10766 * loop above should've taken us as far as we could
10768 g_assert (!(definition && !found));
10773 g_assert (result != NULL);