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 * @context: a generics context
878 * If @type is a generic type and @context is not NULL, instantiate it using the
879 * generics context @context.
881 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
882 * on the heap and is owned by the caller. Returns NULL on error.
884 * @deprecated Please use mono_class_inflate_generic_type_checked instead
887 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
891 result = mono_class_inflate_generic_type_checked (type, context, &error);
892 mono_error_cleanup (&error);
897 * mono_class_inflate_generic_type:
899 * @context: a generics context
900 * @error: error context to use
902 * If @type is a generic type and @context is not NULL, instantiate it using the
903 * generics context @context.
905 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
906 * on the heap and is owned by the caller.
909 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
911 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
915 * mono_class_inflate_generic_type_no_copy:
917 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
921 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
923 MonoType *inflated = NULL;
927 inflated = inflate_generic_type (image, type, context, error);
928 return_val_if_nok (error, NULL);
934 mono_stats.inflated_type_count++;
939 * mono_class_inflate_generic_class:
941 * Inflate the class @gklass with @context. Set @error on failure.
944 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
949 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
950 return_val_if_nok (error, NULL);
952 res = mono_class_from_mono_type (inflated);
953 mono_metadata_free_type (inflated);
958 static MonoGenericContext
959 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
961 MonoGenericInst *class_inst = NULL;
962 MonoGenericInst *method_inst = NULL;
963 MonoGenericContext res = { NULL, NULL };
967 if (context->class_inst) {
968 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
969 if (!mono_error_ok (error))
973 if (context->method_inst) {
974 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
975 if (!mono_error_ok (error))
979 res.class_inst = class_inst;
980 res.method_inst = method_inst;
986 * mono_class_inflate_generic_method:
987 * @method: a generic method
988 * @context: a generics context
990 * Instantiate the generic method @method using the generics context @context.
992 * Returns: The new instantiated method
995 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
997 return mono_class_inflate_generic_method_full (method, NULL, context);
1001 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1003 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1007 * mono_class_inflate_generic_method_full:
1009 * Instantiate method \p method with the generic context \p context.
1010 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1011 * Use mono_method_signature() and mono_method_get_header() to get the correct values.
1014 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1017 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1018 if (!mono_error_ok (&error))
1019 /*FIXME do proper error handling - on this case, kill this function. */
1020 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1026 * mono_class_inflate_generic_method_full_checked:
1027 * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1030 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1033 MonoMethodInflated *iresult, *cached;
1034 MonoMethodSignature *sig;
1035 MonoGenericContext tmp_context;
1039 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1040 while (method->is_inflated) {
1041 MonoGenericContext *method_context = mono_method_get_context (method);
1042 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1044 tmp_context = inflate_generic_context (method_context, context, error);
1045 return_val_if_nok (error, NULL);
1047 context = &tmp_context;
1049 if (mono_metadata_generic_context_equal (method_context, context))
1052 method = imethod->declaring;
1056 * A method only needs to be inflated if the context has argument for which it is
1059 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1060 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1063 if (!((method->is_generic && context->method_inst) ||
1064 (mono_class_is_gtd (method->klass) && context->class_inst)))
1067 iresult = g_new0 (MonoMethodInflated, 1);
1068 iresult->context = *context;
1069 iresult->declaring = method;
1071 if (!context->method_inst && method->is_generic)
1072 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1074 if (!context->class_inst) {
1075 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1076 if (mono_class_is_gtd (iresult->declaring->klass))
1077 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1079 /* This can happen with some callers like mono_object_get_virtual_method () */
1080 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1081 iresult->context.class_inst = NULL;
1083 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1086 mono_image_set_lock (set);
1087 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1088 mono_image_set_unlock (set);
1092 return (MonoMethod*)cached;
1095 mono_stats.inflated_method_count++;
1097 inflated_methods_size += sizeof (MonoMethodInflated);
1099 sig = mono_method_signature (method);
1101 char *name = mono_type_get_full_name (method->klass);
1102 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1108 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1110 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1113 result = (MonoMethod *) iresult;
1114 result->is_inflated = TRUE;
1115 result->is_generic = FALSE;
1116 result->sre_method = FALSE;
1117 result->signature = NULL;
1119 if (method->wrapper_type) {
1120 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1121 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1122 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1124 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1125 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1128 if (iresult->context.method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1139 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1140 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1144 if (mono_class_is_gtd (method->klass))
1145 result->klass = klass_hint;
1147 if (!result->klass) {
1148 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1149 if (!mono_error_ok (error))
1152 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1154 mono_metadata_free_type (inflated);
1158 * FIXME: This should hold, but it doesn't:
1160 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1161 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1162 * g_assert (result->is_generic);
1165 * Fixing this here causes other things to break, hence a very
1166 * ugly hack in mini-trampolines.c - see
1167 * is_generic_method_definition().
1171 mono_image_set_lock (set);
1172 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1174 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1175 iresult->owner = set;
1178 mono_image_set_unlock (set);
1180 return (MonoMethod*)cached;
1188 * mono_get_inflated_method:
1190 * Obsolete. We keep it around since it's mentioned in the public API.
1193 mono_get_inflated_method (MonoMethod *method)
1199 * mono_method_get_context_general:
1201 * @uninflated: handle uninflated methods?
1203 * Returns the generic context of a method or NULL if it doesn't have
1204 * one. For an inflated method that's the context stored in the
1205 * method. Otherwise it's in the method's generic container or in the
1206 * generic container of the method's class.
1209 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1211 if (method->is_inflated) {
1212 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1213 return &imethod->context;
1217 if (method->is_generic)
1218 return &(mono_method_get_generic_container (method)->context);
1219 if (mono_class_is_gtd (method->klass))
1220 return &mono_class_get_generic_container (method->klass)->context;
1225 * mono_method_get_context:
1228 * Returns the generic context for method if it's inflated, otherwise
1232 mono_method_get_context (MonoMethod *method)
1234 return mono_method_get_context_general (method, FALSE);
1238 * mono_method_get_generic_container:
1240 * Returns the generic container of METHOD, which should be a generic method definition.
1241 * Returns NULL if METHOD is not a generic method definition.
1242 * LOCKING: Acquires the loader lock.
1244 MonoGenericContainer*
1245 mono_method_get_generic_container (MonoMethod *method)
1247 MonoGenericContainer *container;
1249 if (!method->is_generic)
1252 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1253 g_assert (container);
1259 * mono_method_set_generic_container:
1261 * Sets the generic container of METHOD to CONTAINER.
1262 * LOCKING: Acquires the image lock.
1265 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1267 g_assert (method->is_generic);
1269 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1273 * mono_class_find_enum_basetype:
1274 * \param class The enum class
1276 * Determine the basetype of an enum by iterating through its fields. We do this
1277 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1280 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1282 MonoGenericContainer *container = NULL;
1283 MonoImage *m = klass->image;
1284 const int top = mono_class_get_field_count (klass);
1285 int i, first_field_idx;
1287 g_assert (klass->enumtype);
1291 container = mono_class_try_get_generic_container (klass);
1292 if (mono_class_is_ginst (klass)) {
1293 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1295 container = mono_class_get_generic_container (gklass);
1296 g_assert (container);
1300 * Fetch all the field information.
1302 first_field_idx = mono_class_get_first_field_idx (klass);
1303 for (i = 0; i < top; i++){
1305 guint32 cols [MONO_FIELD_SIZE];
1306 int idx = first_field_idx + i;
1309 /* first_field_idx and idx points into the fieldptr table */
1310 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1312 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1315 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1316 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1320 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1321 mono_metadata_decode_value (sig, &sig);
1322 /* FIELD signature == 0x06 */
1324 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1328 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1332 if (mono_class_is_ginst (klass)) {
1333 //FIXME do we leak here?
1334 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1335 if (!mono_error_ok (error))
1337 ftype->attrs = cols [MONO_FIELD_FLAGS];
1342 mono_error_set_type_load_class (error, klass, "Could not find base type");
1349 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1352 mono_type_has_exceptions (MonoType *type)
1354 switch (type->type) {
1355 case MONO_TYPE_CLASS:
1356 case MONO_TYPE_VALUETYPE:
1357 case MONO_TYPE_SZARRAY:
1358 return mono_class_has_failure (type->data.klass);
1359 case MONO_TYPE_ARRAY:
1360 return mono_class_has_failure (type->data.array->eklass);
1361 case MONO_TYPE_GENERICINST:
1362 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1369 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1371 g_assert (mono_class_has_failure (klass));
1372 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1373 mono_error_set_from_boxed (oerror, box);
1379 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1383 mono_class_alloc (MonoClass *klass, int size)
1385 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1387 return mono_image_set_alloc (gklass->owner, size);
1389 return mono_image_alloc (klass->image, size);
1393 mono_class_alloc0 (MonoClass *klass, int size)
1397 res = mono_class_alloc (klass, size);
1398 memset (res, 0, size);
1402 #define mono_class_new0(klass,struct_type, n_structs) \
1403 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1406 * mono_class_setup_basic_field_info:
1407 * \param class The class to initialize
1409 * Initializes the following fields in MonoClass:
1410 * * klass->fields (only field->parent and field->name)
1411 * * klass->field.count
1412 * * klass->first_field_idx
1413 * LOCKING: Acquires the loader lock
1416 mono_class_setup_basic_field_info (MonoClass *klass)
1418 MonoGenericClass *gklass;
1419 MonoClassField *field;
1420 MonoClassField *fields;
1428 gklass = mono_class_try_get_generic_class (klass);
1429 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1430 image = klass->image;
1433 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1435 * This happens when a generic instance of an unfinished generic typebuilder
1436 * is used as an element type for creating an array type. We can't initialize
1437 * the fields of this class using the fields of gklass, since gklass is not
1438 * finished yet, fields could be added to it later.
1444 mono_class_setup_basic_field_info (gtd);
1446 mono_loader_lock ();
1447 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1448 mono_loader_unlock ();
1451 top = mono_class_get_field_count (klass);
1453 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1456 * Fetch all the field information.
1458 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1459 for (i = 0; i < top; i++) {
1460 field = &fields [i];
1461 field->parent = klass;
1464 field->name = mono_field_get_name (>d->fields [i]);
1466 int idx = first_field_idx + i;
1467 /* first_field_idx and idx points into the fieldptr table */
1468 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1469 /* The name is needed for fieldrefs */
1470 field->name = mono_metadata_string_heap (image, name_idx);
1474 mono_memory_barrier ();
1476 mono_loader_lock ();
1478 klass->fields = fields;
1479 mono_loader_unlock ();
1483 * mono_class_set_failure_causedby_class:
1484 * \param klass the class that is failing
1485 * \param caused_by the class that caused the failure
1486 * \param msg Why \p klass is failing.
1488 * If \p caused_by has a failure, sets a TypeLoadException failure on
1489 * \p klass with message "\p msg, due to: {\p caused_by message}".
1491 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1494 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1496 if (mono_class_has_failure (caused_by)) {
1497 MonoError cause_error;
1498 error_init (&cause_error);
1499 mono_error_set_for_class_failure (&cause_error, caused_by);
1500 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1501 mono_error_cleanup (&cause_error);
1510 * mono_class_setup_fields:
1511 * \p klass The class to initialize
1513 * Initializes klass->fields, computes class layout and sizes.
1514 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1515 * Sets the following fields in \p klass:
1516 * - all the fields initialized by mono_class_init_sizes ()
1517 * - element_class/cast_class (for enums)
1518 * - field->type/offset for all fields
1521 * LOCKING: Acquires the loader lock.
1524 mono_class_setup_fields (MonoClass *klass)
1527 MonoImage *m = klass->image;
1529 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1531 guint32 real_size = 0;
1532 guint32 packing_size = 0;
1534 gboolean explicit_size;
1535 MonoClassField *field;
1536 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1537 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1539 if (klass->fields_inited)
1542 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1544 * This happens when a generic instance of an unfinished generic typebuilder
1545 * is used as an element type for creating an array type. We can't initialize
1546 * the fields of this class using the fields of gklass, since gklass is not
1547 * finished yet, fields could be added to it later.
1552 mono_class_setup_basic_field_info (klass);
1553 top = mono_class_get_field_count (klass);
1556 mono_class_setup_fields (gtd);
1557 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1562 if (klass->parent) {
1563 /* For generic instances, klass->parent might not have been initialized */
1564 mono_class_init (klass->parent);
1565 mono_class_setup_fields (klass->parent);
1566 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1568 instance_size = klass->parent->instance_size;
1570 instance_size = sizeof (MonoObject);
1573 /* Get the real size */
1574 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1576 instance_size += real_size;
1579 * This function can recursively call itself.
1580 * Prevent infinite recursion by using a list in TLS.
1582 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1583 if (g_slist_find (init_list, klass))
1585 init_list = g_slist_prepend (init_list, klass);
1586 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1589 * Fetch all the field information.
1591 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1592 for (i = 0; i < top; i++) {
1593 int idx = first_field_idx + i;
1594 field = &klass->fields [i];
1597 mono_field_resolve_type (field, &error);
1598 if (!mono_error_ok (&error)) {
1599 /*mono_field_resolve_type already failed class*/
1600 mono_error_cleanup (&error);
1604 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1605 g_assert (field->type);
1608 if (mono_field_is_deleted (field))
1610 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1612 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1613 int offset = uoffset;
1615 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1616 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1619 if (offset < -1) { /*-1 is used to encode special static fields */
1620 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1623 if (mono_class_is_gtd (klass)) {
1624 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1628 if (mono_type_has_exceptions (field->type)) {
1629 char *class_name = mono_type_get_full_name (klass);
1630 char *type_name = mono_type_full_name (field->type);
1632 mono_class_set_type_load_failure (klass, "");
1633 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1634 g_free (class_name);
1638 /* The def_value of fields is compute lazily during vtable creation */
1641 if (!mono_class_has_failure (klass)) {
1642 mono_loader_lock ();
1643 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1644 mono_loader_unlock ();
1647 init_list = g_slist_remove (init_list, klass);
1648 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1652 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1655 mono_loader_lock ();
1656 klass->instance_size = cached_info->instance_size;
1657 klass->sizes.class_size = cached_info->class_size;
1658 klass->packing_size = cached_info->packing_size;
1659 klass->min_align = cached_info->min_align;
1660 klass->blittable = cached_info->blittable;
1661 klass->has_references = cached_info->has_references;
1662 klass->has_static_refs = cached_info->has_static_refs;
1663 klass->no_special_static_fields = cached_info->no_special_static_fields;
1664 mono_loader_unlock ();
1667 if (!klass->size_inited)
1668 mono_class_setup_fields (klass);
1673 * mono_class_init_sizes:
1675 * Initializes the size related fields of @klass without loading all field data if possible.
1676 * Sets the following fields in @klass:
1678 * - sizes.class_size
1685 * Can fail the class.
1687 * LOCKING: Acquires the loader lock.
1690 mono_class_init_sizes (MonoClass *klass)
1692 MonoCachedClassInfo cached_info;
1693 gboolean has_cached_info;
1695 if (klass->size_inited)
1698 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1700 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1704 * mono_type_get_basic_type_from_generic:
1707 * Returns a closed type corresponding to the possibly open type
1711 mono_type_get_basic_type_from_generic (MonoType *type)
1713 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1714 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1715 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1716 return &mono_defaults.object_class->byval_arg;
1721 class_has_references (MonoClass *klass)
1723 mono_class_init_sizes (klass);
1726 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1727 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1730 return klass->has_references;
1734 type_has_references (MonoClass *klass, MonoType *ftype)
1736 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1738 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1739 MonoGenericParam *gparam = ftype->data.generic_param;
1741 if (gparam->gshared_constraint)
1742 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1748 * mono_class_layout_fields:
1750 * @base_instance_size: base instance size
1753 * This contains the common code for computing the layout of classes and sizes.
1754 * This should only be called from mono_class_setup_fields () and
1755 * typebuilder_setup_fields ().
1757 * LOCKING: Acquires the loader lock
1760 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1763 const int top = mono_class_get_field_count (klass);
1764 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1765 guint32 pass, passes, real_size;
1766 gboolean gc_aware_layout = FALSE;
1767 gboolean has_static_fields = FALSE;
1768 gboolean has_references = FALSE;
1769 gboolean has_static_refs = FALSE;
1770 MonoClassField *field;
1772 int instance_size = base_instance_size;
1773 int class_size, min_align;
1775 gboolean *fields_has_references;
1778 * We want to avoid doing complicated work inside locks, so we compute all the required
1779 * information and write it to @klass inside a lock.
1781 if (klass->fields_inited)
1784 if ((packing_size & 0xffffff00) != 0) {
1785 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1789 if (klass->parent) {
1790 min_align = klass->parent->min_align;
1791 /* we use | since it may have been set already */
1792 has_references = klass->has_references | klass->parent->has_references;
1796 /* We can't really enable 16 bytes alignment until the GC supports it.
1797 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1798 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1799 Bug #506144 is an example of this issue.
1801 if (klass->simd_type)
1806 * When we do generic sharing we need to have layout
1807 * information for open generic classes (either with a generic
1808 * context containing type variables or with a generic
1809 * container), so we don't return in that case anymore.
1812 if (klass->enumtype) {
1813 for (i = 0; i < top; i++) {
1814 field = &klass->fields [i];
1815 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1816 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1821 if (!mono_class_enum_basetype (klass)) {
1822 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1828 * Enable GC aware auto layout: in this mode, reference
1829 * fields are grouped together inside objects, increasing collector
1831 * Requires that all classes whose layout is known to native code be annotated
1832 * with [StructLayout (LayoutKind.Sequential)]
1833 * Value types have gc_aware_layout disabled by default, as per
1834 * what the default is for other runtimes.
1836 /* corlib is missing [StructLayout] directives in many places */
1837 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1838 if (!klass->valuetype)
1839 gc_aware_layout = TRUE;
1842 /* Compute klass->blittable */
1845 blittable = klass->parent->blittable;
1846 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1848 for (i = 0; i < top; i++) {
1849 field = &klass->fields [i];
1851 if (mono_field_is_deleted (field))
1853 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1856 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1859 MonoClass *field_class = mono_class_from_mono_type (field->type);
1861 mono_class_setup_fields (field_class);
1862 if (mono_class_has_failure (field_class)) {
1863 MonoError field_error;
1864 error_init (&field_error);
1865 mono_error_set_for_class_failure (&field_error, field_class);
1866 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1867 mono_error_cleanup (&field_error);
1871 if (!field_class || !field_class->blittable)
1875 if (klass->enumtype)
1876 blittable = klass->element_class->blittable;
1878 if (mono_class_has_failure (klass))
1880 if (klass == mono_defaults.string_class)
1883 /* Compute klass->has_references */
1885 * Process non-static fields first, since static fields might recursively
1886 * refer to the class itself.
1888 for (i = 0; i < top; i++) {
1891 field = &klass->fields [i];
1893 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1894 ftype = mono_type_get_underlying_type (field->type);
1895 ftype = mono_type_get_basic_type_from_generic (ftype);
1896 if (type_has_references (klass, ftype))
1897 has_references = TRUE;
1902 * Compute field layout and total size (not considering static fields)
1904 field_offsets = g_new0 (int, top);
1905 fields_has_references = g_new0 (gboolean, top);
1906 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1908 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1909 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1910 if (gc_aware_layout)
1915 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1918 if (klass->parent) {
1919 mono_class_setup_fields (klass->parent);
1920 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1922 real_size = klass->parent->instance_size;
1924 real_size = sizeof (MonoObject);
1927 for (pass = 0; pass < passes; ++pass) {
1928 for (i = 0; i < top; i++){
1933 field = &klass->fields [i];
1935 if (mono_field_is_deleted (field))
1937 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1940 ftype = mono_type_get_underlying_type (field->type);
1941 ftype = mono_type_get_basic_type_from_generic (ftype);
1942 if (gc_aware_layout) {
1943 fields_has_references [i] = type_has_references (klass, ftype);
1944 if (fields_has_references [i]) {
1953 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1954 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1955 /* This field is a hack inserted by MCS to empty structures */
1959 size = mono_type_size (field->type, &align);
1961 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1962 align = packing_size ? MIN (packing_size, align): align;
1963 /* if the field has managed references, we need to force-align it
1966 if (type_has_references (klass, ftype))
1967 align = MAX (align, sizeof (gpointer));
1969 min_align = MAX (align, min_align);
1970 field_offsets [i] = real_size;
1972 field_offsets [i] += align - 1;
1973 field_offsets [i] &= ~(align - 1);
1975 /*TypeBuilders produce all sort of weird things*/
1976 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1977 real_size = field_offsets [i] + size;
1980 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1981 if (klass->simd_type)
1982 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1983 instance_size = MAX (real_size, instance_size);
1985 if (instance_size & (min_align - 1)) {
1986 instance_size += min_align - 1;
1987 instance_size &= ~(min_align - 1);
1991 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1995 for (i = 0; i < top; i++) {
2000 field = &klass->fields [i];
2003 * There must be info about all the fields in a type if it
2004 * uses explicit layout.
2006 if (mono_field_is_deleted (field))
2008 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2011 size = mono_type_size (field->type, &align);
2012 align = packing_size ? MIN (packing_size, align): align;
2013 min_align = MAX (align, min_align);
2016 /* Already set by typebuilder_setup_fields () */
2017 field_offsets [i] = field->offset + sizeof (MonoObject);
2019 int idx = first_field_idx + i;
2021 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2022 field_offsets [i] = offset + sizeof (MonoObject);
2024 ftype = mono_type_get_underlying_type (field->type);
2025 ftype = mono_type_get_basic_type_from_generic (ftype);
2026 if (type_has_references (klass, ftype)) {
2027 if (field_offsets [i] % sizeof (gpointer)) {
2028 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2035 real_size = MAX (real_size, size + field_offsets [i]);
2038 if (klass->has_references) {
2039 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2041 /* Check for overlapping reference and non-reference fields */
2042 for (i = 0; i < top; i++) {
2045 field = &klass->fields [i];
2047 if (mono_field_is_deleted (field))
2049 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2051 ftype = mono_type_get_underlying_type (field->type);
2052 if (MONO_TYPE_IS_REFERENCE (ftype))
2053 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2055 for (i = 0; i < top; i++) {
2056 field = &klass->fields [i];
2058 if (mono_field_is_deleted (field))
2060 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2063 // FIXME: Too much code does this
2065 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2066 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]);
2070 g_free (ref_bitmap);
2073 instance_size = MAX (real_size, instance_size);
2074 if (instance_size & (min_align - 1)) {
2075 instance_size += min_align - 1;
2076 instance_size &= ~(min_align - 1);
2082 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2084 * This leads to all kinds of problems with nested structs, so only
2085 * enable it when a MONO_DEBUG property is set.
2087 * For small structs, set min_align to at least the struct size to improve
2088 * performance, and since the JIT memset/memcpy code assumes this and generates
2089 * unaligned accesses otherwise. See #78990 for a testcase.
2091 if (mono_align_small_structs && top) {
2092 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2093 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2097 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2098 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2099 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2100 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2102 /* Publish the data */
2103 mono_loader_lock ();
2104 if (klass->instance_size && !klass->image->dynamic) {
2105 /* Might be already set using cached info */
2106 if (klass->instance_size != instance_size) {
2107 /* Emit info to help debugging */
2108 g_print ("%s\n", mono_class_full_name (klass));
2109 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2110 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2111 g_print ("%d %d\n", klass->min_align, min_align);
2112 for (i = 0; i < top; ++i) {
2113 field = &klass->fields [i];
2114 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2115 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2118 g_assert (klass->instance_size == instance_size);
2120 klass->instance_size = instance_size;
2122 klass->blittable = blittable;
2123 klass->has_references = has_references;
2124 klass->packing_size = packing_size;
2125 klass->min_align = min_align;
2126 for (i = 0; i < top; ++i) {
2127 field = &klass->fields [i];
2128 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2129 klass->fields [i].offset = field_offsets [i];
2132 mono_memory_barrier ();
2133 klass->size_inited = 1;
2134 mono_loader_unlock ();
2137 * Compute static field layout and size
2138 * Static fields can reference the class itself, so this has to be
2139 * done after instance_size etc. are initialized.
2142 for (i = 0; i < top; i++) {
2146 field = &klass->fields [i];
2148 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2150 if (mono_field_is_deleted (field))
2153 if (mono_type_has_exceptions (field->type)) {
2154 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2158 has_static_fields = TRUE;
2160 size = mono_type_size (field->type, &align);
2161 field_offsets [i] = class_size;
2162 /*align is always non-zero here*/
2163 field_offsets [i] += align - 1;
2164 field_offsets [i] &= ~(align - 1);
2165 class_size = field_offsets [i] + size;
2168 if (has_static_fields && class_size == 0)
2169 /* Simplify code which depends on class_size != 0 if the class has static fields */
2172 /* Compute klass->has_static_refs */
2173 has_static_refs = FALSE;
2174 for (i = 0; i < top; i++) {
2177 field = &klass->fields [i];
2179 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2180 ftype = mono_type_get_underlying_type (field->type);
2181 ftype = mono_type_get_basic_type_from_generic (ftype);
2182 if (type_has_references (klass, ftype))
2183 has_static_refs = TRUE;
2187 /*valuetypes can't be neither bigger than 1Mb or empty. */
2188 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2189 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2191 /* Publish the data */
2192 mono_loader_lock ();
2194 klass->sizes.class_size = class_size;
2195 klass->has_static_refs = has_static_refs;
2196 for (i = 0; i < top; ++i) {
2197 field = &klass->fields [i];
2199 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2200 field->offset = field_offsets [i];
2203 mono_memory_barrier ();
2204 klass->fields_inited = 1;
2205 mono_loader_unlock ();
2207 g_free (field_offsets);
2208 g_free (fields_has_references);
2212 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2216 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2217 method->klass = klass;
2218 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2219 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2220 method->signature = sig;
2221 method->name = name;
2224 if (name [0] == '.') {
2225 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2227 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2233 * mono_class_setup_methods:
2236 * Initializes the 'methods' array in CLASS.
2237 * Calling this method should be avoided if possible since it allocates a lot
2238 * of long-living MonoMethod structures.
2239 * Methods belonging to an interface are assigned a sequential slot starting
2242 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2245 mono_class_setup_methods (MonoClass *klass)
2248 MonoMethod **methods;
2253 if (mono_class_is_ginst (klass)) {
2255 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2257 mono_class_init (gklass);
2258 if (!mono_class_has_failure (gklass))
2259 mono_class_setup_methods (gklass);
2260 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2263 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2264 count = mono_class_get_method_count (gklass);
2265 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2267 for (i = 0; i < count; i++) {
2268 methods [i] = mono_class_inflate_generic_method_full_checked (
2269 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2270 if (!mono_error_ok (&error)) {
2271 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2272 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2275 mono_error_cleanup (&error);
2279 } else if (klass->rank) {
2281 MonoMethod *amethod;
2282 MonoMethodSignature *sig;
2283 int count_generic = 0, first_generic = 0;
2285 gboolean jagged_ctor = FALSE;
2287 count = 3 + (klass->rank > 1? 2: 1);
2289 mono_class_setup_interfaces (klass, &error);
2290 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2292 if (klass->rank == 1 && klass->element_class->rank) {
2297 if (klass->interface_count) {
2298 count_generic = generic_array_methods (klass);
2299 first_generic = count;
2300 count += klass->interface_count * count_generic;
2303 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2305 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2306 sig->ret = &mono_defaults.void_class->byval_arg;
2307 sig->pinvoke = TRUE;
2308 sig->hasthis = TRUE;
2309 for (i = 0; i < klass->rank; ++i)
2310 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2312 amethod = create_array_method (klass, ".ctor", sig);
2313 methods [method_num++] = amethod;
2314 if (klass->rank > 1) {
2315 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2316 sig->ret = &mono_defaults.void_class->byval_arg;
2317 sig->pinvoke = TRUE;
2318 sig->hasthis = TRUE;
2319 for (i = 0; i < klass->rank * 2; ++i)
2320 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2322 amethod = create_array_method (klass, ".ctor", sig);
2323 methods [method_num++] = amethod;
2327 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2328 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2329 sig->ret = &mono_defaults.void_class->byval_arg;
2330 sig->pinvoke = TRUE;
2331 sig->hasthis = TRUE;
2332 for (i = 0; i < klass->rank + 1; ++i)
2333 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2334 amethod = create_array_method (klass, ".ctor", sig);
2335 methods [method_num++] = amethod;
2338 /* element Get (idx11, [idx2, ...]) */
2339 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2340 sig->ret = &klass->element_class->byval_arg;
2341 sig->pinvoke = TRUE;
2342 sig->hasthis = TRUE;
2343 for (i = 0; i < klass->rank; ++i)
2344 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2345 amethod = create_array_method (klass, "Get", sig);
2346 methods [method_num++] = amethod;
2347 /* element& Address (idx11, [idx2, ...]) */
2348 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2349 sig->ret = &klass->element_class->this_arg;
2350 sig->pinvoke = TRUE;
2351 sig->hasthis = TRUE;
2352 for (i = 0; i < klass->rank; ++i)
2353 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2354 amethod = create_array_method (klass, "Address", sig);
2355 methods [method_num++] = amethod;
2356 /* void Set (idx11, [idx2, ...], element) */
2357 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2358 sig->ret = &mono_defaults.void_class->byval_arg;
2359 sig->pinvoke = TRUE;
2360 sig->hasthis = TRUE;
2361 for (i = 0; i < klass->rank; ++i)
2362 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2363 sig->params [i] = &klass->element_class->byval_arg;
2364 amethod = create_array_method (klass, "Set", sig);
2365 methods [method_num++] = amethod;
2367 GHashTable *cache = g_hash_table_new (NULL, NULL);
2368 for (i = 0; i < klass->interface_count; i++)
2369 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2370 g_hash_table_destroy (cache);
2371 } else if (mono_class_has_static_metadata (klass)) {
2373 int first_idx = mono_class_get_first_method_idx (klass);
2375 count = mono_class_get_method_count (klass);
2376 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2377 for (i = 0; i < count; ++i) {
2378 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2379 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2381 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2382 mono_error_cleanup (&error);
2386 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2390 if (MONO_CLASS_IS_INTERFACE (klass)) {
2392 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2393 for (i = 0; i < count; ++i) {
2394 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2395 methods [i]->slot = slot++;
2399 mono_image_lock (klass->image);
2401 if (!klass->methods) {
2402 mono_class_set_method_count (klass, count);
2404 /* Needed because of the double-checking locking pattern */
2405 mono_memory_barrier ();
2407 klass->methods = methods;
2410 mono_image_unlock (klass->image);
2414 * mono_class_get_method_by_index:
2416 * Returns klass->methods [index], initializing klass->methods if neccesary.
2418 * LOCKING: Acquires the loader lock.
2421 mono_class_get_method_by_index (MonoClass *klass, int index)
2425 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2426 /* Avoid calling setup_methods () if possible */
2427 if (gklass && !klass->methods) {
2430 m = mono_class_inflate_generic_method_full_checked (
2431 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2432 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2434 * If setup_methods () is called later for this class, no duplicates are created,
2435 * since inflate_generic_method guarantees that only one instance of a method
2436 * is created for each context.
2439 mono_class_setup_methods (klass);
2440 g_assert (m == klass->methods [index]);
2444 mono_class_setup_methods (klass);
2445 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2447 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2448 return klass->methods [index];
2453 * mono_class_get_inflated_method:
2455 * Given an inflated class CLASS and a method METHOD which should be a method of
2456 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2459 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2461 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2464 g_assert (method->klass == gklass);
2466 mono_class_setup_methods (gklass);
2467 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2469 mcount = mono_class_get_method_count (gklass);
2470 for (i = 0; i < mcount; ++i) {
2471 if (gklass->methods [i] == method) {
2472 if (klass->methods) {
2473 return klass->methods [i];
2476 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2477 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2487 * mono_class_get_vtable_entry:
2489 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2490 * LOCKING: Acquires the loader lock.
2493 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2497 if (klass->rank == 1) {
2499 * szarrays do not overwrite any methods of Array, so we can avoid
2500 * initializing their vtables in some cases.
2502 mono_class_setup_vtable (klass->parent);
2503 if (offset < klass->parent->vtable_size)
2504 return klass->parent->vtable [offset];
2507 if (mono_class_is_ginst (klass)) {
2509 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2510 mono_class_setup_vtable (gklass);
2511 m = gklass->vtable [offset];
2513 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2514 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2516 mono_class_setup_vtable (klass);
2517 if (mono_class_has_failure (klass))
2519 m = klass->vtable [offset];
2526 * mono_class_get_vtable_size:
2528 * Return the vtable size for KLASS.
2531 mono_class_get_vtable_size (MonoClass *klass)
2533 mono_class_setup_vtable (klass);
2535 return klass->vtable_size;
2539 * mono_class_setup_properties:
2541 * Initialize klass->ext.property and klass->ext.properties.
2543 * This method can fail the class.
2546 mono_class_setup_properties (MonoClass *klass)
2548 guint startm, endm, i, j;
2549 guint32 cols [MONO_PROPERTY_SIZE];
2550 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2551 MonoProperty *properties;
2554 MonoClassPropertyInfo *info;
2556 info = mono_class_get_property_info (klass);
2560 if (mono_class_is_ginst (klass)) {
2561 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2563 mono_class_init (gklass);
2564 mono_class_setup_properties (gklass);
2565 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2568 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2569 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2571 for (i = 0; i < ginfo->count; i++) {
2573 MonoProperty *prop = &properties [i];
2575 *prop = ginfo->properties [i];
2578 prop->get = mono_class_inflate_generic_method_full_checked (
2579 prop->get, klass, mono_class_get_context (klass), &error);
2581 prop->set = mono_class_inflate_generic_method_full_checked (
2582 prop->set, klass, mono_class_get_context (klass), &error);
2584 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2585 prop->parent = klass;
2588 first = ginfo->first;
2589 count = ginfo->count;
2591 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2592 count = last - first;
2595 mono_class_setup_methods (klass);
2596 if (mono_class_has_failure (klass))
2600 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2601 for (i = first; i < last; ++i) {
2602 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2603 properties [i - first].parent = klass;
2604 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2605 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2607 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2608 int first_idx = mono_class_get_first_method_idx (klass);
2609 for (j = startm; j < endm; ++j) {
2612 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2614 if (klass->image->uncompressed_metadata) {
2616 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2617 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2618 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2620 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2623 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2624 case METHOD_SEMANTIC_SETTER:
2625 properties [i - first].set = method;
2627 case METHOD_SEMANTIC_GETTER:
2628 properties [i - first].get = method;
2637 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2638 info->first = first;
2639 info->count = count;
2640 info->properties = properties;
2641 mono_memory_barrier ();
2643 /* This might leak 'info' which was allocated from the image mempool */
2644 mono_class_set_property_info (klass, info);
2648 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2650 MonoMethod **om, **retval;
2653 for (om = methods, count = 0; *om; ++om, ++count)
2656 retval = g_new0 (MonoMethod*, count + 1);
2658 for (om = methods, count = 0; *om; ++om, ++count) {
2660 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2661 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2667 /*This method can fail the class.*/
2669 mono_class_setup_events (MonoClass *klass)
2672 guint startm, endm, i, j;
2673 guint32 cols [MONO_EVENT_SIZE];
2674 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2678 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2682 if (mono_class_is_ginst (klass)) {
2683 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2684 MonoGenericContext *context = NULL;
2686 mono_class_setup_events (gklass);
2687 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2690 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2691 first = ginfo->first;
2692 count = ginfo->count;
2694 events = mono_class_new0 (klass, MonoEvent, count);
2697 context = mono_class_get_context (klass);
2699 for (i = 0; i < count; i++) {
2701 MonoEvent *event = &events [i];
2702 MonoEvent *gevent = &ginfo->events [i];
2704 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2706 event->parent = klass;
2707 event->name = gevent->name;
2708 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2709 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2710 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2711 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2712 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2713 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2715 #ifndef MONO_SMALL_CONFIG
2716 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2718 event->attrs = gevent->attrs;
2721 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2722 count = last - first;
2725 mono_class_setup_methods (klass);
2726 if (mono_class_has_failure (klass)) {
2731 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2732 for (i = first; i < last; ++i) {
2733 MonoEvent *event = &events [i - first];
2735 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2736 event->parent = klass;
2737 event->attrs = cols [MONO_EVENT_FLAGS];
2738 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2740 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2741 int first_idx = mono_class_get_first_method_idx (klass);
2742 for (j = startm; j < endm; ++j) {
2745 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2747 if (klass->image->uncompressed_metadata) {
2749 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2750 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2751 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2753 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2756 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2757 case METHOD_SEMANTIC_ADD_ON:
2758 event->add = method;
2760 case METHOD_SEMANTIC_REMOVE_ON:
2761 event->remove = method;
2763 case METHOD_SEMANTIC_FIRE:
2764 event->raise = method;
2766 case METHOD_SEMANTIC_OTHER: {
2767 #ifndef MONO_SMALL_CONFIG
2770 if (event->other == NULL) {
2771 event->other = g_new0 (MonoMethod*, 2);
2773 while (event->other [n])
2775 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2777 event->other [n] = method;
2778 /* NULL terminated */
2779 event->other [n + 1] = NULL;
2790 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2791 info->events = events;
2792 info->first = first;
2793 info->count = count;
2795 mono_memory_barrier ();
2797 mono_class_set_event_info (klass, info);
2801 * Global pool of interface IDs, represented as a bitset.
2802 * LOCKING: Protected by the classes lock.
2804 static MonoBitSet *global_interface_bitset = NULL;
2807 * mono_unload_interface_ids:
2808 * @bitset: bit set of interface IDs
2810 * When an image is unloaded, the interface IDs associated with
2811 * the image are put back in the global pool of IDs so the numbers
2815 mono_unload_interface_ids (MonoBitSet *bitset)
2818 mono_bitset_sub (global_interface_bitset, bitset);
2823 mono_unload_interface_id (MonoClass *klass)
2825 if (global_interface_bitset && klass->interface_id) {
2827 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2833 * mono_get_unique_iid:
2834 * \param klass interface
2836 * Assign a unique integer ID to the interface represented by \p klass.
2837 * The ID will positive and as small as possible.
2838 * LOCKING: Acquires the classes lock.
2839 * \returns The new ID.
2842 mono_get_unique_iid (MonoClass *klass)
2846 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2850 if (!global_interface_bitset) {
2851 global_interface_bitset = mono_bitset_new (128, 0);
2854 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2856 int old_size = mono_bitset_size (global_interface_bitset);
2857 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2858 mono_bitset_free (global_interface_bitset);
2859 global_interface_bitset = new_set;
2862 mono_bitset_set (global_interface_bitset, iid);
2863 /* set the bit also in the per-image set */
2864 if (!mono_class_is_ginst (klass)) {
2865 if (klass->image->interface_bitset) {
2866 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2867 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2868 mono_bitset_free (klass->image->interface_bitset);
2869 klass->image->interface_bitset = new_set;
2872 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2874 mono_bitset_set (klass->image->interface_bitset, iid);
2879 #ifndef MONO_SMALL_CONFIG
2880 if (mono_print_vtable) {
2882 char *type_name = mono_type_full_name (&klass->byval_arg);
2883 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2884 if (gklass && !gklass->context.class_inst->is_open) {
2885 generic_id = gklass->context.class_inst->id;
2886 g_assert (generic_id != 0);
2890 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2895 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2896 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2897 g_assert (iid < INT_MAX);
2902 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2907 mono_class_setup_interfaces (klass, error);
2908 return_if_nok (error);
2910 for (i = 0; i < klass->interface_count; i++) {
2911 ic = klass->interfaces [i];
2914 *res = g_ptr_array_new ();
2915 if (*ifaces == NULL)
2916 *ifaces = g_hash_table_new (NULL, NULL);
2917 if (g_hash_table_lookup (*ifaces, ic))
2919 g_ptr_array_add (*res, ic);
2920 g_hash_table_insert (*ifaces, ic, ic);
2921 mono_class_init (ic);
2922 if (mono_class_has_failure (ic)) {
2923 mono_error_set_type_load_class (error, ic, "Error Loading class");
2927 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2928 return_if_nok (error);
2933 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2935 GPtrArray *res = NULL;
2936 GHashTable *ifaces = NULL;
2938 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2940 g_hash_table_destroy (ifaces);
2941 if (!mono_error_ok (error)) {
2943 g_ptr_array_free (res, TRUE);
2950 compare_interface_ids (const void *p_key, const void *p_element)
2952 const MonoClass *key = (const MonoClass *)p_key;
2953 const MonoClass *element = *(const MonoClass **)p_element;
2955 return (key->interface_id - element->interface_id);
2958 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2960 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2962 MonoClass **result = (MonoClass **)mono_binary_search (
2964 klass->interfaces_packed,
2965 klass->interface_offsets_count,
2966 sizeof (MonoClass *),
2967 compare_interface_ids);
2969 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2976 * mono_class_interface_offset_with_variance:
2978 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2979 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2981 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2983 * FIXME figure out MS disambiguation rules and fix this function.
2986 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2988 int i = mono_class_interface_offset (klass, itf);
2989 *non_exact_match = FALSE;
2993 if (itf->is_array_special_interface && klass->rank < 2) {
2994 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
2996 for (i = 0; i < klass->interface_offsets_count; i++) {
2997 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
2998 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
2999 *non_exact_match = TRUE;
3000 return klass->interface_offsets_packed [i];
3005 if (!mono_class_has_variant_generic_params (itf))
3008 for (i = 0; i < klass->interface_offsets_count; i++) {
3009 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3010 *non_exact_match = TRUE;
3011 return klass->interface_offsets_packed [i];
3019 print_implemented_interfaces (MonoClass *klass)
3023 GPtrArray *ifaces = NULL;
3025 int ancestor_level = 0;
3027 name = mono_type_get_full_name (klass);
3028 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3031 for (i = 0; i < klass->interface_offsets_count; i++)
3032 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3033 klass->interfaces_packed [i]->interface_id,
3034 klass->interface_offsets_packed [i],
3035 mono_class_get_method_count (klass->interfaces_packed [i]),
3036 klass->interfaces_packed [i]->name_space,
3037 klass->interfaces_packed [i]->name );
3038 printf ("Interface flags: ");
3039 for (i = 0; i <= klass->max_interface_id; i++)
3040 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3041 printf ("(%d,T)", i);
3043 printf ("(%d,F)", i);
3045 printf ("Dump interface flags:");
3046 #ifdef COMPRESSED_INTERFACE_BITMAP
3048 const uint8_t* p = klass->interface_bitmap;
3049 i = klass->max_interface_id;
3051 printf (" %d x 00 %02X", p [0], p [1]);
3057 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3058 printf (" %02X", klass->interface_bitmap [i]);
3061 while (klass != NULL) {
3062 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3063 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3064 if (!mono_error_ok (&error)) {
3065 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3066 mono_error_cleanup (&error);
3067 } else if (ifaces) {
3068 for (i = 0; i < ifaces->len; i++) {
3069 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3070 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3071 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3073 mono_class_interface_offset (klass, ic),
3074 mono_class_get_method_count (ic),
3078 g_ptr_array_free (ifaces, TRUE);
3081 klass = klass->parent;
3086 * Return the number of virtual methods.
3087 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3088 * Return -1 on failure.
3089 * FIXME It would be nice if this information could be cached somewhere.
3092 count_virtual_methods (MonoClass *klass)
3094 int i, mcount, vcount = 0;
3096 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3098 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3099 mono_class_setup_methods (klass);
3100 if (mono_class_has_failure (klass))
3103 mcount = mono_class_get_method_count (klass);
3104 for (i = 0; i < mcount; ++i) {
3105 flags = klass->methods [i]->flags;
3106 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3110 int first_idx = mono_class_get_first_method_idx (klass);
3111 mcount = mono_class_get_method_count (klass);
3112 for (i = 0; i < mcount; ++i) {
3113 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3115 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3123 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3131 m = (l + num_ifaces) / 2;
3132 if (interfaces_full [m] == ic)
3134 if (l == num_ifaces)
3136 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3145 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3147 int i = find_interface (num_ifaces, interfaces_full, ic);
3151 interface_offsets_full [i] = offset;
3154 for (i = 0; i < num_ifaces; ++i) {
3155 if (interfaces_full [i]) {
3157 if (interfaces_full [i]->interface_id < ic->interface_id)
3160 while (end < num_ifaces && interfaces_full [end]) end++;
3161 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3162 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3164 interfaces_full [i] = ic;
3165 interface_offsets_full [i] = offset;
3171 #ifdef COMPRESSED_INTERFACE_BITMAP
3174 * Compressed interface bitmap design.
3176 * Interface bitmaps take a large amount of memory, because their size is
3177 * linear with the maximum interface id assigned in the process (each interface
3178 * is assigned a unique id as it is loaded). The number of interface classes
3179 * is high because of the many implicit interfaces implemented by arrays (we'll
3180 * need to lazy-load them in the future).
3181 * Most classes implement a very small number of interfaces, so the bitmap is
3182 * sparse. This bitmap needs to be checked by interface casts, so access to the
3183 * needed bit must be fast and doable with few jit instructions.
3185 * The current compression format is as follows:
3186 * *) it is a sequence of one or more two-byte elements
3187 * *) the first byte in the element is the count of empty bitmap bytes
3188 * at the current bitmap position
3189 * *) the second byte in the element is an actual bitmap byte at the current
3192 * As an example, the following compressed bitmap bytes:
3193 * 0x07 0x01 0x00 0x7
3194 * correspond to the following bitmap:
3195 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3197 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3198 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3199 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3203 * mono_compress_bitmap:
3204 * \param dest destination buffer
3205 * \param bitmap bitmap buffer
3206 * \param size size of \p bitmap in bytes
3208 * This is a mono internal function.
3209 * The \p bitmap data is compressed into a format that is small but
3210 * still searchable in few instructions by the JIT and runtime.
3211 * The compressed data is stored in the buffer pointed to by the
3212 * \p dest array. Passing a NULL value for \p dest allows to just compute
3213 * the size of the buffer.
3214 * This compression algorithm assumes the bits set in the bitmap are
3215 * few and far between, like in interface bitmaps.
3216 * \returns The size of the compressed bitmap in bytes.
3219 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3223 const uint8_t *end = bitmap + size;
3224 while (bitmap < end) {
3225 if (*bitmap || numz == 255) {
3249 * mono_class_interface_match:
3250 * \param bitmap a compressed bitmap buffer
3251 * \param id the index to check in the bitmap
3253 * This is a mono internal function.
3254 * Checks if a bit is set in a compressed interface bitmap. \p id must
3255 * be already checked for being smaller than the maximum id encoded in the
3258 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3262 mono_class_interface_match (const uint8_t *bitmap, int id)
3265 id -= bitmap [0] * 8;
3269 return bitmap [1] & (1 << id);
3278 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3279 * LOCKING: Acquires the loader lock.
3282 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3286 int i, j, num_ifaces;
3288 MonoClass **interfaces_full = NULL;
3289 int *interface_offsets_full = NULL;
3291 GPtrArray **ifaces_array = NULL;
3292 int interface_offsets_count;
3294 mono_loader_lock ();
3296 mono_class_setup_supertypes (klass);
3298 /* compute maximum number of slots and maximum interface id */
3300 num_ifaces = 0; /* this can include duplicated ones */
3301 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3302 for (j = 0; j < klass->idepth; j++) {
3303 k = klass->supertypes [j];
3305 num_ifaces += k->interface_count;
3306 for (i = 0; i < k->interface_count; i++) {
3307 ic = k->interfaces [i];
3309 mono_class_init (ic);
3311 if (max_iid < ic->interface_id)
3312 max_iid = ic->interface_id;
3314 ifaces = mono_class_get_implemented_interfaces (k, &error);
3315 if (!mono_error_ok (&error)) {
3316 char *name = mono_type_get_full_name (k);
3317 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3319 mono_error_cleanup (&error);
3324 num_ifaces += ifaces->len;
3325 for (i = 0; i < ifaces->len; ++i) {
3326 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3327 if (max_iid < ic->interface_id)
3328 max_iid = ic->interface_id;
3330 ifaces_array [j] = ifaces;
3334 if (MONO_CLASS_IS_INTERFACE (klass)) {
3336 if (max_iid < klass->interface_id)
3337 max_iid = klass->interface_id;
3340 /* compute vtable offset for interfaces */
3341 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3342 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3344 for (i = 0; i < num_ifaces; i++)
3345 interface_offsets_full [i] = -1;
3347 /* skip the current class */
3348 for (j = 0; j < klass->idepth - 1; j++) {
3349 k = klass->supertypes [j];
3350 ifaces = ifaces_array [j];
3353 for (i = 0; i < ifaces->len; ++i) {
3355 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3357 /*Force the sharing of interface offsets between parent and subtypes.*/
3358 io = mono_class_interface_offset (k, ic);
3360 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3365 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3366 ifaces = ifaces_array [klass->idepth - 1];
3368 for (i = 0; i < ifaces->len; ++i) {
3370 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3371 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3373 count = count_virtual_methods (ic);
3375 char *name = mono_type_get_full_name (ic);
3376 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3385 if (MONO_CLASS_IS_INTERFACE (klass))
3386 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3388 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3389 if (interface_offsets_full [i] != -1)
3390 interface_offsets_count ++;
3393 /* Publish the data */
3394 klass->max_interface_id = max_iid;
3396 * We might get called multiple times:
3397 * - mono_class_init ()
3398 * - mono_class_setup_vtable ().
3399 * - mono_class_setup_interface_offsets ().
3400 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3401 * means we have to overwrite those when called from other places (#4440).
3403 if (klass->interfaces_packed) {
3405 g_assert (klass->interface_offsets_count == interface_offsets_count);
3409 klass->interface_offsets_count = interface_offsets_count;
3410 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3411 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3412 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3413 #ifdef COMPRESSED_INTERFACE_BITMAP
3414 bitmap = g_malloc0 (bsize);
3416 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3418 for (i = 0; i < interface_offsets_count; i++) {
3419 guint32 id = interfaces_full [i]->interface_id;
3420 bitmap [id >> 3] |= (1 << (id & 7));
3421 klass->interfaces_packed [i] = interfaces_full [i];
3422 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3424 #ifdef COMPRESSED_INTERFACE_BITMAP
3425 i = mono_compress_bitmap (NULL, bitmap, bsize);
3426 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3427 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3430 klass->interface_bitmap = bitmap;
3434 mono_loader_unlock ();
3436 g_free (interfaces_full);
3437 g_free (interface_offsets_full);
3438 for (i = 0; i < klass->idepth; i++) {
3439 ifaces = ifaces_array [i];
3441 g_ptr_array_free (ifaces, TRUE);
3443 g_free (ifaces_array);
3445 //printf ("JUST DONE: ");
3446 //print_implemented_interfaces (klass);
3452 * Setup interface offsets for interfaces.
3454 * - klass->max_interface_id
3455 * - klass->interface_offsets_count
3456 * - klass->interfaces_packed
3457 * - klass->interface_offsets_packed
3458 * - klass->interface_bitmap
3460 * This function can fail @class.
3463 mono_class_setup_interface_offsets (MonoClass *klass)
3465 setup_interface_offsets (klass, 0, FALSE);
3468 /*Checks if @klass has @parent as one of it's parents type gtd
3472 * Bar<T> : Foo<Bar<Bar<T>>>
3476 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3478 klass = mono_class_get_generic_type_definition (klass);
3479 parent = mono_class_get_generic_type_definition (parent);
3480 mono_class_setup_supertypes (klass);
3481 mono_class_setup_supertypes (parent);
3483 return klass->idepth >= parent->idepth &&
3484 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3488 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3490 MonoGenericInst *ginst;
3493 if (!mono_class_is_ginst (klass)) {
3494 mono_class_setup_vtable_full (klass, in_setup);
3495 return !mono_class_has_failure (klass);
3498 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3499 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3502 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3503 for (i = 0; i < ginst->type_argc; ++i) {
3505 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3507 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3508 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3509 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3511 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3512 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3520 * mono_class_setup_vtable:
3522 * Creates the generic vtable of CLASS.
3523 * Initializes the following fields in MonoClass:
3526 * Plus all the fields initialized by setup_interface_offsets ().
3527 * If there is an error during vtable construction, klass->has_failure
3528 * is set and details are stored in a MonoErrorBoxed.
3530 * LOCKING: Acquires the loader lock.
3533 mono_class_setup_vtable (MonoClass *klass)
3535 mono_class_setup_vtable_full (klass, NULL);
3539 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3542 MonoMethod **overrides;
3543 MonoGenericContext *context;
3551 if (MONO_CLASS_IS_INTERFACE (klass)) {
3552 /* This sets method->slot for all methods if this is an interface */
3553 mono_class_setup_methods (klass);
3557 if (mono_class_has_failure (klass))
3560 if (g_list_find (in_setup, klass))
3563 mono_loader_lock ();
3565 if (klass->vtable) {
3566 mono_loader_unlock ();
3570 mono_stats.generic_vtable_count ++;
3571 in_setup = g_list_prepend (in_setup, klass);
3573 if (mono_class_is_ginst (klass)) {
3574 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3575 mono_loader_unlock ();
3576 g_list_remove (in_setup, klass);
3580 context = mono_class_get_context (klass);
3581 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3583 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3584 type_token = klass->type_token;
3587 if (image_is_dynamic (klass->image)) {
3588 /* Generic instances can have zero method overrides without causing any harm.
3589 * This is true since we don't do layout all over again for them, we simply inflate
3590 * the layout of the parent.
3592 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3593 if (!is_ok (&error)) {
3594 mono_loader_unlock ();
3595 g_list_remove (in_setup, klass);
3596 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3597 mono_error_cleanup (&error);
3601 /* The following call fails if there are missing methods in the type */
3602 /* FIXME it's probably a good idea to avoid this for generic instances. */
3603 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3607 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3609 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3613 mono_loader_unlock ();
3614 g_list_remove (in_setup, klass);
3619 #define DEBUG_INTERFACE_VTABLE_CODE 0
3620 #define TRACE_INTERFACE_VTABLE_CODE 0
3621 #define VERIFY_INTERFACE_VTABLE_CODE 0
3622 #define VTABLE_SELECTOR (1)
3624 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3625 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3626 if (!(VTABLE_SELECTOR)) break; \
3630 #define DEBUG_INTERFACE_VTABLE(stmt)
3633 #if TRACE_INTERFACE_VTABLE_CODE
3634 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3635 if (!(VTABLE_SELECTOR)) break; \
3639 #define TRACE_INTERFACE_VTABLE(stmt)
3642 #if VERIFY_INTERFACE_VTABLE_CODE
3643 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3644 if (!(VTABLE_SELECTOR)) break; \
3648 #define VERIFY_INTERFACE_VTABLE(stmt)
3652 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3654 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3658 GString *res = g_string_new ("");
3660 g_string_append_c (res, '(');
3661 for (i = 0; i < sig->param_count; ++i) {
3663 g_string_append_c (res, ',');
3664 mono_type_get_desc (res, sig->params [i], include_namespace);
3666 g_string_append (res, ")=>");
3667 if (sig->ret != NULL) {
3668 mono_type_get_desc (res, sig->ret, include_namespace);
3670 g_string_append (res, "NULL");
3673 g_string_free (res, FALSE);
3677 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3678 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3679 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3680 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3688 is_wcf_hack_disabled (void)
3690 static gboolean disabled;
3691 static gboolean inited = FALSE;
3693 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3700 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3702 MonoMethodSignature *cmsig, *imsig;
3703 if (strcmp (im->name, cm->name) == 0) {
3704 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3705 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3708 if (! slot_is_empty) {
3709 if (require_newslot) {
3710 if (! interface_is_explicitly_implemented_by_class) {
3711 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3714 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3715 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3719 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3722 cmsig = mono_method_signature (cm);
3723 imsig = mono_method_signature (im);
3724 if (!cmsig || !imsig) {
3725 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3729 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3730 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3731 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3732 TRACE_INTERFACE_VTABLE (printf ("]"));
3735 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3736 if (mono_security_core_clr_enabled ())
3737 mono_security_core_clr_check_override (klass, cm, im);
3739 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3740 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3741 char *body_name = mono_method_full_name (cm, TRUE);
3742 char *decl_name = mono_method_full_name (im, TRUE);
3743 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3751 MonoClass *ic = im->klass;
3752 const char *ic_name_space = ic->name_space;
3753 const char *ic_name = ic->name;
3756 if (! require_newslot) {
3757 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3760 if (cm->klass->rank == 0) {
3761 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3764 cmsig = mono_method_signature (cm);
3765 imsig = mono_method_signature (im);
3766 if (!cmsig || !imsig) {
3767 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3771 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3772 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3773 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3774 TRACE_INTERFACE_VTABLE (printf ("]"));
3777 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3778 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3781 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3782 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3785 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))) {
3786 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3790 subname = strstr (cm->name, ic_name_space);
3791 if (subname != cm->name) {
3792 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3795 subname += strlen (ic_name_space);
3796 if (subname [0] != '.') {
3797 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3801 if (strstr (subname, ic_name) != subname) {
3802 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3805 subname += strlen (ic_name);
3806 if (subname [0] != '.') {
3807 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3811 if (strcmp (subname, im->name) != 0) {
3812 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3816 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3817 if (mono_security_core_clr_enabled ())
3818 mono_security_core_clr_check_override (klass, cm, im);
3820 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3821 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3822 char *body_name = mono_method_full_name (cm, TRUE);
3823 char *decl_name = mono_method_full_name (im, TRUE);
3824 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3834 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3836 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3837 MonoMethod *method = key;
3838 MonoMethod *override = value;
3839 MonoClass *method_class = mono_method_get_class (method);
3840 MonoClass *override_class = mono_method_get_class (override);
3842 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3843 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3844 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3847 print_overrides (GHashTable *override_map, const char *message) {
3849 printf ("Override map \"%s\" START:\n", message);
3850 g_hash_table_foreach (override_map, foreach_override, NULL);
3851 printf ("Override map \"%s\" END.\n", message);
3853 printf ("Override map \"%s\" EMPTY.\n", message);
3857 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3858 char *full_name = mono_type_full_name (&klass->byval_arg);
3862 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3864 if (print_interfaces) {
3865 print_implemented_interfaces (klass);
3866 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3869 if (klass->parent) {
3870 parent_size = klass->parent->vtable_size;
3874 for (i = 0; i < size; ++i) {
3875 MonoMethod *cm = vtable [i];
3876 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3877 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3879 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3887 #if VERIFY_INTERFACE_VTABLE_CODE
3889 mono_method_try_get_vtable_index (MonoMethod *method)
3891 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3892 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3893 if (imethod->declaring->is_generic)
3894 return imethod->declaring->slot;
3896 return method->slot;
3900 mono_class_verify_vtable (MonoClass *klass)
3903 char *full_name = mono_type_full_name (&klass->byval_arg);
3905 printf ("*** Verifying VTable of class '%s' \n", full_name);
3909 if (!klass->methods)
3912 count = mono_class_method_count (klass);
3913 for (i = 0; i < count; ++i) {
3914 MonoMethod *cm = klass->methods [i];
3917 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3921 full_name = mono_method_full_name (cm, TRUE);
3923 slot = mono_method_try_get_vtable_index (cm);
3925 if (slot >= klass->vtable_size) {
3926 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3930 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3931 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3932 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3933 g_free (other_name);
3936 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3943 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3946 char *method_signature;
3949 for (index = 0; index < onum; ++index) {
3950 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3951 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3953 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3954 type_name = mono_type_full_name (&klass->byval_arg);
3955 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3956 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3957 g_free (method_signature);
3959 mono_class_setup_methods (klass);
3960 if (mono_class_has_failure (klass)) {
3961 char *name = mono_type_get_full_name (klass);
3962 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3966 mcount = mono_class_get_method_count (klass);
3967 for (index = 0; index < mcount; ++index) {
3968 MonoMethod *cm = klass->methods [index];
3969 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3971 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3972 g_free (method_signature);
3977 mono_method_get_method_definition (MonoMethod *method)
3979 while (method->is_inflated)
3980 method = ((MonoMethodInflated*)method)->declaring;
3985 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3989 for (i = 0; i < onum; ++i) {
3990 MonoMethod *decl = overrides [i * 2];
3991 MonoMethod *body = overrides [i * 2 + 1];
3993 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
3994 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
3998 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3999 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4000 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4002 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4006 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4007 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4008 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4010 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4014 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4015 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4019 body = mono_method_get_method_definition (body);
4020 decl = mono_method_get_method_definition (decl);
4022 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4023 char *body_name = mono_method_full_name (body, TRUE);
4024 char *decl_name = mono_method_full_name (decl, TRUE);
4025 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4035 mono_class_need_stelemref_method (MonoClass *klass)
4037 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4041 * LOCKING: this is supposed to be called with the loader lock held.
4044 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4048 MonoMethod **vtable = NULL;
4049 int i, max_vtsize = 0, cur_slot = 0;
4051 GPtrArray *ifaces = NULL;
4052 GHashTable *override_map = NULL;
4054 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4055 int first_non_interface_slot;
4057 GSList *virt_methods = NULL, *l;
4058 int stelemref_slot = 0;
4063 if (overrides && !verify_class_overrides (klass, overrides, onum))
4066 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4067 if (!mono_error_ok (&error)) {
4068 char *name = mono_type_get_full_name (klass);
4069 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4071 mono_error_cleanup (&error);
4073 } else if (ifaces) {
4074 for (i = 0; i < ifaces->len; i++) {
4075 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4076 max_vtsize += mono_class_get_method_count (ic);
4078 g_ptr_array_free (ifaces, TRUE);
4082 if (klass->parent) {
4083 mono_class_init (klass->parent);
4084 mono_class_setup_vtable_full (klass->parent, in_setup);
4086 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4089 max_vtsize += klass->parent->vtable_size;
4090 cur_slot = klass->parent->vtable_size;
4093 max_vtsize += mono_class_get_method_count (klass);
4095 /*Array have a slot for stelemref*/
4096 if (mono_class_need_stelemref_method (klass)) {
4097 stelemref_slot = cur_slot;
4102 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4104 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4105 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4108 max_iid = klass->max_interface_id;
4109 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4111 /* Optimized version for generic instances */
4112 if (mono_class_is_ginst (klass)) {
4114 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4117 mono_class_setup_vtable_full (gklass, in_setup);
4118 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4121 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4122 klass->vtable_size = gklass->vtable_size;
4123 for (i = 0; i < gklass->vtable_size; ++i)
4124 if (gklass->vtable [i]) {
4125 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4126 if (!mono_error_ok (&error)) {
4127 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4128 mono_error_cleanup (&error);
4132 tmp [i]->slot = gklass->vtable [i]->slot;
4134 mono_memory_barrier ();
4135 klass->vtable = tmp;
4137 /* Have to set method->slot for abstract virtual methods */
4138 if (klass->methods && gklass->methods) {
4139 int mcount = mono_class_get_method_count (klass);
4140 for (i = 0; i < mcount; ++i)
4141 if (klass->methods [i]->slot == -1)
4142 klass->methods [i]->slot = gklass->methods [i]->slot;
4148 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4150 if (klass->parent && klass->parent->vtable_size) {
4151 MonoClass *parent = klass->parent;
4154 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4156 // Also inherit parent interface vtables, just as a starting point.
4157 // This is needed otherwise bug-77127.exe fails when the property methods
4158 // have different names in the iterface and the class, because for child
4159 // classes the ".override" information is not used anymore.
4160 for (i = 0; i < parent->interface_offsets_count; i++) {
4161 MonoClass *parent_interface = parent->interfaces_packed [i];
4162 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4163 /*FIXME this is now dead code as this condition will never hold true.
4164 Since interface offsets are inherited then the offset of an interface implemented
4165 by a parent will never be the out of it's vtable boundary.
4167 if (interface_offset >= parent->vtable_size) {
4168 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4171 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4172 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4173 int mcount = mono_class_get_method_count (parent_interface);
4174 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4175 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4176 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4177 parent_interface_offset + j, parent_interface_offset, j,
4178 interface_offset + j, interface_offset, j));
4185 /*Array have a slot for stelemref*/
4186 if (mono_class_need_stelemref_method (klass)) {
4187 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4189 method->slot = stelemref_slot;
4191 g_assert (method->slot == stelemref_slot);
4193 vtable [stelemref_slot] = method;
4196 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4197 /* override interface methods */
4198 for (i = 0; i < onum; i++) {
4199 MonoMethod *decl = overrides [i*2];
4200 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4202 dslot = mono_method_get_vtable_slot (decl);
4204 mono_class_set_type_load_failure (klass, "");
4208 dslot += mono_class_interface_offset (klass, decl->klass);
4209 vtable [dslot] = overrides [i*2 + 1];
4210 vtable [dslot]->slot = dslot;
4212 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4214 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4216 if (mono_security_core_clr_enabled ())
4217 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4220 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4221 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4224 * Create a list of virtual methods to avoid calling
4225 * mono_class_get_virtual_methods () which is slow because of the metadata
4229 gpointer iter = NULL;
4232 virt_methods = NULL;
4233 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4234 virt_methods = g_slist_prepend (virt_methods, cm);
4236 if (mono_class_has_failure (klass))
4240 // Loop on all implemented interfaces...
4241 for (i = 0; i < klass->interface_offsets_count; i++) {
4242 MonoClass *parent = klass->parent;
4244 gboolean interface_is_explicitly_implemented_by_class;
4247 ic = klass->interfaces_packed [i];
4248 ic_offset = mono_class_interface_offset (klass, ic);
4250 mono_class_setup_methods (ic);
4251 if (mono_class_has_failure (ic))
4254 // Check if this interface is explicitly implemented (instead of just inherited)
4255 if (parent != NULL) {
4256 int implemented_interfaces_index;
4257 interface_is_explicitly_implemented_by_class = FALSE;
4258 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4259 if (ic == klass->interfaces [implemented_interfaces_index]) {
4260 interface_is_explicitly_implemented_by_class = TRUE;
4265 interface_is_explicitly_implemented_by_class = TRUE;
4268 // Loop on all interface methods...
4269 int mcount = mono_class_get_method_count (ic);
4270 for (im_index = 0; im_index < mcount; im_index++) {
4271 MonoMethod *im = ic->methods [im_index];
4272 int im_slot = ic_offset + im->slot;
4273 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4275 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4278 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4280 // If there is an explicit implementation, just use it right away,
4281 // otherwise look for a matching method
4282 if (override_im == NULL) {
4286 // First look for a suitable method among the class methods
4287 for (l = virt_methods; l; l = l->next) {
4288 cm = (MonoMethod *)l->data;
4289 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)));
4290 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4291 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4292 vtable [im_slot] = cm;
4293 /* Why do we need this? */
4298 TRACE_INTERFACE_VTABLE (printf ("\n"));
4299 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4303 // If the slot is still empty, look in all the inherited virtual methods...
4304 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4305 MonoClass *parent = klass->parent;
4306 // Reverse order, so that last added methods are preferred
4307 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4308 MonoMethod *cm = parent->vtable [cm_index];
4310 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));
4311 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4312 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4313 vtable [im_slot] = cm;
4314 /* Why do we need this? */
4320 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4322 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4326 g_assert (vtable [im_slot] == override_im);
4331 // If the class is not abstract, check that all its interface slots are full.
4332 // The check is done here and not directly at the end of the loop above because
4333 // it can happen (for injected generic array interfaces) that the same slot is
4334 // processed multiple times (those interfaces have overlapping slots), and it
4335 // will not always be the first pass the one that fills the slot.
4336 if (!mono_class_is_abstract (klass)) {
4337 for (i = 0; i < klass->interface_offsets_count; i++) {
4341 ic = klass->interfaces_packed [i];
4342 ic_offset = mono_class_interface_offset (klass, ic);
4344 int mcount = mono_class_get_method_count (ic);
4345 for (im_index = 0; im_index < mcount; im_index++) {
4346 MonoMethod *im = ic->methods [im_index];
4347 int im_slot = ic_offset + im->slot;
4349 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4352 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4353 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4354 if (vtable [im_slot] == NULL) {
4355 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4362 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4363 for (l = virt_methods; l; l = l->next) {
4364 cm = (MonoMethod *)l->data;
4366 * If the method is REUSE_SLOT, we must check in the
4367 * base class for a method to override.
4369 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4371 for (k = klass->parent; k ; k = k->parent) {
4376 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4377 MonoMethodSignature *cmsig, *m1sig;
4379 cmsig = mono_method_signature (cm);
4380 m1sig = mono_method_signature (m1);
4382 if (!cmsig || !m1sig) {
4383 /* FIXME proper error message */
4384 mono_class_set_type_load_failure (klass, "");
4388 if (!strcmp(cm->name, m1->name) &&
4389 mono_metadata_signature_equal (cmsig, m1sig)) {
4391 if (mono_security_core_clr_enabled ())
4392 mono_security_core_clr_check_override (klass, cm, m1);
4394 slot = mono_method_get_vtable_slot (m1);
4398 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4399 char *body_name = mono_method_full_name (cm, TRUE);
4400 char *decl_name = mono_method_full_name (m1, TRUE);
4401 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4407 g_assert (cm->slot < max_vtsize);
4409 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4410 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4411 mono_method_full_name (m1, 1), m1,
4412 mono_method_full_name (cm, 1), cm));
4413 g_hash_table_insert (override_map, m1, cm);
4417 if (mono_class_has_failure (k))
4427 /*Non final newslot methods must be given a non-interface vtable slot*/
4428 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4432 cm->slot = cur_slot++;
4434 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4435 vtable [cm->slot] = cm;
4438 /* override non interface methods */
4439 for (i = 0; i < onum; i++) {
4440 MonoMethod *decl = overrides [i*2];
4441 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4442 g_assert (decl->slot != -1);
4443 vtable [decl->slot] = overrides [i*2 + 1];
4444 overrides [i * 2 + 1]->slot = decl->slot;
4446 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4447 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4448 mono_method_full_name (decl, 1), decl,
4449 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4450 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4452 if (mono_security_core_clr_enabled ())
4453 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4458 * If a method occupies more than one place in the vtable, and it is
4459 * overriden, then change the other occurances too.
4464 for (i = 0; i < max_vtsize; ++i)
4466 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4468 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4473 g_hash_table_destroy (override_map);
4474 override_map = NULL;
4477 g_slist_free (virt_methods);
4478 virt_methods = NULL;
4480 g_assert (cur_slot <= max_vtsize);
4482 /* Ensure that all vtable slots are filled with concrete instance methods */
4483 if (!mono_class_is_abstract (klass)) {
4484 for (i = 0; i < cur_slot; ++i) {
4485 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4486 char *type_name = mono_type_get_full_name (klass);
4487 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4488 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4490 g_free (method_name);
4497 if (mono_class_is_ginst (klass)) {
4498 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4500 mono_class_init (gklass);
4502 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4504 /* Check that the vtable_size value computed in mono_class_init () is correct */
4505 if (klass->vtable_size)
4506 g_assert (cur_slot == klass->vtable_size);
4507 klass->vtable_size = cur_slot;
4510 /* Try to share the vtable with our parent. */
4511 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4512 mono_memory_barrier ();
4513 klass->vtable = klass->parent->vtable;
4515 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4516 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4517 mono_memory_barrier ();
4518 klass->vtable = tmp;
4521 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4522 if (mono_print_vtable) {
4525 print_implemented_interfaces (klass);
4527 for (i = 0; i <= max_iid; i++)
4528 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4531 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4532 klass->vtable_size, icount);
4534 for (i = 0; i < cur_slot; ++i) {
4539 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4540 mono_method_full_name (cm, TRUE));
4546 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4547 klass->name, max_iid);
4549 for (i = 0; i < klass->interface_count; i++) {
4550 ic = klass->interfaces [i];
4551 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4552 mono_class_interface_offset (klass, ic),
4553 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4556 for (k = klass->parent; k ; k = k->parent) {
4557 for (i = 0; i < k->interface_count; i++) {
4558 ic = k->interfaces [i];
4559 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4560 mono_class_interface_offset (klass, ic),
4561 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4569 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4574 char *name = mono_type_get_full_name (klass);
4575 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4579 g_hash_table_destroy (override_map);
4581 g_slist_free (virt_methods);
4586 * mono_method_get_vtable_slot:
4588 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4589 * LOCKING: Acquires the loader lock.
4591 * FIXME Use proper MonoError machinery here.
4594 mono_method_get_vtable_slot (MonoMethod *method)
4596 if (method->slot == -1) {
4597 mono_class_setup_vtable (method->klass);
4598 if (mono_class_has_failure (method->klass))
4600 if (method->slot == -1) {
4604 if (!mono_class_is_ginst (method->klass)) {
4605 g_assert (method->is_inflated);
4606 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4609 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4610 g_assert (mono_class_is_ginst (method->klass));
4611 gklass = mono_class_get_generic_class (method->klass)->container_class;
4612 mono_class_setup_methods (method->klass);
4613 g_assert (method->klass->methods);
4614 mcount = mono_class_get_method_count (method->klass);
4615 for (i = 0; i < mcount; ++i) {
4616 if (method->klass->methods [i] == method)
4619 g_assert (i < mcount);
4620 g_assert (gklass->methods);
4621 method->slot = gklass->methods [i]->slot;
4623 g_assert (method->slot != -1);
4625 return method->slot;
4629 * mono_method_get_vtable_index:
4630 * \param method a method
4632 * Returns the index into the runtime vtable to access the method or,
4633 * in the case of a virtual generic method, the virtual generic method
4634 * thunk. Returns -1 on failure.
4636 * FIXME Use proper MonoError machinery here.
4639 mono_method_get_vtable_index (MonoMethod *method)
4641 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4642 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4643 if (imethod->declaring->is_generic)
4644 return mono_method_get_vtable_slot (imethod->declaring);
4646 return mono_method_get_vtable_slot (method);
4649 static MonoMethod *default_ghc = NULL;
4650 static MonoMethod *default_finalize = NULL;
4651 static int finalize_slot = -1;
4652 static int ghc_slot = -1;
4655 initialize_object_slots (MonoClass *klass)
4660 if (klass == mono_defaults.object_class) {
4661 mono_class_setup_vtable (klass);
4662 for (i = 0; i < klass->vtable_size; ++i) {
4663 MonoMethod *cm = klass->vtable [i];
4665 if (!strcmp (cm->name, "GetHashCode"))
4667 else if (!strcmp (cm->name, "Finalize"))
4671 g_assert (ghc_slot > 0);
4672 default_ghc = klass->vtable [ghc_slot];
4674 g_assert (finalize_slot > 0);
4675 default_finalize = klass->vtable [finalize_slot];
4680 MonoMethod *array_method;
4682 } GenericArrayMethodInfo;
4684 static int generic_array_method_num = 0;
4685 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4688 generic_array_methods (MonoClass *klass)
4690 int i, count_generic = 0, mcount;
4691 GList *list = NULL, *tmp;
4692 if (generic_array_method_num)
4693 return generic_array_method_num;
4694 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4695 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4696 mcount = mono_class_get_method_count (klass->parent);
4697 for (i = 0; i < mcount; i++) {
4698 MonoMethod *m = klass->parent->methods [i];
4699 if (!strncmp (m->name, "InternalArray__", 15)) {
4701 list = g_list_prepend (list, m);
4704 list = g_list_reverse (list);
4705 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4707 for (tmp = list; tmp; tmp = tmp->next) {
4708 const char *mname, *iname;
4710 MonoMethod *m = (MonoMethod *)tmp->data;
4711 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4712 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4714 generic_array_method_info [i].array_method = m;
4715 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4716 iname = "System.Collections.Generic.ICollection`1.";
4717 mname = m->name + 27;
4718 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4719 iname = "System.Collections.Generic.IEnumerable`1.";
4720 mname = m->name + 27;
4721 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4722 iname = "System.Collections.Generic.IReadOnlyList`1.";
4723 mname = m->name + strlen (ireadonlylist_prefix);
4724 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4725 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4726 mname = m->name + strlen (ireadonlycollection_prefix);
4727 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4728 iname = "System.Collections.Generic.IList`1.";
4729 mname = m->name + 15;
4731 g_assert_not_reached ();
4734 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4735 strcpy (name, iname);
4736 strcpy (name + strlen (iname), mname);
4737 generic_array_method_info [i].name = name;
4740 /*g_print ("array generic methods: %d\n", count_generic);*/
4742 generic_array_method_num = count_generic;
4744 return generic_array_method_num;
4748 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4750 MonoGenericContext tmp_context;
4753 tmp_context.class_inst = NULL;
4754 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4755 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4757 for (i = 0; i < generic_array_method_num; i++) {
4759 MonoMethod *m = generic_array_method_info [i].array_method;
4760 MonoMethod *inflated, *helper;
4762 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4763 mono_error_assert_ok (&error);
4764 helper = g_hash_table_lookup (cache, inflated);
4766 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4767 g_hash_table_insert (cache, inflated, helper);
4769 methods [pos ++] = helper;
4774 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4776 int null_length = strlen ("(null)");
4777 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4778 char *s = (char *)mono_image_alloc (image, len);
4781 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4782 g_assert (result == len - 1);
4789 * \param klass: the class to initialize
4791 * Compute the instance_size, class_size and other infos that cannot be
4792 * computed at mono_class_get() time. Also compute vtable_size if possible.
4793 * Returns TRUE on success or FALSE if there was a problem in loading
4794 * the type (incorrect assemblies, missing assemblies, methods, etc).
4795 * Initializes the following fields in \param klass:
4796 * - all the fields initialized by mono_class_init_sizes ()
4801 * LOCKING: Acquires the loader lock.
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
6322 * \returns a MonoClass for the specified MonoType, the value is never NULL.
6325 mono_class_from_mono_type (MonoType *type)
6327 switch (type->type) {
6328 case MONO_TYPE_OBJECT:
6329 return type->data.klass? type->data.klass: mono_defaults.object_class;
6330 case MONO_TYPE_VOID:
6331 return type->data.klass? type->data.klass: mono_defaults.void_class;
6332 case MONO_TYPE_BOOLEAN:
6333 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6334 case MONO_TYPE_CHAR:
6335 return type->data.klass? type->data.klass: mono_defaults.char_class;
6337 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6339 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6341 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6343 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6345 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6347 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6349 return type->data.klass? type->data.klass: mono_defaults.int_class;
6351 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6353 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6355 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6357 return type->data.klass? type->data.klass: mono_defaults.single_class;
6359 return type->data.klass? type->data.klass: mono_defaults.double_class;
6360 case MONO_TYPE_STRING:
6361 return type->data.klass? type->data.klass: mono_defaults.string_class;
6362 case MONO_TYPE_TYPEDBYREF:
6363 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6364 case MONO_TYPE_ARRAY:
6365 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6367 return mono_ptr_class_get (type->data.type);
6368 case MONO_TYPE_FNPTR:
6369 return mono_fnptr_class_get (type->data.method);
6370 case MONO_TYPE_SZARRAY:
6371 return mono_array_class_get (type->data.klass, 1);
6372 case MONO_TYPE_CLASS:
6373 case MONO_TYPE_VALUETYPE:
6374 return type->data.klass;
6375 case MONO_TYPE_GENERICINST:
6376 return mono_generic_class_get_class (type->data.generic_class);
6377 case MONO_TYPE_MVAR:
6379 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6381 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6382 g_assert_not_reached ();
6385 // Yes, this returns NULL, even if it is documented as not doing so, but there
6386 // is no way for the code to make it this far, due to the assert above.
6391 * mono_type_retrieve_from_typespec
6392 * \param image context where the image is created
6393 * \param type_spec typespec token
6394 * \param context the generic context used to evaluate generic instantiations in
6397 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6399 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6401 *did_inflate = FALSE;
6406 if (context && (context->class_inst || context->method_inst)) {
6407 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6409 if (!mono_error_ok (error)) {
6415 *did_inflate = TRUE;
6422 * mono_class_create_from_typespec
6423 * \param image context where the image is created
6424 * \param type_spec typespec token
6425 * \param context the generic context used to evaluate generic instantiations in
6428 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6431 gboolean inflated = FALSE;
6432 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6433 return_val_if_nok (error, NULL);
6434 ret = mono_class_from_mono_type (t);
6436 mono_metadata_free_type (t);
6441 * mono_bounded_array_class_get:
6442 * \param element_class element class
6443 * \param rank the dimension of the array class
6444 * \param bounded whenever the array has non-zero bounds
6446 * \returns A class object describing the array with element type \p element_type and
6447 * dimension \p rank.
6450 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6453 MonoClass *klass, *cached, *k;
6454 MonoClass *parent = NULL;
6455 GSList *list, *rootlist = NULL;
6459 g_assert (rank <= 255);
6462 /* bounded only matters for one-dimensional arrays */
6465 image = eclass->image;
6469 if (rank == 1 && !bounded) {
6471 * This case is very frequent not just during compilation because of calls
6472 * from mono_class_from_mono_type (), mono_array_new (),
6473 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6475 mono_os_mutex_lock (&image->szarray_cache_lock);
6476 if (!image->szarray_cache)
6477 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6478 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6479 mono_os_mutex_unlock (&image->szarray_cache_lock);
6481 mono_loader_lock ();
6482 if (!image->array_cache)
6483 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6484 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6485 for (list = rootlist; list; list = list->next) {
6486 k = (MonoClass *)list->data;
6487 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6492 mono_loader_unlock ();
6497 parent = mono_defaults.array_class;
6498 if (!parent->inited)
6499 mono_class_init (parent);
6501 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6503 klass->image = image;
6504 klass->name_space = eclass->name_space;
6505 klass->class_kind = MONO_CLASS_ARRAY;
6507 nsize = strlen (eclass->name);
6508 name = (char *)g_malloc (nsize + 2 + rank + 1);
6509 memcpy (name, eclass->name, nsize);
6512 memset (name + nsize + 1, ',', rank - 1);
6514 name [nsize + rank] = '*';
6515 name [nsize + rank + bounded] = ']';
6516 name [nsize + rank + bounded + 1] = 0;
6517 klass->name = mono_image_strdup (image, name);
6520 klass->type_token = 0;
6521 klass->parent = parent;
6522 klass->instance_size = mono_class_instance_size (klass->parent);
6524 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6525 /*Arrays of those two types are invalid.*/
6526 MonoError prepared_error;
6527 error_init (&prepared_error);
6528 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6529 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6530 mono_error_cleanup (&prepared_error);
6531 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6532 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6533 if (!ref_info_handle || eclass->wastypebuilder) {
6534 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6535 g_assert (ref_info_handle && !eclass->wastypebuilder);
6537 /* element_size -1 is ok as this is not an instantitable type*/
6538 klass->sizes.element_size = -1;
6540 klass->sizes.element_size = mono_class_array_element_size (eclass);
6542 mono_class_setup_supertypes (klass);
6544 if (mono_class_is_ginst (eclass))
6545 mono_class_init (eclass);
6546 if (!eclass->size_inited)
6547 mono_class_setup_fields (eclass);
6548 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6549 /*FIXME we fail the array type, but we have to let other fields be set.*/
6551 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6555 if (eclass->enumtype)
6556 klass->cast_class = eclass->element_class;
6558 klass->cast_class = eclass;
6560 switch (klass->cast_class->byval_arg.type) {
6562 klass->cast_class = mono_defaults.byte_class;
6565 klass->cast_class = mono_defaults.int16_class;
6568 #if SIZEOF_VOID_P == 4
6572 klass->cast_class = mono_defaults.int32_class;
6575 #if SIZEOF_VOID_P == 8
6579 klass->cast_class = mono_defaults.int64_class;
6585 klass->element_class = eclass;
6587 if ((rank > 1) || bounded) {
6588 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6589 klass->byval_arg.type = MONO_TYPE_ARRAY;
6590 klass->byval_arg.data.array = at;
6591 at->eklass = eclass;
6593 /* FIXME: complete.... */
6595 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6596 klass->byval_arg.data.klass = eclass;
6598 klass->this_arg = klass->byval_arg;
6599 klass->this_arg.byref = 1;
6602 MonoError prepared_error;
6603 error_init (&prepared_error);
6604 name = mono_type_get_full_name (klass);
6605 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6606 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6607 mono_error_cleanup (&prepared_error);
6611 mono_loader_lock ();
6613 /* Check cache again */
6615 if (rank == 1 && !bounded) {
6616 mono_os_mutex_lock (&image->szarray_cache_lock);
6617 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6618 mono_os_mutex_unlock (&image->szarray_cache_lock);
6620 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6621 for (list = rootlist; list; list = list->next) {
6622 k = (MonoClass *)list->data;
6623 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6630 mono_loader_unlock ();
6634 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6636 classes_size += sizeof (MonoClassArray);
6637 ++class_array_count;
6639 if (rank == 1 && !bounded) {
6640 mono_os_mutex_lock (&image->szarray_cache_lock);
6641 g_hash_table_insert (image->szarray_cache, eclass, klass);
6642 mono_os_mutex_unlock (&image->szarray_cache_lock);
6644 list = g_slist_append (rootlist, klass);
6645 g_hash_table_insert (image->array_cache, eclass, list);
6648 mono_loader_unlock ();
6650 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6656 * mono_array_class_get:
6657 * \param element_class element class
6658 * \param rank the dimension of the array class
6660 * \returns A class object describing the array with element type \p element_type and
6661 * dimension \p rank.
6664 mono_array_class_get (MonoClass *eclass, guint32 rank)
6666 return mono_bounded_array_class_get (eclass, rank, FALSE);
6670 * mono_class_instance_size:
6671 * \param klass: a class
6673 * Use to get the size of a class in bytes.
6675 * \returns The size of an object instance
6678 mono_class_instance_size (MonoClass *klass)
6680 if (!klass->size_inited)
6681 mono_class_init (klass);
6683 return klass->instance_size;
6687 * mono_class_min_align:
6688 * \param klass a class
6690 * Use to get the computed minimum alignment requirements for the specified class.
6692 * Returns: minimum alignment requirements
6695 mono_class_min_align (MonoClass *klass)
6697 if (!klass->size_inited)
6698 mono_class_init (klass);
6700 return klass->min_align;
6704 * mono_class_value_size:
6705 * \param klass a class
6707 * This function is used for value types, and return the
6708 * space and the alignment to store that kind of value object.
6710 * \returns the size of a value of kind \p klass
6713 mono_class_value_size (MonoClass *klass, guint32 *align)
6717 /* fixme: check disable, because we still have external revereces to
6718 * mscorlib and Dummy Objects
6720 /*g_assert (klass->valuetype);*/
6722 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6725 *align = klass->min_align;
6731 * mono_class_data_size:
6732 * \param klass a class
6734 * \returns The size of the static class data
6737 mono_class_data_size (MonoClass *klass)
6740 mono_class_init (klass);
6741 /* This can happen with dynamically created types */
6742 if (!klass->fields_inited)
6743 mono_class_setup_fields (klass);
6745 /* in arrays, sizes.class_size is unioned with element_size
6746 * and arrays have no static fields
6750 return klass->sizes.class_size;
6754 * Auxiliary routine to mono_class_get_field
6756 * Takes a field index instead of a field token.
6758 static MonoClassField *
6759 mono_class_get_field_idx (MonoClass *klass, int idx)
6761 mono_class_setup_fields (klass);
6762 if (mono_class_has_failure (klass))
6766 int first_field_idx = mono_class_get_first_field_idx (klass);
6767 int fcount = mono_class_get_field_count (klass);
6768 if (klass->image->uncompressed_metadata) {
6770 * first_field_idx points to the FieldPtr table, while idx points into the
6771 * Field table, so we have to do a search.
6773 /*FIXME this is broken for types with multiple fields with the same name.*/
6774 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6777 for (i = 0; i < fcount; ++i)
6778 if (mono_field_get_name (&klass->fields [i]) == name)
6779 return &klass->fields [i];
6780 g_assert_not_reached ();
6783 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6784 return &klass->fields [idx - first_field_idx];
6788 klass = klass->parent;
6794 * mono_class_get_field:
6795 * \param class the class to lookup the field.
6796 * \param field_token the field token
6798 * \returns A MonoClassField representing the type and offset of
6799 * the field, or a NULL value if the field does not belong to this
6803 mono_class_get_field (MonoClass *klass, guint32 field_token)
6805 int idx = mono_metadata_token_index (field_token);
6807 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6809 return mono_class_get_field_idx (klass, idx - 1);
6813 * mono_class_get_field_from_name:
6814 * \param klass: the class to lookup the field.
6815 * \param name: the field name
6817 * Search the class \p klass and its parents for a field with the name \p name.
6819 * \returns The MonoClassField pointer of the named field or NULL
6822 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6824 return mono_class_get_field_from_name_full (klass, name, NULL);
6828 * mono_class_get_field_from_name_full:
6829 * \param klass the class to lookup the field.
6830 * \param name the field name
6831 * \param type the type of the fields. This optional.
6833 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6835 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6836 * of its generic type definition.
6838 * \returns The MonoClassField pointer of the named field or NULL
6841 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6845 mono_class_setup_fields (klass);
6846 if (mono_class_has_failure (klass))
6850 int fcount = mono_class_get_field_count (klass);
6851 for (i = 0; i < fcount; ++i) {
6852 MonoClassField *field = &klass->fields [i];
6854 if (strcmp (name, mono_field_get_name (field)) != 0)
6858 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6859 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6864 klass = klass->parent;
6870 * mono_class_get_field_token:
6871 * \param field the field we need the token of
6873 * Get the token of a field. Note that the tokesn is only valid for the image
6874 * the field was loaded from. Don't use this function for fields in dynamic types.
6876 * \returns The token representing the field in the image it was loaded from.
6879 mono_class_get_field_token (MonoClassField *field)
6881 MonoClass *klass = field->parent;
6884 mono_class_setup_fields (klass);
6889 int first_field_idx = mono_class_get_first_field_idx (klass);
6890 int fcount = mono_class_get_field_count (klass);
6891 for (i = 0; i < fcount; ++i) {
6892 if (&klass->fields [i] == field) {
6893 int idx = first_field_idx + i + 1;
6895 if (klass->image->uncompressed_metadata)
6896 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6897 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6900 klass = klass->parent;
6903 g_assert_not_reached ();
6908 mono_field_get_index (MonoClassField *field)
6910 int index = field - field->parent->fields;
6911 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6917 * mono_class_get_field_default_value:
6919 * Return the default value of the field as a pointer into the metadata blob.
6922 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6925 guint32 constant_cols [MONO_CONSTANT_SIZE];
6927 MonoClass *klass = field->parent;
6928 MonoFieldDefaultValue *def_values;
6930 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6932 def_values = mono_class_get_field_def_values (klass);
6934 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6936 mono_class_set_field_def_values (klass, def_values);
6939 field_index = mono_field_get_index (field);
6941 if (!def_values [field_index].data) {
6942 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6946 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6948 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6949 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6950 mono_memory_barrier ();
6951 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6954 *def_type = def_values [field_index].def_type;
6955 return def_values [field_index].data;
6959 mono_property_get_index (MonoProperty *prop)
6961 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6962 int index = prop - info->properties;
6964 g_assert (index >= 0 && index < info->count);
6970 * mono_class_get_property_default_value:
6972 * Return the default value of the field as a pointer into the metadata blob.
6975 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6978 guint32 constant_cols [MONO_CONSTANT_SIZE];
6979 MonoClass *klass = property->parent;
6981 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6983 * We don't cache here because it is not used by C# so it's quite rare, but
6984 * we still do the lookup in klass->ext because that is where the data
6985 * is stored for dynamic assemblies.
6988 if (image_is_dynamic (klass->image)) {
6989 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
6990 int prop_index = mono_property_get_index (property);
6991 if (info->def_values && info->def_values [prop_index].data) {
6992 *def_type = info->def_values [prop_index].def_type;
6993 return info->def_values [prop_index].data;
6997 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7001 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7002 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7003 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7007 mono_class_get_event_token (MonoEvent *event)
7009 MonoClass *klass = event->parent;
7013 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7015 for (i = 0; i < info->count; ++i) {
7016 if (&info->events [i] == event)
7017 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7020 klass = klass->parent;
7023 g_assert_not_reached ();
7028 * mono_class_get_property_from_name:
7029 * \param klass a class
7030 * \param name name of the property to lookup in the specified class
7032 * Use this method to lookup a property in a class
7033 * \returns the MonoProperty with the given name, or NULL if the property
7034 * does not exist on the \p klass.
7037 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7041 gpointer iter = NULL;
7042 while ((p = mono_class_get_properties (klass, &iter))) {
7043 if (! strcmp (name, p->name))
7046 klass = klass->parent;
7052 * mono_class_get_property_token:
7053 * \param prop MonoProperty to query
7055 * \returns The ECMA token for the specified property.
7058 mono_class_get_property_token (MonoProperty *prop)
7060 MonoClass *klass = prop->parent;
7064 gpointer iter = NULL;
7065 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7066 while ((p = mono_class_get_properties (klass, &iter))) {
7067 if (&info->properties [i] == prop)
7068 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7072 klass = klass->parent;
7075 g_assert_not_reached ();
7080 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7082 const char *name, *nspace;
7083 if (image_is_dynamic (image))
7084 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7086 switch (type_token & 0xff000000){
7087 case MONO_TOKEN_TYPE_DEF: {
7088 guint32 cols [MONO_TYPEDEF_SIZE];
7089 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7090 guint tidx = mono_metadata_token_index (type_token);
7092 if (tidx > tt->rows)
7093 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7095 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7096 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7097 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7098 if (strlen (nspace) == 0)
7099 return g_strdup_printf ("%s", name);
7101 return g_strdup_printf ("%s.%s", nspace, name);
7104 case MONO_TOKEN_TYPE_REF: {
7106 guint32 cols [MONO_TYPEREF_SIZE];
7107 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7108 guint tidx = mono_metadata_token_index (type_token);
7111 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7113 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7114 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7115 mono_error_cleanup (&error);
7119 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7120 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7121 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7122 if (strlen (nspace) == 0)
7123 return g_strdup_printf ("%s", name);
7125 return g_strdup_printf ("%s.%s", nspace, name);
7128 case MONO_TOKEN_TYPE_SPEC:
7129 return g_strdup_printf ("Typespec 0x%08x", type_token);
7131 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7136 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7138 if (image_is_dynamic (image))
7139 return g_strdup_printf ("DynamicAssembly %s", image->name);
7141 switch (type_token & 0xff000000){
7142 case MONO_TOKEN_TYPE_DEF:
7143 if (image->assembly)
7144 return mono_stringify_assembly_name (&image->assembly->aname);
7145 else if (image->assembly_name)
7146 return g_strdup (image->assembly_name);
7147 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7148 case MONO_TOKEN_TYPE_REF: {
7150 MonoAssemblyName aname;
7151 guint32 cols [MONO_TYPEREF_SIZE];
7152 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7153 guint32 idx = mono_metadata_token_index (type_token);
7156 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7158 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7159 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7160 mono_error_cleanup (&error);
7163 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7165 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7166 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7167 case MONO_RESOLUTION_SCOPE_MODULE:
7169 return g_strdup ("");
7170 case MONO_RESOLUTION_SCOPE_MODULEREF:
7172 return g_strdup ("");
7173 case MONO_RESOLUTION_SCOPE_TYPEREF:
7175 return g_strdup ("");
7176 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7177 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7178 return mono_stringify_assembly_name (&aname);
7180 g_assert_not_reached ();
7184 case MONO_TOKEN_TYPE_SPEC:
7186 return g_strdup ("");
7188 g_assert_not_reached ();
7195 * mono_class_get_full:
7196 * \param image the image where the class resides
7197 * \param type_token the token for the class
7198 * \param context the generic context used to evaluate generic instantiations in
7199 * \param deprecated Functions that expose MonoGenericContext are going away in mono 4.0
7201 * \returns The MonoClass that represents \p type_token in \p image
7204 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7208 klass = mono_class_get_checked (image, type_token, &error);
7210 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7211 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7213 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7219 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7224 klass = mono_class_get_checked (image, type_token, error);
7226 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7227 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7232 * mono_class_get_checked:
7233 * \param image the image where the class resides
7234 * \param type_token the token for the class
7235 * \param error error object to return any error
7237 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7240 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7242 MonoClass *klass = NULL;
7246 if (image_is_dynamic (image)) {
7247 int table = mono_metadata_token_table (type_token);
7249 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7250 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7253 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7257 switch (type_token & 0xff000000){
7258 case MONO_TOKEN_TYPE_DEF:
7259 klass = mono_class_create_from_typedef (image, type_token, error);
7261 case MONO_TOKEN_TYPE_REF:
7262 klass = mono_class_from_typeref_checked (image, type_token, error);
7264 case MONO_TOKEN_TYPE_SPEC:
7265 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7268 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7272 /* Generic case, should be avoided for when a better error is possible. */
7273 if (!klass && mono_error_ok (error)) {
7274 char *name = mono_class_name_from_token (image, type_token);
7275 char *assembly = mono_assembly_name_from_token (image, type_token);
7276 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7284 * mono_type_get_checked:
7285 * \param image the image where the type resides
7286 * \param type_token the token for the type
7287 * \param context the generic context used to evaluate generic instantiations in
7288 * \param error Error handling context
7290 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7292 * \returns The MonoType that represents \p type_token in \p image
7295 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7297 MonoType *type = NULL;
7298 gboolean inflated = FALSE;
7302 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7303 if (image_is_dynamic (image)) {
7304 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7305 return_val_if_nok (error, NULL);
7306 return mono_class_get_type (klass);
7309 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7310 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7317 return mono_class_get_type (klass);
7320 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7327 MonoType *tmp = type;
7328 type = mono_class_get_type (mono_class_from_mono_type (type));
7329 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7330 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7331 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7333 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7335 if (type->type != tmp->type)
7338 mono_metadata_free_type (tmp);
7345 * \param image image where the class token will be looked up.
7346 * \param type_token a type token from the image
7348 * \returns the MonoClass with the given \p type_token on the \p image
7351 mono_class_get (MonoImage *image, guint32 type_token)
7353 return mono_class_get_full (image, type_token, NULL);
7357 * mono_image_init_name_cache:
7359 * Initializes the class name cache stored in image->name_cache.
7361 * LOCKING: Acquires the corresponding image lock.
7364 mono_image_init_name_cache (MonoImage *image)
7366 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7367 guint32 cols [MONO_TYPEDEF_SIZE];
7370 guint32 i, visib, nspace_index;
7371 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7373 if (image->name_cache)
7376 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7378 if (image_is_dynamic (image)) {
7379 mono_image_lock (image);
7380 if (image->name_cache) {
7381 /* Somebody initialized it before us */
7382 g_hash_table_destroy (the_name_cache);
7384 mono_atomic_store_release (&image->name_cache, the_name_cache);
7386 mono_image_unlock (image);
7390 /* Temporary hash table to avoid lookups in the nspace_table */
7391 name_cache2 = g_hash_table_new (NULL, NULL);
7393 for (i = 1; i <= t->rows; ++i) {
7394 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7395 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7397 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7398 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7400 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7402 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7403 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7405 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7406 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7407 if (!nspace_table) {
7408 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7409 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7410 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7413 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7416 /* Load type names from EXPORTEDTYPES table */
7418 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7419 guint32 cols [MONO_EXP_TYPE_SIZE];
7422 for (i = 0; i < t->rows; ++i) {
7423 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7425 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7426 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7430 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7431 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7433 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7434 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7435 if (!nspace_table) {
7436 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7437 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7438 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7441 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7445 g_hash_table_destroy (name_cache2);
7447 mono_image_lock (image);
7448 if (image->name_cache) {
7449 /* Somebody initialized it before us */
7450 g_hash_table_destroy (the_name_cache);
7452 mono_atomic_store_release (&image->name_cache, the_name_cache);
7454 mono_image_unlock (image);
7457 /*FIXME Only dynamic assemblies should allow this operation.*/
7459 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7460 const char *name, guint32 index)
7462 GHashTable *nspace_table;
7463 GHashTable *name_cache;
7466 mono_image_init_name_cache (image);
7467 mono_image_lock (image);
7469 name_cache = image->name_cache;
7470 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7471 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7472 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7475 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7476 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7478 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7480 mono_image_unlock (image);
7489 find_nocase (gpointer key, gpointer value, gpointer user_data)
7491 char *name = (char*)key;
7492 FindUserData *data = (FindUserData*)user_data;
7494 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7495 data->value = value;
7499 * mono_class_from_name_case:
7500 * \param image The MonoImage where the type is looked up in
7501 * \param name_space the type namespace
7502 * \param name the type short name.
7503 * \deprecated use the mono_class_from_name_case_checked variant instead.
7505 * Obtains a MonoClass with a given namespace and a given name which
7506 * is located in the given MonoImage. The namespace and name
7507 * lookups are case insensitive.
7510 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7513 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7514 mono_error_cleanup (&error);
7520 * mono_class_from_name_case_checked:
7521 * \param image The MonoImage where the type is looked up in
7522 * \param name_space the type namespace
7523 * \param name the type short name.
7526 * Obtains a MonoClass with a given namespace and a given name which
7527 * is located in the given MonoImage. The namespace and name
7528 * lookups are case insensitive.
7530 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7531 * was not found. The \p error object will contain information about the problem
7535 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7537 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7538 guint32 cols [MONO_TYPEDEF_SIZE];
7545 if (image_is_dynamic (image)) {
7547 FindUserData user_data;
7549 mono_image_init_name_cache (image);
7550 mono_image_lock (image);
7552 user_data.key = name_space;
7553 user_data.value = NULL;
7554 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7556 if (user_data.value) {
7557 GHashTable *nspace_table = (GHashTable*)user_data.value;
7559 user_data.key = name;
7560 user_data.value = NULL;
7562 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7564 if (user_data.value)
7565 token = GPOINTER_TO_UINT (user_data.value);
7568 mono_image_unlock (image);
7571 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7577 /* add a cache if needed */
7578 for (i = 1; i <= t->rows; ++i) {
7579 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7580 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7582 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7583 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7585 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7587 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7588 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7589 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7590 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7596 return_nested_in (MonoClass *klass, char *nested)
7599 char *s = strchr (nested, '/');
7600 gpointer iter = NULL;
7607 while ((found = mono_class_get_nested_types (klass, &iter))) {
7608 if (strcmp (found->name, nested) == 0) {
7610 return return_nested_in (found, s);
7618 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7620 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7621 MonoImage *file_image;
7628 * The EXPORTEDTYPES table only contains public types, so have to search the
7630 * Note: image->modules contains the contents of the MODULEREF table, while
7631 * the real module list is in the FILE table.
7633 for (i = 0; i < file_table->rows; i++) {
7634 guint32 cols [MONO_FILE_SIZE];
7635 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7636 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7639 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7641 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7642 if (klass || !is_ok (error))
7651 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7653 GHashTable *nspace_table;
7654 MonoImage *loaded_image;
7663 // Checking visited images avoids stack overflows when cyclic references exist.
7664 if (g_hash_table_lookup (visited_images, image))
7667 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7669 if ((nested = strchr (name, '/'))) {
7670 int pos = nested - name;
7671 int len = strlen (name);
7674 memcpy (buf, name, len + 1);
7676 nested = buf + pos + 1;
7680 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7681 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7682 gboolean res = get_class_from_name (image, name_space, name, &klass);
7685 klass = search_modules (image, name_space, name, error);
7690 return klass ? return_nested_in (klass, nested) : NULL;
7696 mono_image_init_name_cache (image);
7697 mono_image_lock (image);
7699 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7702 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7704 mono_image_unlock (image);
7706 if (!token && image_is_dynamic (image) && image->modules) {
7707 /* Search modules as well */
7708 for (i = 0; i < image->module_count; ++i) {
7709 MonoImage *module = image->modules [i];
7711 klass = mono_class_from_name_checked (module, name_space, name, error);
7712 if (klass || !is_ok (error))
7718 klass = search_modules (image, name_space, name, error);
7719 if (klass || !is_ok (error))
7724 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7725 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7726 guint32 cols [MONO_EXP_TYPE_SIZE];
7729 idx = mono_metadata_token_index (token);
7731 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7733 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7734 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7735 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7738 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7740 return klass ? return_nested_in (klass, nested) : NULL;
7742 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7743 guint32 assembly_idx;
7745 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7747 mono_assembly_load_reference (image, assembly_idx - 1);
7748 g_assert (image->references [assembly_idx - 1]);
7749 if (image->references [assembly_idx - 1] == (gpointer)-1)
7751 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7753 return klass ? return_nested_in (klass, nested) : NULL;
7756 g_assert_not_reached ();
7760 token = MONO_TOKEN_TYPE_DEF | token;
7762 klass = mono_class_get_checked (image, token, error);
7764 return return_nested_in (klass, nested);
7769 * mono_class_from_name_checked:
7770 * \param image The MonoImage where the type is looked up in
7771 * \param name_space the type namespace
7772 * \param name the type short name.
7774 * Obtains a MonoClass with a given namespace and a given name which
7775 * is located in the given MonoImage.
7777 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7778 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7781 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7784 GHashTable *visited_images;
7786 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7788 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7790 g_hash_table_destroy (visited_images);
7796 * mono_class_from_name:
7797 * \param image The MonoImage where the type is looked up in
7798 * \param name_space the type namespace
7799 * \param name the type short name.
7801 * Obtains a MonoClass with a given namespace and a given name which
7802 * is located in the given MonoImage.
7804 * To reference nested classes, use the "/" character as a separator.
7805 * For example use "Foo/Bar" to reference the class Bar that is nested
7806 * inside Foo, like this: "class Foo { class Bar {} }".
7809 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7814 klass = mono_class_from_name_checked (image, name_space, name, &error);
7815 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7821 * mono_class_load_from_name:
7822 * \param image The MonoImage where the type is looked up in
7823 * \param name_space the type namespace
7824 * \param name the type short name.
7826 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7827 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7828 * If they are missing. Thing of System.Object or System.String.
7831 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7836 klass = mono_class_from_name_checked (image, name_space, name, &error);
7838 g_error ("Runtime critical type %s.%s not found", name_space, name);
7839 if (!mono_error_ok (&error))
7840 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7845 * mono_class_try_load_from_name:
7846 * \param image The MonoImage where the type is looked up in
7847 * \param name_space the type namespace
7848 * \param name the type short name.
7850 * This function tries to load a type, returning the class was found or NULL otherwise.
7851 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7853 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7854 * a type that we would otherwise assume to be available but was not due some error.
7858 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7863 klass = mono_class_from_name_checked (image, name_space, name, &error);
7864 if (!mono_error_ok (&error))
7865 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7871 * mono_class_is_subclass_of:
7872 * \param klass class to probe if it is a subclass of another one
7873 * \param klassc the class we suspect is the base class
7874 * \param check_interfaces whether we should perform interface checks
7876 * This method determines whether \p klass is a subclass of \p klassc.
7878 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7879 * this method return TRUE if the \p klass implements the interface or
7880 * if \p klass is an interface, if one of its base classes is \p klass.
7882 * If \p check_interfaces is false then, then if \p klass is not an interface
7883 * then it returns TRUE if the \p klass is a subclass of \p klassc.
7885 * if \p klass is an interface and \p klassc is System.Object, then this function
7890 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7891 gboolean check_interfaces)
7893 /* FIXME test for interfaces with variant generic arguments */
7894 mono_class_init (klass);
7895 mono_class_init (klassc);
7897 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7898 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7900 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7903 for (i = 0; i < klass->interface_count; i ++) {
7904 MonoClass *ic = klass->interfaces [i];
7909 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7914 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7917 if (klassc == mono_defaults.object_class)
7924 mono_type_is_generic_argument (MonoType *type)
7926 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7930 mono_class_has_variant_generic_params (MonoClass *klass)
7933 MonoGenericContainer *container;
7935 if (!mono_class_is_ginst (klass))
7938 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7940 for (i = 0; i < container->type_argc; ++i)
7941 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7948 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7950 if (target == candidate)
7953 if (check_for_reference_conv &&
7954 mono_type_is_generic_argument (&target->byval_arg) &&
7955 mono_type_is_generic_argument (&candidate->byval_arg)) {
7956 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7957 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7959 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7962 if (!mono_class_is_assignable_from (target, candidate))
7968 * @container the generic container from the GTD
7969 * @klass: the class to be assigned to
7970 * @oklass: the source class
7972 * Both @klass and @oklass must be instances of the same generic interface.
7974 * Returns: TRUE if @klass can be assigned to a @klass variable
7977 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7980 MonoType **klass_argv, **oklass_argv;
7981 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7982 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
7984 if (klass == oklass)
7987 /*Viable candidates are instances of the same generic interface*/
7988 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7991 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
7992 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
7994 for (j = 0; j < container->type_argc; ++j) {
7995 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7996 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7998 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8002 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8003 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8005 if (param1_class != param2_class) {
8006 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8007 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8009 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8010 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8020 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8022 MonoGenericParam *gparam, *ogparam;
8023 MonoGenericParamInfo *tinfo, *cinfo;
8024 MonoClass **candidate_class;
8025 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8028 if (target == candidate)
8030 if (target->byval_arg.type != candidate->byval_arg.type)
8033 gparam = target->byval_arg.data.generic_param;
8034 ogparam = candidate->byval_arg.data.generic_param;
8035 tinfo = mono_generic_param_info (gparam);
8036 cinfo = mono_generic_param_info (ogparam);
8038 class_constraint_satisfied = FALSE;
8039 valuetype_constraint_satisfied = FALSE;
8041 /*candidate must have a super set of target's special constraints*/
8042 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8043 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8045 if (cinfo->constraints) {
8046 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8047 MonoClass *cc = *candidate_class;
8049 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8050 class_constraint_satisfied = TRUE;
8051 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8052 valuetype_constraint_satisfied = TRUE;
8055 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8056 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8058 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8060 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8062 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8063 valuetype_constraint_satisfied)) {
8068 /*candidate type constraints must be a superset of target's*/
8069 if (tinfo->constraints) {
8070 MonoClass **target_class;
8071 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8072 MonoClass *tc = *target_class;
8075 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8076 * check it's constraints since it satisfy the constraint by itself.
8078 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8081 if (!cinfo->constraints)
8084 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8085 MonoClass *cc = *candidate_class;
8087 if (mono_class_is_assignable_from (tc, cc))
8091 * This happens when we have the following:
8093 * Bar<K> where K : IFace
8094 * Foo<T, U> where T : U where U : IFace
8096 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8099 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8100 if (mono_gparam_is_assignable_from (target, cc))
8104 if (!*candidate_class)
8109 /*candidate itself must have a constraint that satisfy target*/
8110 if (cinfo->constraints) {
8111 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8112 MonoClass *cc = *candidate_class;
8113 if (mono_class_is_assignable_from (target, cc))
8121 * mono_class_is_assignable_from:
8122 * \param klass the class to be assigned to
8123 * \param oklass the source class
8125 * \returns TRUE if an instance of object oklass can be assigned to an
8126 * instance of object \p klass
8129 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8132 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8134 mono_class_init (klass);
8136 if (!oklass->inited)
8137 mono_class_init (oklass);
8139 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8142 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8143 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8145 return mono_gparam_is_assignable_from (klass, oklass);
8148 if (MONO_CLASS_IS_INTERFACE (klass)) {
8149 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8150 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8151 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8155 for (i = 0; constraints [i]; ++i) {
8156 if (mono_class_is_assignable_from (klass, constraints [i]))
8164 /* interface_offsets might not be set for dynamic classes */
8165 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8167 * oklass might be a generic type parameter but they have
8168 * interface_offsets set.
8170 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8171 if (!is_ok (&error)) {
8172 mono_error_cleanup (&error);
8177 if (!oklass->interface_bitmap)
8178 /* Happens with generic instances of not-yet created dynamic types */
8180 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8183 if (klass->is_array_special_interface && oklass->rank == 1) {
8184 //XXX we could offset this by having the cast target computed at JIT time
8185 //XXX we could go even further and emit a wrapper that would do the extra type check
8186 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8187 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8189 // 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
8190 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8191 if (iface_klass->valuetype)
8192 iface_klass = iface_klass->cast_class;
8194 //array covariant casts only operates on scalar to scalar
8195 //This is so int[] can't be casted to IComparable<int>[]
8196 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8200 if (mono_class_has_variant_generic_params (klass)) {
8202 mono_class_setup_interfaces (oklass, &error);
8203 if (!mono_error_ok (&error)) {
8204 mono_error_cleanup (&error);
8208 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8209 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8210 MonoClass *iface = oklass->interfaces_packed [i];
8212 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8217 } else if (klass->delegate) {
8218 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8220 }else if (klass->rank) {
8221 MonoClass *eclass, *eoclass;
8223 if (oklass->rank != klass->rank)
8226 /* vectors vs. one dimensional arrays */
8227 if (oklass->byval_arg.type != klass->byval_arg.type)
8230 eclass = klass->cast_class;
8231 eoclass = oklass->cast_class;
8234 * a is b does not imply a[] is b[] when a is a valuetype, and
8235 * b is a reference type.
8238 if (eoclass->valuetype) {
8239 if ((eclass == mono_defaults.enum_class) ||
8240 (eclass == mono_defaults.enum_class->parent) ||
8241 (eclass == mono_defaults.object_class))
8245 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8246 } else if (mono_class_is_nullable (klass)) {
8247 if (mono_class_is_nullable (oklass))
8248 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8250 return mono_class_is_assignable_from (klass->cast_class, oklass);
8251 } else if (klass == mono_defaults.object_class)
8254 return mono_class_has_parent (oklass, klass);
8257 /*Check if @oklass is variant compatible with @klass.*/
8259 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8262 MonoType **klass_argv, **oklass_argv;
8263 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8264 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8266 /*Viable candidates are instances of the same generic interface*/
8267 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8270 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8271 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8273 for (j = 0; j < container->type_argc; ++j) {
8274 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8275 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8277 if (param1_class->valuetype != param2_class->valuetype)
8281 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8282 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8284 if (param1_class != param2_class) {
8285 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8286 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8288 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8289 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8297 /*Check if @candidate implements the interface @target*/
8299 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8303 gboolean is_variant = mono_class_has_variant_generic_params (target);
8305 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8306 if (mono_class_is_variant_compatible_slow (target, candidate))
8311 if (candidate == target)
8314 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8315 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8316 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8318 if (tb && tb->interfaces) {
8319 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8320 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8321 MonoClass *iface_class;
8323 /* we can't realize the type here since it can do pretty much anything. */
8326 iface_class = mono_class_from_mono_type (iface->type);
8327 if (iface_class == target)
8329 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8331 if (mono_class_implement_interface_slow (target, iface_class))
8336 /*setup_interfaces don't mono_class_init anything*/
8337 /*FIXME this doesn't handle primitive type arrays.
8338 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8339 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8341 mono_class_setup_interfaces (candidate, &error);
8342 if (!mono_error_ok (&error)) {
8343 mono_error_cleanup (&error);
8347 for (i = 0; i < candidate->interface_count; ++i) {
8348 if (candidate->interfaces [i] == target)
8351 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8354 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8358 candidate = candidate->parent;
8359 } while (candidate);
8365 * Check if @oklass can be assigned to @klass.
8366 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8369 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8371 if (candidate == target)
8373 if (target == mono_defaults.object_class)
8376 if (mono_class_has_parent (candidate, target))
8379 /*If target is not an interface there is no need to check them.*/
8380 if (MONO_CLASS_IS_INTERFACE (target))
8381 return mono_class_implement_interface_slow (target, candidate);
8383 if (target->delegate && mono_class_has_variant_generic_params (target))
8384 return mono_class_is_variant_compatible (target, candidate, FALSE);
8387 MonoClass *eclass, *eoclass;
8389 if (target->rank != candidate->rank)
8392 /* vectors vs. one dimensional arrays */
8393 if (target->byval_arg.type != candidate->byval_arg.type)
8396 eclass = target->cast_class;
8397 eoclass = candidate->cast_class;
8400 * a is b does not imply a[] is b[] when a is a valuetype, and
8401 * b is a reference type.
8404 if (eoclass->valuetype) {
8405 if ((eclass == mono_defaults.enum_class) ||
8406 (eclass == mono_defaults.enum_class->parent) ||
8407 (eclass == mono_defaults.object_class))
8411 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8413 /*FIXME properly handle nullables */
8414 /*FIXME properly handle (M)VAR */
8419 * mono_class_get_cctor:
8420 * \param klass A MonoClass pointer
8422 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8425 mono_class_get_cctor (MonoClass *klass)
8427 MonoCachedClassInfo cached_info;
8429 if (image_is_dynamic (klass->image)) {
8431 * has_cctor is not set for these classes because mono_class_init () is
8434 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8437 mono_class_init (klass);
8439 if (!klass->has_cctor)
8442 if (mono_class_is_ginst (klass) && !klass->methods)
8443 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8445 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8447 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8448 if (!mono_error_ok (&error))
8449 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8453 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8457 * mono_class_get_finalizer:
8458 * \param klass: The MonoClass pointer
8460 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8463 mono_class_get_finalizer (MonoClass *klass)
8465 MonoCachedClassInfo cached_info;
8468 mono_class_init (klass);
8469 if (!mono_class_has_finalizer (klass))
8472 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8474 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8475 if (!mono_error_ok (&error))
8476 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8479 mono_class_setup_vtable (klass);
8480 return klass->vtable [finalize_slot];
8485 * mono_class_needs_cctor_run:
8486 * \param klass the MonoClass pointer
8487 * \param caller a MonoMethod describing the caller
8489 * Determines whenever the class has a static constructor and whenever it
8490 * needs to be called when executing CALLER.
8493 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8497 method = mono_class_get_cctor (klass);
8499 return (method == caller) ? FALSE : TRUE;
8505 * mono_class_array_element_size:
8508 * \returns The number of bytes an element of type \p klass
8509 * uses when stored into an array.
8512 mono_class_array_element_size (MonoClass *klass)
8514 MonoType *type = &klass->byval_arg;
8517 switch (type->type) {
8520 case MONO_TYPE_BOOLEAN:
8524 case MONO_TYPE_CHAR:
8533 case MONO_TYPE_CLASS:
8534 case MONO_TYPE_STRING:
8535 case MONO_TYPE_OBJECT:
8536 case MONO_TYPE_SZARRAY:
8537 case MONO_TYPE_ARRAY:
8538 return sizeof (gpointer);
8543 case MONO_TYPE_VALUETYPE:
8544 if (type->data.klass->enumtype) {
8545 type = mono_class_enum_basetype (type->data.klass);
8546 klass = klass->element_class;
8549 return mono_class_instance_size (klass) - sizeof (MonoObject);
8550 case MONO_TYPE_GENERICINST:
8551 type = &type->data.generic_class->container_class->byval_arg;
8554 case MONO_TYPE_MVAR: {
8557 return mono_type_size (type, &align);
8559 case MONO_TYPE_VOID:
8563 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8569 * mono_array_element_size:
8570 * \param ac pointer to a \c MonoArrayClass
8572 * \returns The size of single array element.
8575 mono_array_element_size (MonoClass *ac)
8577 g_assert (ac->rank);
8578 return ac->sizes.element_size;
8582 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8583 MonoGenericContext *context)
8586 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8587 g_assert (mono_error_ok (&error));
8592 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8593 MonoGenericContext *context, MonoError *error)
8597 if (image_is_dynamic (image)) {
8598 MonoClass *tmp_handle_class;
8599 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8601 mono_error_assert_ok (error);
8602 g_assert (tmp_handle_class);
8604 *handle_class = tmp_handle_class;
8606 if (tmp_handle_class == mono_defaults.typehandle_class)
8607 return &((MonoClass*)obj)->byval_arg;
8612 switch (token & 0xff000000) {
8613 case MONO_TOKEN_TYPE_DEF:
8614 case MONO_TOKEN_TYPE_REF:
8615 case MONO_TOKEN_TYPE_SPEC: {
8618 *handle_class = mono_defaults.typehandle_class;
8619 type = mono_type_get_checked (image, token, context, error);
8623 mono_class_init (mono_class_from_mono_type (type));
8624 /* We return a MonoType* as handle */
8627 case MONO_TOKEN_FIELD_DEF: {
8629 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8631 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8635 *handle_class = mono_defaults.fieldhandle_class;
8636 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8640 mono_class_init (klass);
8641 return mono_class_get_field (klass, token);
8643 case MONO_TOKEN_METHOD_DEF:
8644 case MONO_TOKEN_METHOD_SPEC: {
8646 meth = mono_get_method_checked (image, token, NULL, context, error);
8648 *handle_class = mono_defaults.methodhandle_class;
8654 case MONO_TOKEN_MEMBER_REF: {
8655 guint32 cols [MONO_MEMBERREF_SIZE];
8657 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8658 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8659 mono_metadata_decode_blob_size (sig, &sig);
8660 if (*sig == 0x6) { /* it's a field */
8662 MonoClassField *field;
8663 field = mono_field_from_token_checked (image, token, &klass, context, error);
8665 *handle_class = mono_defaults.fieldhandle_class;
8669 meth = mono_get_method_checked (image, token, NULL, context, error);
8671 *handle_class = mono_defaults.methodhandle_class;
8676 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8682 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8684 MonoClass *handle_class;
8686 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8690 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8692 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8695 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8698 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8700 get_cached_class_info = func;
8704 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8706 if (!get_cached_class_info)
8709 return get_cached_class_info (klass, res);
8713 mono_install_get_class_from_name (MonoGetClassFromName func)
8715 get_class_from_name = func;
8719 * mono_class_get_image:
8721 * Use this method to get the \c MonoImage* where this class came from.
8723 * \returns The image where this class is defined.
8726 mono_class_get_image (MonoClass *klass)
8728 return klass->image;
8732 * mono_class_get_element_class:
8733 * \param klass the MonoClass to act on
8735 * Use this function to get the element class of an array.
8737 * \returns The element class of an array.
8740 mono_class_get_element_class (MonoClass *klass)
8742 return klass->element_class;
8746 * mono_class_is_valuetype:
8747 * \param klass the \c MonoClass to act on
8749 * Use this method to determine if the provided \c MonoClass* represents a value type,
8750 * or a reference type.
8752 * \returns TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8755 mono_class_is_valuetype (MonoClass *klass)
8757 return klass->valuetype;
8761 * mono_class_is_enum:
8762 * \param klass the \c MonoClass to act on
8764 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8766 * \returns TRUE if the \c MonoClass represents an enumeration.
8769 mono_class_is_enum (MonoClass *klass)
8771 return klass->enumtype;
8775 * mono_class_enum_basetype:
8776 * \param klass: the \c MonoClass to act on
8778 * Use this function to get the underlying type for an enumeration value.
8780 * \returns The underlying type representation for an enumeration.
8783 mono_class_enum_basetype (MonoClass *klass)
8785 if (klass->element_class == klass)
8786 /* SRE or broken types */
8789 return &klass->element_class->byval_arg;
8793 * mono_class_get_parent
8794 * \param klass the \c MonoClass to act on
8796 * \returns The parent class for this class.
8799 mono_class_get_parent (MonoClass *klass)
8801 return klass->parent;
8805 * mono_class_get_nesting_type:
8806 * \param klass the \c MonoClass to act on
8808 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8810 * If the return is NULL, this indicates that this class is not nested.
8812 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8815 mono_class_get_nesting_type (MonoClass *klass)
8817 return klass->nested_in;
8821 * mono_class_get_rank:
8822 * \param klass the MonoClass to act on
8824 * \returns The rank for the array (the number of dimensions).
8827 mono_class_get_rank (MonoClass *klass)
8833 * mono_class_get_name
8834 * \param klass the \c MonoClass to act on
8836 * \returns The name of the class.
8839 mono_class_get_name (MonoClass *klass)
8845 * mono_class_get_namespace:
8846 * \param klass the \c MonoClass to act on
8848 * \returns The namespace of the class.
8851 mono_class_get_namespace (MonoClass *klass)
8853 return klass->name_space;
8857 * mono_class_get_type:
8858 * \param klass the \c MonoClass to act on
8860 * This method returns the internal Type representation for the class.
8862 * \returns The \c MonoType from the class.
8865 mono_class_get_type (MonoClass *klass)
8867 return &klass->byval_arg;
8871 * mono_class_get_type_token:
8872 * \param klass the \c MonoClass to act on
8874 * This method returns type token for the class.
8876 * \returns The type token for the class.
8879 mono_class_get_type_token (MonoClass *klass)
8881 return klass->type_token;
8885 * mono_class_get_byref_type:
8886 * \param klass the \c MonoClass to act on
8891 mono_class_get_byref_type (MonoClass *klass)
8893 return &klass->this_arg;
8897 * mono_class_num_fields:
8898 * \param klass the \c MonoClass to act on
8900 * \returns The number of static and instance fields in the class.
8903 mono_class_num_fields (MonoClass *klass)
8905 return mono_class_get_field_count (klass);
8909 * mono_class_num_methods:
8910 * \param klass the \c MonoClass to act on
8912 * \returns The number of methods in the class.
8915 mono_class_num_methods (MonoClass *klass)
8917 return mono_class_get_method_count (klass);
8921 * mono_class_num_properties
8922 * \param klass the \c MonoClass to act on
8924 * \returns The number of properties in the class.
8927 mono_class_num_properties (MonoClass *klass)
8929 mono_class_setup_properties (klass);
8931 return mono_class_get_property_info (klass)->count;
8935 * mono_class_num_events:
8936 * \param klass the \c MonoClass to act on
8938 * \returns The number of events in the class.
8941 mono_class_num_events (MonoClass *klass)
8943 mono_class_setup_events (klass);
8945 return mono_class_get_event_info (klass)->count;
8949 * mono_class_get_fields:
8950 * \param klass the \c MonoClass to act on
8952 * This routine is an iterator routine for retrieving the fields in a class.
8954 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8955 * iterate over all of the elements. When no more values are
8956 * available, the return value is NULL.
8958 * Returns: a \c MonoClassField* on each iteration, or NULL when no more fields are available.
8961 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8963 MonoClassField* field;
8967 mono_class_setup_fields (klass);
8968 if (mono_class_has_failure (klass))
8970 /* start from the first */
8971 if (mono_class_get_field_count (klass)) {
8972 *iter = &klass->fields [0];
8973 return &klass->fields [0];
8979 field = (MonoClassField *)*iter;
8981 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
8989 * mono_class_get_methods
8990 * \param klass the \c MonoClass to act on
8992 * This routine is an iterator routine for retrieving the fields in a class.
8994 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8995 * iterate over all of the elements. When no more values are
8996 * available, the return value is NULL.
8998 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9001 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9003 MonoMethod** method;
9007 mono_class_setup_methods (klass);
9010 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9011 * FIXME we should better report this error to the caller
9013 if (!klass->methods)
9015 /* start from the first */
9016 if (mono_class_get_method_count (klass)) {
9017 *iter = &klass->methods [0];
9018 return klass->methods [0];
9024 method = (MonoMethod **)*iter;
9026 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9034 * mono_class_get_virtual_methods:
9036 * Iterate over the virtual methods of KLASS.
9038 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9041 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9043 MonoMethod** method;
9046 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9048 mono_class_setup_methods (klass);
9050 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9051 * FIXME we should better report this error to the caller
9053 if (!klass->methods)
9055 /* start from the first */
9056 method = &klass->methods [0];
9058 method = (MonoMethod **)*iter;
9061 int mcount = mono_class_get_method_count (klass);
9062 while (method < &klass->methods [mcount]) {
9063 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9067 if (method < &klass->methods [mcount]) {
9074 /* Search directly in metadata to avoid calling setup_methods () */
9075 MonoMethod *res = NULL;
9081 start_index = GPOINTER_TO_UINT (*iter);
9084 int first_idx = mono_class_get_first_method_idx (klass);
9085 int mcount = mono_class_get_method_count (klass);
9086 for (i = start_index; i < mcount; ++i) {
9089 /* first_idx points into the methodptr table */
9090 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9092 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9098 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9099 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9101 /* Add 1 here so the if (*iter) check fails */
9102 *iter = GUINT_TO_POINTER (i + 1);
9111 * mono_class_get_properties:
9112 * \param klass the \c MonoClass to act on
9114 * This routine is an iterator routine for retrieving the properties in a class.
9116 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9117 * iterate over all of the elements. When no more values are
9118 * available, the return value is NULL.
9120 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9123 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9125 MonoProperty* property;
9129 mono_class_setup_properties (klass);
9130 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9131 /* start from the first */
9133 *iter = &info->properties [0];
9134 return (MonoProperty *)*iter;
9140 property = (MonoProperty *)*iter;
9142 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9143 if (property < &info->properties [info->count]) {
9145 return (MonoProperty *)*iter;
9151 * mono_class_get_events:
9152 * \param klass the \c MonoClass to act on
9154 * This routine is an iterator routine for retrieving the properties in a class.
9156 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9157 * iterate over all of the elements. When no more values are
9158 * available, the return value is NULL.
9160 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9163 mono_class_get_events (MonoClass* klass, gpointer *iter)
9169 mono_class_setup_events (klass);
9170 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9171 /* start from the first */
9173 *iter = &info->events [0];
9174 return (MonoEvent *)*iter;
9180 event = (MonoEvent *)*iter;
9182 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9183 if (event < &info->events [info->count]) {
9185 return (MonoEvent *)*iter;
9191 * mono_class_get_interfaces
9192 * \param klass the \c MonoClass to act on
9194 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9196 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9197 * iterate over all of the elements. When no more values are
9198 * available, the return value is NULL.
9200 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9203 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9211 mono_class_init (klass);
9212 if (!klass->interfaces_inited) {
9213 mono_class_setup_interfaces (klass, &error);
9214 if (!mono_error_ok (&error)) {
9215 mono_error_cleanup (&error);
9219 /* start from the first */
9220 if (klass->interface_count) {
9221 *iter = &klass->interfaces [0];
9222 return klass->interfaces [0];
9228 iface = (MonoClass **)*iter;
9230 if (iface < &klass->interfaces [klass->interface_count]) {
9238 setup_nested_types (MonoClass *klass)
9241 GList *classes, *nested_classes, *l;
9244 if (klass->nested_classes_inited)
9247 if (!klass->type_token) {
9248 mono_loader_lock ();
9249 klass->nested_classes_inited = TRUE;
9250 mono_loader_unlock ();
9254 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9258 guint32 cols [MONO_NESTED_CLASS_SIZE];
9259 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9260 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9261 if (!mono_error_ok (&error)) {
9262 /*FIXME don't swallow the error message*/
9263 mono_error_cleanup (&error);
9265 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9269 classes = g_list_prepend (classes, nclass);
9271 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9274 nested_classes = NULL;
9275 for (l = classes; l; l = l->next)
9276 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9277 g_list_free (classes);
9279 mono_loader_lock ();
9280 if (!klass->nested_classes_inited) {
9281 mono_class_set_nested_classes_property (klass, nested_classes);
9282 mono_memory_barrier ();
9283 klass->nested_classes_inited = TRUE;
9285 mono_loader_unlock ();
9289 * mono_class_get_nested_types
9290 * \param klass the \c MonoClass to act on
9292 * This routine is an iterator routine for retrieving the nested types of a class.
9293 * This works only if \p klass is non-generic, or a generic type definition.
9295 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9296 * iterate over all of the elements. When no more values are
9297 * available, the return value is NULL.
9299 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9302 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9308 if (!klass->nested_classes_inited)
9309 setup_nested_types (klass);
9312 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9313 /* start from the first */
9314 if (nested_classes) {
9315 *iter = nested_classes;
9316 return (MonoClass *)nested_classes->data;
9318 /* no nested types */
9322 item = (GList *)*iter;
9326 return (MonoClass *)item->data;
9333 * mono_class_is_delegate
9334 * \param klass the \c MonoClass to act on
9336 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9339 mono_class_is_delegate (MonoClass *klass)
9341 return klass->delegate;
9345 * mono_class_implements_interface
9346 * \param klass The MonoClass to act on
9347 * \param interface The interface to check if \p klass implements.
9349 * \returns TRUE if \p klass implements \p interface.
9352 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9354 return mono_class_is_assignable_from (iface, klass);
9358 * mono_field_get_name:
9359 * \param field the \c MonoClassField to act on
9361 * \returns The name of the field.
9364 mono_field_get_name (MonoClassField *field)
9370 * mono_field_get_type:
9371 * \param field the \c MonoClassField to act on
9373 * \returns \c MonoType of the field.
9376 mono_field_get_type (MonoClassField *field)
9379 MonoType *type = mono_field_get_type_checked (field, &error);
9380 if (!mono_error_ok (&error)) {
9381 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9382 mono_error_cleanup (&error);
9389 * mono_field_get_type_checked:
9390 * \param field the \c MonoClassField to act on
9391 * \param error used to return any error found while retrieving \p field type
9393 * \returns \c MonoType of the field.
9396 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9400 mono_field_resolve_type (field, error);
9405 * mono_field_get_parent:
9406 * \param field the \c MonoClassField to act on
9408 * \returns \c MonoClass where the field was defined.
9411 mono_field_get_parent (MonoClassField *field)
9413 return field->parent;
9417 * mono_field_get_flags;
9418 * @field: the MonoClassField to act on
9420 * The metadata flags for a field are encoded using the
9421 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9423 * Returns: The flags for the field.
9426 mono_field_get_flags (MonoClassField *field)
9429 return mono_field_resolve_flags (field);
9430 return field->type->attrs;
9434 * mono_field_get_offset:
9435 * \param field the \c MonoClassField to act on
9437 * \returns The field offset.
9440 mono_field_get_offset (MonoClassField *field)
9442 return field->offset;
9446 mono_field_get_rva (MonoClassField *field)
9450 MonoClass *klass = field->parent;
9451 MonoFieldDefaultValue *def_values;
9453 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9455 def_values = mono_class_get_field_def_values (klass);
9457 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9459 mono_class_set_field_def_values (klass, def_values);
9462 field_index = mono_field_get_index (field);
9464 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9465 int first_field_idx = mono_class_get_first_field_idx (klass);
9466 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9468 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9469 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9472 return def_values [field_index].data;
9476 * mono_field_get_data:
9477 * \param field the \c MonoClassField to act on
9479 * \returns A pointer to the metadata constant value or to the field
9480 * data if it has an RVA flag.
9483 mono_field_get_data (MonoClassField *field)
9485 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9486 MonoTypeEnum def_type;
9488 return mono_class_get_field_default_value (field, &def_type);
9489 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9490 return mono_field_get_rva (field);
9497 * mono_property_get_name:
9498 * @prop: the MonoProperty to act on
9500 * Returns: The name of the property
9503 mono_property_get_name (MonoProperty *prop)
9509 * mono_property_get_set_method
9510 * \param prop the \c MonoProperty to act on.
9512 * \returns The setter method of the property (A MonoMethod)
9515 mono_property_get_set_method (MonoProperty *prop)
9521 * mono_property_get_get_method
9522 * \param prop the MonoProperty to act on.
9524 * \returns The setter method of the property (A \c MonoMethod)
9527 mono_property_get_get_method (MonoProperty *prop)
9533 * mono_property_get_parent:
9534 * \param prop the MonoProperty to act on.
9536 * \returns The \c MonoClass where the property was defined.
9539 mono_property_get_parent (MonoProperty *prop)
9541 return prop->parent;
9545 * mono_property_get_flags:
9546 * \param prop the \c MonoProperty to act on.
9548 * The metadata flags for a property are encoded using the
9549 * \c PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9551 * \returns The flags for the property.
9554 mono_property_get_flags (MonoProperty *prop)
9560 * mono_event_get_name:
9561 * \param event the MonoEvent to act on
9563 * \returns The name of the event.
9566 mono_event_get_name (MonoEvent *event)
9572 * mono_event_get_add_method:
9573 * \param event The \c MonoEvent to act on.
9575 * \returns The \c add method for the event (a \c MonoMethod).
9578 mono_event_get_add_method (MonoEvent *event)
9584 * mono_event_get_remove_method:
9585 * \param event The \c MonoEvent to act on.
9587 * \returns The \c remove method for the event (a \c MonoMethod).
9590 mono_event_get_remove_method (MonoEvent *event)
9592 return event->remove;
9596 * mono_event_get_raise_method:
9597 * \param event The \c MonoEvent to act on.
9599 * \returns The \c raise method for the event (a \c MonoMethod).
9602 mono_event_get_raise_method (MonoEvent *event)
9604 return event->raise;
9608 * mono_event_get_parent:
9609 * @event: the MonoEvent to act on.
9611 * Returns: The MonoClass where the event is defined.
9614 mono_event_get_parent (MonoEvent *event)
9616 return event->parent;
9620 * mono_event_get_flags
9621 * @event: the MonoEvent to act on.
9623 * The metadata flags for an event are encoded using the
9624 * EVENT_* constants. See the tabledefs.h file for details.
9626 * Returns: The flags for the event.
9629 mono_event_get_flags (MonoEvent *event)
9631 return event->attrs;
9635 * mono_class_get_method_from_name:
9636 * @klass: where to look for the method
9637 * @name: name of the method
9638 * @param_count: number of parameters. -1 for any number.
9640 * Obtains a MonoMethod with a given name and number of parameters.
9641 * It only works if there are no multiple signatures for any given method name.
9644 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9646 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9650 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9652 MonoMethod *res = NULL;
9655 /* Search directly in the metadata to avoid calling setup_methods () */
9656 int first_idx = mono_class_get_first_method_idx (klass);
9657 int mcount = mono_class_get_method_count (klass);
9658 for (i = 0; i < mcount; ++i) {
9660 guint32 cols [MONO_METHOD_SIZE];
9662 MonoMethodSignature *sig;
9664 /* first_idx points into the methodptr table */
9665 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9667 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9668 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9670 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9673 if (param_count == -1) {
9677 sig = mono_method_signature_checked (method, &error);
9679 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9682 if (sig->param_count == param_count) {
9693 * mono_class_get_method_from_name_flags:
9694 * @klass: where to look for the method
9695 * @name_space: name of the method
9696 * @param_count: number of parameters. -1 for any number.
9697 * @flags: flags which must be set in the method
9699 * Obtains a MonoMethod with a given name and number of parameters.
9700 * It only works if there are no multiple signatures for any given method name.
9703 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9705 MonoMethod *res = NULL;
9708 mono_class_init (klass);
9710 if (mono_class_is_ginst (klass) && !klass->methods) {
9711 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9714 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9715 if (!mono_error_ok (&error))
9716 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9721 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9722 mono_class_setup_methods (klass);
9724 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9725 See mono/tests/array_load_exception.il
9726 FIXME we should better report this error to the caller
9728 if (!klass->methods)
9730 int mcount = mono_class_get_method_count (klass);
9731 for (i = 0; i < mcount; ++i) {
9732 MonoMethod *method = klass->methods [i];
9734 if (method->name[0] == name [0] &&
9735 !strcmp (name, method->name) &&
9736 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9737 ((method->flags & flags) == flags)) {
9744 res = find_method_in_metadata (klass, name, param_count, flags);
9751 * mono_class_set_failure:
9752 * @klass: class in which the failure was detected
9753 * @ex_type: the kind of exception/error to be thrown (later)
9754 * @ex_data: exception data (specific to each type of exception/error)
9756 * Keep a detected failure informations in the class for later processing.
9757 * Note that only the first failure is kept.
9759 * LOCKING: Acquires the loader lock.
9762 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9764 g_assert (boxed_error != NULL);
9766 if (mono_class_has_failure (klass))
9769 mono_loader_lock ();
9770 klass->has_failure = 1;
9771 mono_class_set_exception_data (klass, boxed_error);
9772 mono_loader_unlock ();
9778 mono_class_has_failure (const MonoClass *klass)
9780 g_assert (klass != NULL);
9781 return klass->has_failure != 0;
9786 * mono_class_set_type_load_failure:
9787 * @klass: class in which the failure was detected
9788 * @fmt: Printf-style error message string.
9790 * Collect detected failure informaion in the class for later processing.
9791 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9792 * Note that only the first failure is kept.
9794 * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9796 * LOCKING: Acquires the loader lock.
9799 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9801 MonoError prepare_error;
9804 if (mono_class_has_failure (klass))
9807 error_init (&prepare_error);
9809 va_start (args, fmt);
9810 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9813 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9814 mono_error_cleanup (&prepare_error);
9815 return mono_class_set_failure (klass, box);
9819 * mono_classes_init:
9821 * Initialize the resources used by this module.
9824 mono_classes_init (void)
9826 mono_os_mutex_init (&classes_mutex);
9828 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9829 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9831 mono_counters_register ("MonoClassDef count",
9832 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9833 mono_counters_register ("MonoClassGtd count",
9834 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9835 mono_counters_register ("MonoClassGenericInst count",
9836 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9837 mono_counters_register ("MonoClassGenericParam count",
9838 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9839 mono_counters_register ("MonoClassArray count",
9840 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9841 mono_counters_register ("MonoClassPointer count",
9842 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9843 mono_counters_register ("Inflated methods size",
9844 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9845 mono_counters_register ("Inflated classes size",
9846 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9847 mono_counters_register ("MonoClass size",
9848 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9852 * mono_classes_cleanup:
9854 * Free the resources used by this module.
9857 mono_classes_cleanup (void)
9859 mono_native_tls_free (setup_fields_tls_id);
9860 mono_native_tls_free (init_pending_tls_id);
9862 if (global_interface_bitset)
9863 mono_bitset_free (global_interface_bitset);
9864 global_interface_bitset = NULL;
9865 mono_os_mutex_destroy (&classes_mutex);
9869 * mono_class_get_exception_for_failure:
9870 * @klass: class in which the failure was detected
9872 * Return a constructed MonoException than the caller can then throw
9873 * using mono_raise_exception - or NULL if no failure is present (or
9874 * doesn't result in an exception).
9877 mono_class_get_exception_for_failure (MonoClass *klass)
9879 if (!mono_class_has_failure (klass))
9881 MonoError unboxed_error;
9882 error_init (&unboxed_error);
9883 mono_error_set_for_class_failure (&unboxed_error, klass);
9884 return mono_error_convert_to_exception (&unboxed_error);
9888 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9890 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9891 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9893 if (outer_klass == inner_klass)
9895 inner_klass = inner_klass->nested_in;
9896 } while (inner_klass);
9901 mono_class_get_generic_type_definition (MonoClass *klass)
9903 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9904 return gklass ? gklass->container_class : klass;
9908 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9910 * Generic instantiations are ignored for all super types of @klass.
9912 * Visibility checks ignoring generic instantiations.
9915 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9918 klass = mono_class_get_generic_type_definition (klass);
9919 parent = mono_class_get_generic_type_definition (parent);
9920 mono_class_setup_supertypes (klass);
9922 for (i = 0; i < klass->idepth; ++i) {
9923 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9929 * Subtype can only access parent members with family protection if the site object
9930 * is subclass of Subtype. For example:
9931 * class A { protected int x; }
9933 * void valid_access () {
9937 * void invalid_access () {
9944 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9946 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9949 if (context_klass == NULL)
9951 /*if access_klass is not member_klass context_klass must be type compat*/
9952 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9958 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9961 if (accessing == accessed)
9963 if (!accessed || !accessing)
9966 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9967 * anywhere so untrusted friends are not safe to access platform's code internals */
9968 if (mono_security_core_clr_enabled ()) {
9969 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9973 mono_assembly_load_friends (accessed);
9974 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9975 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
9976 /* Be conservative with checks */
9979 if (strcmp (accessing->aname.name, friend_->name))
9981 if (friend_->public_key_token [0]) {
9982 if (!accessing->aname.public_key_token [0])
9984 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
9993 * If klass is a generic type or if it is derived from a generic type, return the
9994 * MonoClass of the generic definition
9995 * Returns NULL if not found
9998 get_generic_definition_class (MonoClass *klass)
10001 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10002 if (gklass && gklass->container_class)
10003 return gklass->container_class;
10004 klass = klass->parent;
10010 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10013 for (i = 0; i < ginst->type_argc; ++i) {
10014 MonoType *type = ginst->type_argv[i];
10015 switch (type->type) {
10016 case MONO_TYPE_SZARRAY:
10017 if (!can_access_type (access_klass, type->data.klass))
10020 case MONO_TYPE_ARRAY:
10021 if (!can_access_type (access_klass, type->data.array->eklass))
10024 case MONO_TYPE_PTR:
10025 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10028 case MONO_TYPE_CLASS:
10029 case MONO_TYPE_VALUETYPE:
10030 case MONO_TYPE_GENERICINST:
10031 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10041 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10045 if (access_klass == member_klass)
10048 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10051 if (access_klass->element_class && !access_klass->enumtype)
10052 access_klass = access_klass->element_class;
10054 if (member_klass->element_class && !member_klass->enumtype)
10055 member_klass = member_klass->element_class;
10057 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10059 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10062 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10065 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10068 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10071 /*Non nested type with nested visibility. We just fail it.*/
10072 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10075 switch (access_level) {
10076 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10077 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10079 case TYPE_ATTRIBUTE_PUBLIC:
10082 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10085 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10086 return is_nesting_type (member_klass, access_klass);
10088 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10089 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10091 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10092 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10094 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10095 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10096 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10098 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10099 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10100 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10105 /* FIXME: check visibility of type, too */
10107 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10109 MonoClass *member_generic_def;
10110 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10113 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10114 if (((access_gklass && access_gklass->container_class) ||
10115 mono_class_is_gtd (access_klass)) &&
10116 (member_generic_def = get_generic_definition_class (member_klass))) {
10117 MonoClass *access_container;
10119 if (mono_class_is_gtd (access_klass))
10120 access_container = access_klass;
10122 access_container = access_gklass->container_class;
10124 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10128 /* Partition I 8.5.3.2 */
10129 /* the access level values are the same for fields and methods */
10130 switch (access_level) {
10131 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10132 /* same compilation unit */
10133 return access_klass->image == member_klass->image;
10134 case FIELD_ATTRIBUTE_PRIVATE:
10135 return access_klass == member_klass;
10136 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10137 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10138 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10141 case FIELD_ATTRIBUTE_ASSEMBLY:
10142 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10143 case FIELD_ATTRIBUTE_FAMILY:
10144 if (is_valid_family_access (access_klass, member_klass, context_klass))
10147 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10148 if (is_valid_family_access (access_klass, member_klass, context_klass))
10150 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10151 case FIELD_ATTRIBUTE_PUBLIC:
10158 * mono_method_can_access_field:
10159 * @method: Method that will attempt to access the field
10160 * @field: the field to access
10162 * Used to determine if a method is allowed to access the specified field.
10164 * Returns: TRUE if the given @method is allowed to access the @field while following
10165 * the accessibility rules of the CLI.
10168 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10170 /* FIXME: check all overlapping fields */
10171 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10173 MonoClass *nested = method->klass->nested_in;
10175 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10178 nested = nested->nested_in;
10185 * mono_method_can_access_method:
10186 * @method: Method that will attempt to access the other method
10187 * @called: the method that we want to probe for accessibility.
10189 * Used to determine if the @method is allowed to access the specified @called method.
10191 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10192 * the accessibility rules of the CLI.
10195 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10197 method = mono_method_get_method_definition (method);
10198 called = mono_method_get_method_definition (called);
10199 return mono_method_can_access_method_full (method, called, NULL);
10203 * mono_method_can_access_method_full:
10204 * @method: The caller method
10205 * @called: The called method
10206 * @context_klass: The static type on stack of the owner @called object used
10208 * This function must be used with instance calls, as they have more strict family accessibility.
10209 * It can be used with static methods, but context_klass should be NULL.
10211 * Returns: TRUE if caller have proper visibility and acessibility to @called
10214 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10216 /* Wrappers are except from access checks */
10217 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10220 MonoClass *access_class = method->klass;
10221 MonoClass *member_class = called->klass;
10222 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10224 MonoClass *nested = access_class->nested_in;
10226 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10229 nested = nested->nested_in;
10236 can = can_access_type (access_class, member_class);
10238 MonoClass *nested = access_class->nested_in;
10240 can = can_access_type (nested, member_class);
10243 nested = nested->nested_in;
10250 if (called->is_inflated) {
10251 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10252 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10261 * mono_method_can_access_field_full:
10262 * @method: The caller method
10263 * @field: The accessed field
10264 * @context_klass: The static type on stack of the owner @field object used
10266 * This function must be used with instance fields, as they have more strict family accessibility.
10267 * It can be used with static fields, but context_klass should be NULL.
10269 * Returns: TRUE if caller have proper visibility and acessibility to @field
10272 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10274 MonoClass *access_class = method->klass;
10275 MonoClass *member_class = field->parent;
10276 /* FIXME: check all overlapping fields */
10277 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10279 MonoClass *nested = access_class->nested_in;
10281 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10284 nested = nested->nested_in;
10291 can = can_access_type (access_class, member_class);
10293 MonoClass *nested = access_class->nested_in;
10295 can = can_access_type (nested, member_class);
10298 nested = nested->nested_in;
10308 * mono_class_can_access_class:
10309 * @source_class: The source class
10310 * @target_class: The accessed class
10312 * This function returns is @target_class is visible to @source_class
10314 * Returns: TRUE if source have proper visibility and acessibility to target
10317 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10319 return can_access_type (source_class, target_class);
10323 * mono_type_is_valid_enum_basetype:
10324 * @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 * @klass: An enum class to be validated
10352 * This method verify the required properties an enum should have.
10354 * Returns: TRUE if the informed enum class is valid
10356 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10357 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10358 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
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 * @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 @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 * @method: a method
10627 * @definition: if true, get the definition
10628 * @error: set on failure
10630 * Given a virtual method associated with a subclass, return the corresponding
10631 * method from an ancestor. If @definition is FALSE, returns the method in the
10632 * superclass of the given method. If @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
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);