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/unlocked.h>
50 #include <mono/utils/bsearch.h>
51 #include <mono/utils/checked-build.h>
55 gboolean mono_print_vtable = FALSE;
56 gboolean mono_align_small_structs = FALSE;
59 gint32 inflated_classes_size, inflated_methods_size;
61 gint32 class_def_count, class_gtd_count, class_ginst_count, class_gparam_count, class_array_count, class_pointer_count;
63 /* Low level lock which protects data structures in this module */
64 static mono_mutex_t classes_mutex;
66 /* Function supplied by the runtime to find classes by name using information from the AOT file */
67 static MonoGetClassFromName get_class_from_name = NULL;
69 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
70 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
71 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
72 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
73 static int generic_array_methods (MonoClass *klass);
74 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache);
76 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
77 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
78 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
79 static guint32 mono_field_resolve_flags (MonoClassField *field);
80 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
81 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
83 static gboolean mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error);
87 We use gclass recording to allow recursive system f types to be referenced by a parent.
89 Given the following type hierarchy:
91 class TextBox : TextBoxBase<TextBox> {}
92 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
93 class TextInput<T> : Input<T> where T: TextInput<T> {}
96 The runtime tries to load TextBoxBase<>.
97 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
98 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
99 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
101 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
102 at this point, iow, both are registered in the type map and both and a NULL parent. This means
103 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
105 To fix that what we do is to record all generic instantes created while resolving the parent of
106 any generic type definition and, after resolved, correct the parent field if needed.
109 static int record_gclass_instantiation;
110 static GSList *gclass_recorded_list;
111 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
113 /* This TLS variable points to a GSList of classes which have setup_fields () executing */
114 static MonoNativeTlsKey setup_fields_tls_id;
116 static MonoNativeTlsKey init_pending_tls_id;
121 mono_locks_os_acquire (&classes_mutex, ClassesLock);
125 classes_unlock (void)
127 mono_locks_os_release (&classes_mutex, ClassesLock);
131 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
134 enable_gclass_recording (void)
136 ++record_gclass_instantiation;
140 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
143 disable_gclass_recording (gclass_record_func func, void *user_data)
145 GSList **head = &gclass_recorded_list;
147 g_assert (record_gclass_instantiation > 0);
148 --record_gclass_instantiation;
151 GSList *node = *head;
152 if (func ((MonoClass*)node->data, user_data)) {
154 g_slist_free_1 (node);
160 /* We automatically discard all recorded gclasses when disabled. */
161 if (!record_gclass_instantiation && gclass_recorded_list) {
162 g_slist_free (gclass_recorded_list);
163 gclass_recorded_list = NULL;
168 * mono_class_from_typeref:
169 * \param image a MonoImage
170 * \param type_token a TypeRef token
172 * Creates the \c MonoClass* structure representing the type defined by
173 * the typeref token valid inside \p image.
174 * \returns The \c MonoClass* representing the typeref token, or NULL if it could
178 mono_class_from_typeref (MonoImage *image, guint32 type_token)
181 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
182 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
187 * mono_class_from_typeref_checked:
188 * \param image a MonoImage
189 * \param type_token a TypeRef token
190 * \param error error return code, if any.
192 * Creates the \c MonoClass* structure representing the type defined by
193 * the typeref token valid inside \p image.
195 * \returns The \c MonoClass* representing the typeref token, NULL if it could
196 * not be loaded with the \p error value filled with the information about the
200 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
202 guint32 cols [MONO_TYPEREF_SIZE];
203 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
205 const char *name, *nspace;
206 MonoClass *res = NULL;
211 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
214 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
216 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
217 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
219 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
220 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
221 case MONO_RESOLUTION_SCOPE_MODULE:
223 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
224 This is not the observed behavior of existing implementations.
225 The defacto behavior is that it's just a typedef in disguise.
227 /* a typedef in disguise */
228 res = mono_class_from_name_checked (image, nspace, name, error);
231 case MONO_RESOLUTION_SCOPE_MODULEREF:
232 module = mono_image_load_module_checked (image, idx, error);
234 res = mono_class_from_name_checked (module, nspace, name, error);
237 case MONO_RESOLUTION_SCOPE_TYPEREF: {
238 MonoClass *enclosing;
241 if (idx == mono_metadata_token_index (type_token)) {
242 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
246 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
247 return_val_if_nok (error, NULL);
249 GList *nested_classes = mono_class_get_nested_classes_property (enclosing);
250 if (enclosing->nested_classes_inited && nested_classes) {
251 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
252 for (tmp = nested_classes; tmp; tmp = tmp->next) {
253 res = (MonoClass *)tmp->data;
254 if (strcmp (res->name, name) == 0)
258 /* Don't call mono_class_init as we might've been called by it recursively */
259 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
261 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
262 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
263 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
265 if (strcmp (nname, name) == 0)
266 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
268 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
271 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
274 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
278 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
279 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
283 if (!image->references || !image->references [idx - 1])
284 mono_assembly_load_reference (image, idx - 1);
285 g_assert (image->references [idx - 1]);
287 /* If the assembly did not load, register this as a type load exception */
288 if (image->references [idx - 1] == REFERENCE_MISSING){
289 MonoAssemblyName aname;
292 mono_assembly_get_assemblyref (image, idx - 1, &aname);
293 human_name = mono_stringify_assembly_name (&aname);
294 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
298 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
301 /* Generic case, should be avoided for when a better error is possible. */
302 if (!res && mono_error_ok (error)) {
303 char *name = mono_class_name_from_token (image, type_token);
304 char *assembly = mono_assembly_name_from_token (image, type_token);
305 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);
312 mono_image_memdup (MonoImage *image, void *data, guint size)
314 void *res = mono_image_alloc (image, size);
315 memcpy (res, data, size);
319 /* Copy everything mono_metadata_free_array free. */
321 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
324 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
326 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
328 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
330 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
332 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
334 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
339 /* Copy everything mono_metadata_free_method_signature free. */
341 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
345 sig = mono_metadata_signature_dup_full (image, sig);
347 sig->ret = mono_metadata_type_dup (image, sig->ret);
348 for (i = 0; i < sig->param_count; ++i)
349 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
355 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
357 MonoAssembly *ta = klass->image->assembly;
360 name = mono_stringify_assembly_name (&ta->aname);
361 g_string_append_printf (str, ", %s", name);
366 mono_type_name_check_byref (MonoType *type, GString *str)
369 g_string_append_c (str, '&');
373 * mono_identifier_escape_type_name_chars:
374 * \param str a destination string
375 * \param identifier an IDENTIFIER in internal form
379 * The displayed form of the identifier is appended to str.
381 * The displayed form of an identifier has the characters ,+&*[]\
382 * that have special meaning in type names escaped with a preceeding
383 * backslash (\) character.
386 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
392 // reserve space for common case: there will be no escaped characters.
393 g_string_set_size(str, n + strlen(identifier));
394 g_string_set_size(str, n);
396 for (const char* s = identifier; *s != 0 ; s++) {
405 g_string_append_c (str, '\\');
406 g_string_append_c (str, *s);
409 g_string_append_c (str, *s);
417 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
418 MonoTypeNameFormat format)
422 switch (type->type) {
423 case MONO_TYPE_ARRAY: {
424 int i, rank = type->data.array->rank;
425 MonoTypeNameFormat nested_format;
427 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
428 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
430 mono_type_get_name_recurse (
431 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
432 g_string_append_c (str, '[');
434 g_string_append_c (str, '*');
435 for (i = 1; i < rank; i++)
436 g_string_append_c (str, ',');
437 g_string_append_c (str, ']');
439 mono_type_name_check_byref (type, str);
441 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
442 _mono_type_get_assembly_name (type->data.array->eklass, str);
445 case MONO_TYPE_SZARRAY: {
446 MonoTypeNameFormat nested_format;
448 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
449 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
451 mono_type_get_name_recurse (
452 &type->data.klass->byval_arg, str, FALSE, nested_format);
453 g_string_append (str, "[]");
455 mono_type_name_check_byref (type, str);
457 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
458 _mono_type_get_assembly_name (type->data.klass, str);
461 case MONO_TYPE_PTR: {
462 MonoTypeNameFormat nested_format;
464 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
465 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
467 mono_type_get_name_recurse (
468 type->data.type, str, FALSE, nested_format);
469 g_string_append_c (str, '*');
471 mono_type_name_check_byref (type, str);
473 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
474 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
479 if (!mono_generic_param_info (type->data.generic_param))
480 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
482 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
484 mono_type_name_check_byref (type, str);
488 klass = mono_class_from_mono_type (type);
489 if (klass->nested_in) {
490 mono_type_get_name_recurse (
491 &klass->nested_in->byval_arg, str, TRUE, format);
492 if (format == MONO_TYPE_NAME_FORMAT_IL)
493 g_string_append_c (str, '.');
495 g_string_append_c (str, '+');
496 } else if (*klass->name_space) {
497 if (format == MONO_TYPE_NAME_FORMAT_IL)
498 g_string_append (str, klass->name_space);
500 mono_identifier_escape_type_name_chars (str, klass->name_space);
501 g_string_append_c (str, '.');
503 if (format == MONO_TYPE_NAME_FORMAT_IL) {
504 char *s = strchr (klass->name, '`');
505 int len = s ? s - klass->name : strlen (klass->name);
506 g_string_append_len (str, klass->name, len);
508 mono_identifier_escape_type_name_chars (str, klass->name);
512 if (mono_class_is_ginst (klass)) {
513 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
514 MonoGenericInst *inst = gclass->context.class_inst;
515 MonoTypeNameFormat nested_format;
518 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
519 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
521 if (format == MONO_TYPE_NAME_FORMAT_IL)
522 g_string_append_c (str, '<');
524 g_string_append_c (str, '[');
525 for (i = 0; i < inst->type_argc; i++) {
526 MonoType *t = inst->type_argv [i];
529 g_string_append_c (str, ',');
530 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
531 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
532 g_string_append_c (str, '[');
533 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
534 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
535 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
536 g_string_append_c (str, ']');
538 if (format == MONO_TYPE_NAME_FORMAT_IL)
539 g_string_append_c (str, '>');
541 g_string_append_c (str, ']');
542 } else if (mono_class_is_gtd (klass) &&
543 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
544 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
547 if (format == MONO_TYPE_NAME_FORMAT_IL)
548 g_string_append_c (str, '<');
550 g_string_append_c (str, '[');
551 for (i = 0; i < mono_class_get_generic_container (klass)->type_argc; i++) {
553 g_string_append_c (str, ',');
554 g_string_append (str, mono_generic_container_get_param_info (mono_class_get_generic_container (klass), i)->name);
556 if (format == MONO_TYPE_NAME_FORMAT_IL)
557 g_string_append_c (str, '>');
559 g_string_append_c (str, ']');
562 mono_type_name_check_byref (type, str);
564 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
565 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
566 _mono_type_get_assembly_name (klass, str);
572 * mono_type_get_name_full:
574 * \param format the format for the return string.
577 * \returns The string representation in a number of formats:
579 * if \p format is \c MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
580 * returned in the format required by \c System.Reflection, this is the
581 * inverse of mono_reflection_parse_type().
583 * if \p format is \c MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
584 * be used by the IL assembler.
586 * if \p format is \c MONO_TYPE_NAME_FORMAT_FULL_NAME
588 * if \p format is \c MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
591 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
595 result = g_string_new ("");
597 mono_type_get_name_recurse (type, result, FALSE, format);
599 return g_string_free (result, FALSE);
603 * mono_type_get_full_name:
604 * \param class a class
606 * \returns The string representation for type as required by System.Reflection.
607 * The inverse of mono_reflection_parse_type().
610 mono_type_get_full_name (MonoClass *klass)
612 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
616 * 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:
629 * \returns The \c MonoType for the underlying integer type if \p type
630 * is an enum and byref is false, otherwise the type itself.
633 mono_type_get_underlying_type (MonoType *type)
635 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
636 return mono_class_enum_basetype (type->data.klass);
637 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
638 return mono_class_enum_basetype (type->data.generic_class->container_class);
643 * mono_class_is_open_constructed_type:
646 * \returns TRUE if type represents a generics open constructed type.
647 * IOW, not all type parameters required for the instantiation have
648 * been provided or it's a generic type definition.
650 * An open constructed type means it's a non realizable type. Not to
651 * be mixed up with an abstract type - we can't cast or dispatch to
652 * an open type, for example.
655 mono_class_is_open_constructed_type (MonoType *t)
661 case MONO_TYPE_SZARRAY:
662 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
663 case MONO_TYPE_ARRAY:
664 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
666 return mono_class_is_open_constructed_type (t->data.type);
667 case MONO_TYPE_GENERICINST:
668 return t->data.generic_class->context.class_inst->is_open;
669 case MONO_TYPE_CLASS:
670 case MONO_TYPE_VALUETYPE:
671 return mono_class_is_gtd (t->data.klass);
678 This is a simple function to catch the most common bad instances of generic types.
679 Specially those that might lead to further failures in the runtime.
682 is_valid_generic_argument (MonoType *type)
684 switch (type->type) {
686 //case MONO_TYPE_TYPEDBYREF:
694 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
698 switch (type->type) {
699 case MONO_TYPE_MVAR: {
701 int num = mono_type_get_generic_param_num (type);
702 MonoGenericInst *inst = context->method_inst;
705 if (num >= inst->type_argc) {
706 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
707 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
708 num, info ? info->name : "", inst->type_argc);
712 if (!is_valid_generic_argument (inst->type_argv [num])) {
713 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
714 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
715 num, info ? info->name : "", inst->type_argv [num]->type);
719 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
720 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
721 * ->byref and ->attrs from @type are propagated to the returned type.
723 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
724 nt->byref = type->byref;
725 nt->attrs = type->attrs;
728 case MONO_TYPE_VAR: {
730 int num = mono_type_get_generic_param_num (type);
731 MonoGenericInst *inst = context->class_inst;
734 if (num >= inst->type_argc) {
735 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
736 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
737 num, info ? info->name : "", inst->type_argc);
740 if (!is_valid_generic_argument (inst->type_argv [num])) {
741 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
742 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
743 num, info ? info->name : "", inst->type_argv [num]->type);
746 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
747 nt->byref = type->byref;
748 nt->attrs = type->attrs;
751 case MONO_TYPE_SZARRAY: {
752 MonoClass *eclass = type->data.klass;
753 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
754 if (!inflated || !mono_error_ok (error))
756 nt = mono_metadata_type_dup (image, type);
757 nt->data.klass = mono_class_from_mono_type (inflated);
758 mono_metadata_free_type (inflated);
761 case MONO_TYPE_ARRAY: {
762 MonoClass *eclass = type->data.array->eklass;
763 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
764 if (!inflated || !mono_error_ok (error))
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.array->eklass = mono_class_from_mono_type (inflated);
768 mono_metadata_free_type (inflated);
771 case MONO_TYPE_GENERICINST: {
772 MonoGenericClass *gclass = type->data.generic_class;
773 MonoGenericInst *inst;
775 if (!gclass->context.class_inst->is_open)
778 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
779 return_val_if_nok (error, NULL);
781 if (inst != gclass->context.class_inst)
782 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
784 if (gclass == type->data.generic_class)
787 nt = mono_metadata_type_dup (image, type);
788 nt->data.generic_class = gclass;
791 case MONO_TYPE_CLASS:
792 case MONO_TYPE_VALUETYPE: {
793 MonoClass *klass = type->data.klass;
794 MonoGenericContainer *container = mono_class_try_get_generic_container (klass);
795 MonoGenericInst *inst;
796 MonoGenericClass *gclass = NULL;
802 /* We can't use context->class_inst directly, since it can have more elements */
803 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
804 return_val_if_nok (error, NULL);
806 if (inst == container->context.class_inst)
809 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
811 nt = mono_metadata_type_dup (image, type);
812 nt->type = MONO_TYPE_GENERICINST;
813 nt->data.generic_class = gclass;
823 mono_generic_class_get_context (MonoGenericClass *gclass)
825 return &gclass->context;
829 mono_class_get_context (MonoClass *klass)
831 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
832 return gklass ? mono_generic_class_get_context (gklass) : NULL;
836 * mono_class_inflate_generic_type_with_mempool:
837 * @mempool: a mempool
839 * @context: a generics context
840 * @error: error context
842 * The same as mono_class_inflate_generic_type, but allocates the MonoType
843 * from mempool if it is non-NULL. If it is NULL, the MonoType is
844 * allocated on the heap and is owned by the caller.
845 * The returned type can potentially be the same as TYPE, so it should not be
846 * modified by the caller, and it should be freed using mono_metadata_free_type ().
849 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
851 MonoType *inflated = NULL;
855 inflated = inflate_generic_type (image, type, context, error);
856 return_val_if_nok (error, NULL);
859 MonoType *shared = mono_metadata_get_shared_type (type);
864 return mono_metadata_type_dup (image, type);
868 UnlockedIncrement (&mono_stats.inflated_type_count);
873 * mono_class_inflate_generic_type:
875 * \param context a generics context
876 * \deprecated Please use \c mono_class_inflate_generic_type_checked instead
878 * If \p type is a generic type and \p context is not NULL, instantiate it using the
879 * generics context \p context.
881 * \returns The instantiated type or a copy of \p type. The returned \c MonoType is allocated
882 * on the heap and is owned by the caller. Returns NULL on error.
885 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
889 result = mono_class_inflate_generic_type_checked (type, context, &error);
890 mono_error_cleanup (&error);
895 * mono_class_inflate_generic_type:
897 * @context: a generics context
898 * @error: error context to use
900 * If @type is a generic type and @context is not NULL, instantiate it using the
901 * generics context @context.
903 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
904 * on the heap and is owned by the caller.
907 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
909 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
913 * mono_class_inflate_generic_type_no_copy:
915 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
919 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
921 MonoType *inflated = NULL;
925 inflated = inflate_generic_type (image, type, context, error);
926 return_val_if_nok (error, NULL);
932 UnlockedIncrement (&mono_stats.inflated_type_count);
937 * mono_class_inflate_generic_class:
939 * Inflate the class @gklass with @context. Set @error on failure.
942 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
947 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
948 return_val_if_nok (error, NULL);
950 res = mono_class_from_mono_type (inflated);
951 mono_metadata_free_type (inflated);
956 static MonoGenericContext
957 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
959 MonoGenericInst *class_inst = NULL;
960 MonoGenericInst *method_inst = NULL;
961 MonoGenericContext res = { NULL, NULL };
965 if (context->class_inst) {
966 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
967 if (!mono_error_ok (error))
971 if (context->method_inst) {
972 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
973 if (!mono_error_ok (error))
977 res.class_inst = class_inst;
978 res.method_inst = method_inst;
984 * mono_class_inflate_generic_method:
985 * \param method a generic method
986 * \param context a generics context
988 * Instantiate the generic method \p method using the generics context \p context.
990 * \returns The new instantiated method
993 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
995 return mono_class_inflate_generic_method_full (method, NULL, context);
999 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1001 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1005 * mono_class_inflate_generic_method_full:
1007 * Instantiate method \p method with the generic context \p context.
1008 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1009 * Use mono_method_signature() and mono_method_get_header() to get the correct values.
1012 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1015 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1016 if (!mono_error_ok (&error))
1017 /*FIXME do proper error handling - on this case, kill this function. */
1018 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1024 * mono_class_inflate_generic_method_full_checked:
1025 * Same as mono_class_inflate_generic_method_full but return failure using \p error.
1028 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1031 MonoMethodInflated *iresult, *cached;
1032 MonoMethodSignature *sig;
1033 MonoGenericContext tmp_context;
1037 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1038 while (method->is_inflated) {
1039 MonoGenericContext *method_context = mono_method_get_context (method);
1040 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1042 tmp_context = inflate_generic_context (method_context, context, error);
1043 return_val_if_nok (error, NULL);
1045 context = &tmp_context;
1047 if (mono_metadata_generic_context_equal (method_context, context))
1050 method = imethod->declaring;
1054 * A method only needs to be inflated if the context has argument for which it is
1057 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1058 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1061 if (!((method->is_generic && context->method_inst) ||
1062 (mono_class_is_gtd (method->klass) && context->class_inst)))
1065 iresult = g_new0 (MonoMethodInflated, 1);
1066 iresult->context = *context;
1067 iresult->declaring = method;
1069 if (!context->method_inst && method->is_generic)
1070 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1072 if (!context->class_inst) {
1073 g_assert (!mono_class_is_ginst (iresult->declaring->klass));
1074 if (mono_class_is_gtd (iresult->declaring->klass))
1075 iresult->context.class_inst = mono_class_get_generic_container (iresult->declaring->klass)->context.class_inst;
1077 /* This can happen with some callers like mono_object_get_virtual_method () */
1078 if (!mono_class_is_gtd (iresult->declaring->klass) && !mono_class_is_ginst (iresult->declaring->klass))
1079 iresult->context.class_inst = NULL;
1081 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1084 mono_image_set_lock (set);
1085 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1086 mono_image_set_unlock (set);
1090 return (MonoMethod*)cached;
1093 UnlockedIncrement (&mono_stats.inflated_method_count);
1095 UnlockedAdd (&inflated_methods_size, sizeof (MonoMethodInflated));
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1117 if (method->wrapper_type) {
1118 MonoMethodWrapper *mw = (MonoMethodWrapper*)method;
1119 MonoMethodWrapper *resw = (MonoMethodWrapper*)result;
1120 int len = GPOINTER_TO_INT (((void**)mw->method_data) [0]);
1122 resw->method_data = (void **)g_malloc (sizeof (gpointer) * (len + 1));
1123 memcpy (resw->method_data, mw->method_data, sizeof (gpointer) * (len + 1));
1126 if (iresult->context.method_inst) {
1127 /* Set the generic_container of the result to the generic_container of method */
1128 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1130 if (generic_container && iresult->context.method_inst == generic_container->context.method_inst) {
1131 result->is_generic = 1;
1132 mono_method_set_generic_container (result, generic_container);
1137 MonoGenericClass *gklass_hint = mono_class_try_get_generic_class (klass_hint);
1138 if (gklass_hint && (gklass_hint->container_class != method->klass || gklass_hint->context.class_inst != context->class_inst))
1142 if (mono_class_is_gtd (method->klass))
1143 result->klass = klass_hint;
1145 if (!result->klass) {
1146 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1147 if (!mono_error_ok (error))
1150 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1152 mono_metadata_free_type (inflated);
1156 * FIXME: This should hold, but it doesn't:
1158 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1159 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1160 * g_assert (result->is_generic);
1163 * Fixing this here causes other things to break, hence a very
1164 * ugly hack in mini-trampolines.c - see
1165 * is_generic_method_definition().
1169 mono_image_set_lock (set);
1170 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1172 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1173 iresult->owner = set;
1176 mono_image_set_unlock (set);
1178 return (MonoMethod*)cached;
1186 * mono_get_inflated_method:
1188 * Obsolete. We keep it around since it's mentioned in the public API.
1191 mono_get_inflated_method (MonoMethod *method)
1197 * mono_method_get_context_general:
1199 * @uninflated: handle uninflated methods?
1201 * Returns the generic context of a method or NULL if it doesn't have
1202 * one. For an inflated method that's the context stored in the
1203 * method. Otherwise it's in the method's generic container or in the
1204 * generic container of the method's class.
1207 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1209 if (method->is_inflated) {
1210 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1211 return &imethod->context;
1215 if (method->is_generic)
1216 return &(mono_method_get_generic_container (method)->context);
1217 if (mono_class_is_gtd (method->klass))
1218 return &mono_class_get_generic_container (method->klass)->context;
1223 * mono_method_get_context:
1226 * Returns the generic context for method if it's inflated, otherwise
1230 mono_method_get_context (MonoMethod *method)
1232 return mono_method_get_context_general (method, FALSE);
1236 * mono_method_get_generic_container:
1238 * Returns the generic container of METHOD, which should be a generic method definition.
1239 * Returns NULL if METHOD is not a generic method definition.
1240 * LOCKING: Acquires the loader lock.
1242 MonoGenericContainer*
1243 mono_method_get_generic_container (MonoMethod *method)
1245 MonoGenericContainer *container;
1247 if (!method->is_generic)
1250 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1251 g_assert (container);
1257 * mono_method_set_generic_container:
1259 * Sets the generic container of METHOD to CONTAINER.
1260 * LOCKING: Acquires the image lock.
1263 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1265 g_assert (method->is_generic);
1267 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1271 * mono_class_find_enum_basetype:
1272 * \param class The enum class
1274 * Determine the basetype of an enum by iterating through its fields. We do this
1275 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1278 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1280 MonoGenericContainer *container = NULL;
1281 MonoImage *m = klass->image;
1282 const int top = mono_class_get_field_count (klass);
1283 int i, first_field_idx;
1285 g_assert (klass->enumtype);
1289 container = mono_class_try_get_generic_container (klass);
1290 if (mono_class_is_ginst (klass)) {
1291 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
1293 container = mono_class_get_generic_container (gklass);
1294 g_assert (container);
1298 * Fetch all the field information.
1300 first_field_idx = mono_class_get_first_field_idx (klass);
1301 for (i = 0; i < top; i++){
1303 guint32 cols [MONO_FIELD_SIZE];
1304 int idx = first_field_idx + i;
1307 /* first_field_idx and idx points into the fieldptr table */
1308 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1310 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1313 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1314 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1318 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1319 mono_metadata_decode_value (sig, &sig);
1320 /* FIELD signature == 0x06 */
1322 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1326 ftype = mono_metadata_parse_type_checked (m, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
1330 if (mono_class_is_ginst (klass)) {
1331 //FIXME do we leak here?
1332 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1333 if (!mono_error_ok (error))
1335 ftype->attrs = cols [MONO_FIELD_FLAGS];
1340 mono_error_set_type_load_class (error, klass, "Could not find base type");
1347 * Checks for MonoClass::has_failure without resolving all MonoType's into MonoClass'es
1350 mono_type_has_exceptions (MonoType *type)
1352 switch (type->type) {
1353 case MONO_TYPE_CLASS:
1354 case MONO_TYPE_VALUETYPE:
1355 case MONO_TYPE_SZARRAY:
1356 return mono_class_has_failure (type->data.klass);
1357 case MONO_TYPE_ARRAY:
1358 return mono_class_has_failure (type->data.array->eklass);
1359 case MONO_TYPE_GENERICINST:
1360 return mono_class_has_failure (mono_generic_class_get_class (type->data.generic_class));
1367 mono_error_set_for_class_failure (MonoError *oerror, const MonoClass *klass)
1369 g_assert (mono_class_has_failure (klass));
1370 MonoErrorBoxed *box = mono_class_get_exception_data ((MonoClass*)klass);
1371 mono_error_set_from_boxed (oerror, box);
1377 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1381 mono_class_alloc (MonoClass *klass, int size)
1383 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1385 return mono_image_set_alloc (gklass->owner, size);
1387 return mono_image_alloc (klass->image, size);
1391 mono_class_alloc0 (MonoClass *klass, int size)
1395 res = mono_class_alloc (klass, size);
1396 memset (res, 0, size);
1400 #define mono_class_new0(klass,struct_type, n_structs) \
1401 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1404 * mono_class_setup_basic_field_info:
1405 * \param class The class to initialize
1407 * Initializes the following fields in MonoClass:
1408 * * klass->fields (only field->parent and field->name)
1409 * * klass->field.count
1410 * * klass->first_field_idx
1411 * LOCKING: Acquires the loader lock
1414 mono_class_setup_basic_field_info (MonoClass *klass)
1416 MonoGenericClass *gklass;
1417 MonoClassField *field;
1418 MonoClassField *fields;
1426 gklass = mono_class_try_get_generic_class (klass);
1427 gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1428 image = klass->image;
1431 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1433 * This happens when a generic instance of an unfinished generic typebuilder
1434 * is used as an element type for creating an array type. We can't initialize
1435 * the fields of this class using the fields of gklass, since gklass is not
1436 * finished yet, fields could be added to it later.
1442 mono_class_setup_basic_field_info (gtd);
1444 mono_loader_lock ();
1445 mono_class_set_field_count (klass, mono_class_get_field_count (gtd));
1446 mono_loader_unlock ();
1449 top = mono_class_get_field_count (klass);
1451 fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1454 * Fetch all the field information.
1456 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1457 for (i = 0; i < top; i++) {
1458 field = &fields [i];
1459 field->parent = klass;
1462 field->name = mono_field_get_name (>d->fields [i]);
1464 int idx = first_field_idx + i;
1465 /* first_field_idx and idx points into the fieldptr table */
1466 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1467 /* The name is needed for fieldrefs */
1468 field->name = mono_metadata_string_heap (image, name_idx);
1472 mono_memory_barrier ();
1474 mono_loader_lock ();
1476 klass->fields = fields;
1477 mono_loader_unlock ();
1481 * mono_class_set_failure_causedby_class:
1482 * \param klass the class that is failing
1483 * \param caused_by the class that caused the failure
1484 * \param msg Why \p klass is failing.
1486 * If \p caused_by has a failure, sets a TypeLoadException failure on
1487 * \p klass with message "\p msg, due to: {\p caused_by message}".
1489 * \returns TRUE if a failiure was set, or FALSE if \p caused_by doesn't have a failure.
1492 mono_class_set_type_load_failure_causedby_class (MonoClass *klass, const MonoClass *caused_by, const gchar* msg)
1494 if (mono_class_has_failure (caused_by)) {
1495 MonoError cause_error;
1496 error_init (&cause_error);
1497 mono_error_set_for_class_failure (&cause_error, caused_by);
1498 mono_class_set_type_load_failure (klass, "%s, due to: %s", msg, mono_error_get_message (&cause_error));
1499 mono_error_cleanup (&cause_error);
1508 * mono_class_setup_fields:
1509 * \p klass The class to initialize
1511 * Initializes klass->fields, computes class layout and sizes.
1512 * typebuilder_setup_fields () is the corresponding function for dynamic classes.
1513 * Sets the following fields in \p klass:
1514 * - all the fields initialized by mono_class_init_sizes ()
1515 * - element_class/cast_class (for enums)
1516 * - sizes:element_size (for arrays)
1517 * - field->type/offset for all fields
1520 * LOCKING: Acquires the loader lock.
1523 mono_class_setup_fields (MonoClass *klass)
1526 MonoImage *m = klass->image;
1528 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1530 guint32 real_size = 0;
1531 guint32 packing_size = 0;
1533 gboolean explicit_size;
1534 MonoClassField *field;
1535 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
1536 MonoClass *gtd = gklass ? mono_class_get_generic_type_definition (klass) : NULL;
1538 if (klass->fields_inited)
1541 if (gklass && image_is_dynamic (gklass->container_class->image) && !gklass->container_class->wastypebuilder) {
1543 * This happens when a generic instance of an unfinished generic typebuilder
1544 * is used as an element type for creating an array type. We can't initialize
1545 * the fields of this class using the fields of gklass, since gklass is not
1546 * finished yet, fields could be added to it later.
1551 mono_class_setup_basic_field_info (klass);
1552 top = mono_class_get_field_count (klass);
1555 mono_class_setup_fields (gtd);
1556 if (mono_class_set_type_load_failure_causedby_class (klass, gtd, "Generic type definition failed"))
1561 if (klass->parent) {
1562 /* For generic instances, klass->parent might not have been initialized */
1563 mono_class_init (klass->parent);
1564 mono_class_setup_fields (klass->parent);
1565 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Could not set up parent class"))
1567 instance_size = klass->parent->instance_size;
1569 instance_size = sizeof (MonoObject);
1572 /* Get the real size */
1573 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1575 instance_size += real_size;
1578 * This function can recursively call itself.
1579 * Prevent infinite recursion by using a list in TLS.
1581 GSList *init_list = (GSList *)mono_native_tls_get_value (setup_fields_tls_id);
1582 if (g_slist_find (init_list, klass))
1584 init_list = g_slist_prepend (init_list, klass);
1585 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1588 * Fetch all the field information.
1590 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1591 for (i = 0; i < top; i++) {
1592 int idx = first_field_idx + i;
1593 field = &klass->fields [i];
1596 mono_field_resolve_type (field, &error);
1597 if (!mono_error_ok (&error)) {
1598 /*mono_field_resolve_type already failed class*/
1599 mono_error_cleanup (&error);
1603 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1604 g_assert (field->type);
1607 if (!mono_type_get_underlying_type (field->type)) {
1608 mono_class_set_type_load_failure (klass, "Field '%s' is an enum type with a bad underlying type", field->name);
1612 if (mono_field_is_deleted (field))
1614 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1616 mono_metadata_field_info (m, idx, &uoffset, NULL, NULL);
1617 int offset = uoffset;
1619 if (offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1620 mono_class_set_type_load_failure (klass, "Missing field layout info for %s", field->name);
1623 if (offset < -1) { /*-1 is used to encode special static fields */
1624 mono_class_set_type_load_failure (klass, "Field '%s' has a negative offset %d", field->name, offset);
1627 if (mono_class_is_gtd (klass)) {
1628 mono_class_set_type_load_failure (klass, "Generic class cannot have explicit layout.");
1632 if (mono_type_has_exceptions (field->type)) {
1633 char *class_name = mono_type_get_full_name (klass);
1634 char *type_name = mono_type_full_name (field->type);
1636 mono_class_set_type_load_failure (klass, "Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1637 g_free (class_name);
1641 /* The def_value of fields is compute lazily during vtable creation */
1644 if (!mono_class_has_failure (klass)) {
1645 mono_loader_lock ();
1646 mono_class_layout_fields (klass, instance_size, packing_size, FALSE);
1647 mono_loader_unlock ();
1650 init_list = g_slist_remove (init_list, klass);
1651 mono_native_tls_set_value (setup_fields_tls_id, init_list);
1655 init_sizes_with_info (MonoClass *klass, MonoCachedClassInfo *cached_info)
1658 mono_loader_lock ();
1659 klass->instance_size = cached_info->instance_size;
1660 klass->sizes.class_size = cached_info->class_size;
1661 klass->packing_size = cached_info->packing_size;
1662 klass->min_align = cached_info->min_align;
1663 klass->blittable = cached_info->blittable;
1664 klass->has_references = cached_info->has_references;
1665 klass->has_static_refs = cached_info->has_static_refs;
1666 klass->no_special_static_fields = cached_info->no_special_static_fields;
1667 mono_loader_unlock ();
1670 if (!klass->size_inited)
1671 mono_class_setup_fields (klass);
1676 * mono_class_init_sizes:
1678 * Initializes the size related fields of @klass without loading all field data if possible.
1679 * Sets the following fields in @klass:
1681 * - sizes.class_size
1688 * Can fail the class.
1690 * LOCKING: Acquires the loader lock.
1693 mono_class_init_sizes (MonoClass *klass)
1695 MonoCachedClassInfo cached_info;
1696 gboolean has_cached_info;
1698 if (klass->size_inited)
1701 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
1703 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
1707 * mono_type_get_basic_type_from_generic:
1710 * Returns a closed type corresponding to the possibly open type
1714 mono_type_get_basic_type_from_generic (MonoType *type)
1716 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1717 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1718 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1719 return &mono_defaults.object_class->byval_arg;
1724 class_has_references (MonoClass *klass)
1726 mono_class_init_sizes (klass);
1729 * has_references is not set if this is called recursively, but this is not a problem since this is only used
1730 * during field layout, and instance fields are initialized before static fields, and instance fields can't
1733 return klass->has_references;
1737 type_has_references (MonoClass *klass, MonoType *ftype)
1739 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && class_has_references (mono_class_from_mono_type (ftype)))))
1741 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1742 MonoGenericParam *gparam = ftype->data.generic_param;
1744 if (gparam->gshared_constraint)
1745 return class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1751 * mono_class_layout_fields:
1753 * @base_instance_size: base instance size
1756 * This contains the common code for computing the layout of classes and sizes.
1757 * This should only be called from mono_class_setup_fields () and
1758 * typebuilder_setup_fields ().
1760 * LOCKING: Acquires the loader lock
1763 mono_class_layout_fields (MonoClass *klass, int base_instance_size, int packing_size, gboolean sre)
1766 const int top = mono_class_get_field_count (klass);
1767 guint32 layout = mono_class_get_flags (klass) & TYPE_ATTRIBUTE_LAYOUT_MASK;
1768 guint32 pass, passes, real_size;
1769 gboolean gc_aware_layout = FALSE;
1770 gboolean has_static_fields = FALSE;
1771 gboolean has_references = FALSE;
1772 gboolean has_static_refs = FALSE;
1773 MonoClassField *field;
1775 int instance_size = base_instance_size;
1776 int element_size = -1;
1777 int class_size, min_align;
1779 gboolean *fields_has_references;
1782 * We want to avoid doing complicated work inside locks, so we compute all the required
1783 * information and write it to @klass inside a lock.
1785 if (klass->fields_inited)
1788 if ((packing_size & 0xffffff00) != 0) {
1789 mono_class_set_type_load_failure (klass, "Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1793 if (klass->parent) {
1794 min_align = klass->parent->min_align;
1795 /* we use | since it may have been set already */
1796 has_references = klass->has_references | klass->parent->has_references;
1800 /* We can't really enable 16 bytes alignment until the GC supports it.
1801 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1802 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1803 Bug #506144 is an example of this issue.
1805 if (klass->simd_type)
1810 * When we do generic sharing we need to have layout
1811 * information for open generic classes (either with a generic
1812 * context containing type variables or with a generic
1813 * container), so we don't return in that case anymore.
1816 if (klass->enumtype) {
1817 for (i = 0; i < top; i++) {
1818 field = &klass->fields [i];
1819 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1820 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1825 if (!mono_class_enum_basetype (klass)) {
1826 mono_class_set_type_load_failure (klass, "The enumeration's base type is invalid.");
1832 * Enable GC aware auto layout: in this mode, reference
1833 * fields are grouped together inside objects, increasing collector
1835 * Requires that all classes whose layout is known to native code be annotated
1836 * with [StructLayout (LayoutKind.Sequential)]
1837 * Value types have gc_aware_layout disabled by default, as per
1838 * what the default is for other runtimes.
1840 /* corlib is missing [StructLayout] directives in many places */
1841 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1842 if (!klass->valuetype)
1843 gc_aware_layout = TRUE;
1846 /* Compute klass->blittable */
1849 blittable = klass->parent->blittable;
1850 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")) && top)
1852 for (i = 0; i < top; i++) {
1853 field = &klass->fields [i];
1855 if (mono_field_is_deleted (field))
1857 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1860 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1863 MonoClass *field_class = mono_class_from_mono_type (field->type);
1865 mono_class_setup_fields (field_class);
1866 if (mono_class_has_failure (field_class)) {
1867 MonoError field_error;
1868 error_init (&field_error);
1869 mono_error_set_for_class_failure (&field_error, field_class);
1870 mono_class_set_type_load_failure (klass, "Could not set up field '%s' due to: %s", field->name, mono_error_get_message (&field_error));
1871 mono_error_cleanup (&field_error);
1875 if (!field_class || !field_class->blittable)
1879 if (klass->enumtype)
1880 blittable = klass->element_class->blittable;
1882 if (mono_class_has_failure (klass))
1884 if (klass == mono_defaults.string_class)
1887 /* Compute klass->has_references */
1889 * Process non-static fields first, since static fields might recursively
1890 * refer to the class itself.
1892 for (i = 0; i < top; i++) {
1895 field = &klass->fields [i];
1897 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1898 ftype = mono_type_get_underlying_type (field->type);
1899 ftype = mono_type_get_basic_type_from_generic (ftype);
1900 if (type_has_references (klass, ftype))
1901 has_references = TRUE;
1906 * Compute field layout and total size (not considering static fields)
1908 field_offsets = g_new0 (int, top);
1909 fields_has_references = g_new0 (gboolean, top);
1910 int first_field_idx = mono_class_has_static_metadata (klass) ? mono_class_get_first_field_idx (klass) : 0;
1912 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1913 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1914 if (gc_aware_layout)
1919 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1922 if (klass->parent) {
1923 mono_class_setup_fields (klass->parent);
1924 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Cannot initialize parent class"))
1926 real_size = klass->parent->instance_size;
1928 real_size = sizeof (MonoObject);
1931 for (pass = 0; pass < passes; ++pass) {
1932 for (i = 0; i < top; i++){
1937 field = &klass->fields [i];
1939 if (mono_field_is_deleted (field))
1941 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1944 ftype = mono_type_get_underlying_type (field->type);
1945 ftype = mono_type_get_basic_type_from_generic (ftype);
1946 if (gc_aware_layout) {
1947 fields_has_references [i] = type_has_references (klass, ftype);
1948 if (fields_has_references [i]) {
1957 if ((top == 1) && (instance_size == sizeof (MonoObject)) &&
1958 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1959 /* This field is a hack inserted by MCS to empty structures */
1963 size = mono_type_size (field->type, &align);
1965 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1966 align = packing_size ? MIN (packing_size, align): align;
1967 /* if the field has managed references, we need to force-align it
1970 if (type_has_references (klass, ftype))
1971 align = MAX (align, sizeof (gpointer));
1973 min_align = MAX (align, min_align);
1974 field_offsets [i] = real_size;
1976 field_offsets [i] += align - 1;
1977 field_offsets [i] &= ~(align - 1);
1979 /*TypeBuilders produce all sort of weird things*/
1980 g_assert (image_is_dynamic (klass->image) || field_offsets [i] > 0);
1981 real_size = field_offsets [i] + size;
1984 /* Make SIMD types as big as a SIMD register since they can be stored into using simd stores */
1985 if (klass->simd_type)
1986 real_size = MAX (real_size, sizeof (MonoObject) + 16);
1987 instance_size = MAX (real_size, instance_size);
1989 if (instance_size & (min_align - 1)) {
1990 instance_size += min_align - 1;
1991 instance_size &= ~(min_align - 1);
1995 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1999 for (i = 0; i < top; i++) {
2004 field = &klass->fields [i];
2007 * There must be info about all the fields in a type if it
2008 * uses explicit layout.
2010 if (mono_field_is_deleted (field))
2012 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2015 size = mono_type_size (field->type, &align);
2016 align = packing_size ? MIN (packing_size, align): align;
2017 min_align = MAX (align, min_align);
2020 /* Already set by typebuilder_setup_fields () */
2021 field_offsets [i] = field->offset + sizeof (MonoObject);
2023 int idx = first_field_idx + i;
2025 mono_metadata_field_info (klass->image, idx, &offset, NULL, NULL);
2026 field_offsets [i] = offset + sizeof (MonoObject);
2028 ftype = mono_type_get_underlying_type (field->type);
2029 ftype = mono_type_get_basic_type_from_generic (ftype);
2030 if (type_has_references (klass, ftype)) {
2031 if (field_offsets [i] % sizeof (gpointer)) {
2032 mono_class_set_type_load_failure (klass, "Reference typed field '%s' has explicit offset that is not pointer-size aligned.", field->name);
2039 real_size = MAX (real_size, size + field_offsets [i]);
2042 if (klass->has_references) {
2043 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2045 /* Check for overlapping reference and non-reference fields */
2046 for (i = 0; i < top; i++) {
2049 field = &klass->fields [i];
2051 if (mono_field_is_deleted (field))
2053 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2055 ftype = mono_type_get_underlying_type (field->type);
2056 if (MONO_TYPE_IS_REFERENCE (ftype))
2057 ref_bitmap [field_offsets [i] / sizeof (gpointer)] = 1;
2059 for (i = 0; i < top; i++) {
2060 field = &klass->fields [i];
2062 if (mono_field_is_deleted (field))
2064 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2067 // FIXME: Too much code does this
2069 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field_offsets [i] / sizeof (gpointer)]) {
2070 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]);
2074 g_free (ref_bitmap);
2077 instance_size = MAX (real_size, instance_size);
2078 if (instance_size & (min_align - 1)) {
2079 instance_size += min_align - 1;
2080 instance_size &= ~(min_align - 1);
2086 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2088 * This leads to all kinds of problems with nested structs, so only
2089 * enable it when a MONO_DEBUG property is set.
2091 * For small structs, set min_align to at least the struct size to improve
2092 * performance, and since the JIT memset/memcpy code assumes this and generates
2093 * unaligned accesses otherwise. See #78990 for a testcase.
2095 if (mono_align_small_structs && top) {
2096 if (instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2097 min_align = MAX (min_align, instance_size - sizeof (MonoObject));
2101 if (klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR)
2102 instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
2103 else if (klass->byval_arg.type == MONO_TYPE_PTR)
2104 instance_size = sizeof (MonoObject) + sizeof (gpointer);
2106 if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2107 element_size = mono_class_array_element_size (klass->element_class);
2109 /* Publish the data */
2110 mono_loader_lock ();
2111 if (klass->instance_size && !klass->image->dynamic) {
2112 /* Might be already set using cached info */
2113 if (klass->instance_size != instance_size) {
2114 /* Emit info to help debugging */
2115 g_print ("%s\n", mono_class_full_name (klass));
2116 g_print ("%d %d %d %d\n", klass->instance_size, instance_size, klass->blittable, blittable);
2117 g_print ("%d %d %d %d\n", klass->has_references, has_references, klass->packing_size, packing_size);
2118 g_print ("%d %d\n", klass->min_align, min_align);
2119 for (i = 0; i < top; ++i) {
2120 field = &klass->fields [i];
2121 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2122 printf (" %s %d %d %d\n", klass->fields [i].name, klass->fields [i].offset, field_offsets [i], fields_has_references [i]);
2125 g_assert (klass->instance_size == instance_size);
2127 klass->instance_size = instance_size;
2129 klass->blittable = blittable;
2130 klass->has_references = has_references;
2131 klass->packing_size = packing_size;
2132 klass->min_align = min_align;
2133 for (i = 0; i < top; ++i) {
2134 field = &klass->fields [i];
2135 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
2136 klass->fields [i].offset = field_offsets [i];
2139 if (klass->byval_arg.type == MONO_TYPE_SZARRAY || klass->byval_arg.type == MONO_TYPE_ARRAY)
2140 klass->sizes.element_size = element_size;
2142 mono_memory_barrier ();
2143 klass->size_inited = 1;
2144 mono_loader_unlock ();
2147 * Compute static field layout and size
2148 * Static fields can reference the class itself, so this has to be
2149 * done after instance_size etc. are initialized.
2152 for (i = 0; i < top; i++) {
2156 field = &klass->fields [i];
2158 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2160 if (mono_field_is_deleted (field))
2163 if (mono_type_has_exceptions (field->type)) {
2164 mono_class_set_type_load_failure (klass, "Field '%s' has an invalid type.", field->name);
2168 has_static_fields = TRUE;
2170 size = mono_type_size (field->type, &align);
2171 field_offsets [i] = class_size;
2172 /*align is always non-zero here*/
2173 field_offsets [i] += align - 1;
2174 field_offsets [i] &= ~(align - 1);
2175 class_size = field_offsets [i] + size;
2178 if (has_static_fields && class_size == 0)
2179 /* Simplify code which depends on class_size != 0 if the class has static fields */
2182 /* Compute klass->has_static_refs */
2183 has_static_refs = FALSE;
2184 for (i = 0; i < top; i++) {
2187 field = &klass->fields [i];
2189 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
2190 ftype = mono_type_get_underlying_type (field->type);
2191 ftype = mono_type_get_basic_type_from_generic (ftype);
2192 if (type_has_references (klass, ftype))
2193 has_static_refs = TRUE;
2197 /*valuetypes can't be neither bigger than 1Mb or empty. */
2198 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
2199 mono_class_set_type_load_failure (klass, "Value type instance size (%d) cannot be zero, negative, or bigger than 1Mb", klass->instance_size);
2201 /* Publish the data */
2202 mono_loader_lock ();
2204 klass->sizes.class_size = class_size;
2205 klass->has_static_refs = has_static_refs;
2206 for (i = 0; i < top; ++i) {
2207 field = &klass->fields [i];
2209 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2210 field->offset = field_offsets [i];
2213 mono_memory_barrier ();
2214 klass->fields_inited = 1;
2215 mono_loader_unlock ();
2217 g_free (field_offsets);
2218 g_free (fields_has_references);
2222 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2226 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2227 method->klass = klass;
2228 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2229 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2230 method->signature = sig;
2231 method->name = name;
2234 if (name [0] == '.') {
2235 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2237 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2243 * mono_class_setup_methods:
2246 * Initializes the 'methods' array in CLASS.
2247 * Calling this method should be avoided if possible since it allocates a lot
2248 * of long-living MonoMethod structures.
2249 * Methods belonging to an interface are assigned a sequential slot starting
2252 * On failure this function sets klass->has_failure and stores a MonoErrorBoxed with details
2255 mono_class_setup_methods (MonoClass *klass)
2258 MonoMethod **methods;
2263 if (mono_class_is_ginst (klass)) {
2265 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2267 mono_class_init (gklass);
2268 if (!mono_class_has_failure (gklass))
2269 mono_class_setup_methods (gklass);
2270 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2273 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2274 count = mono_class_get_method_count (gklass);
2275 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2277 for (i = 0; i < count; i++) {
2278 methods [i] = mono_class_inflate_generic_method_full_checked (
2279 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2280 if (!mono_error_ok (&error)) {
2281 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2282 mono_class_set_type_load_failure (klass, "Could not inflate method %s due to %s", method, mono_error_get_message (&error));
2285 mono_error_cleanup (&error);
2289 } else if (klass->rank) {
2291 MonoMethod *amethod;
2292 MonoMethodSignature *sig;
2293 int count_generic = 0, first_generic = 0;
2295 gboolean jagged_ctor = FALSE;
2297 count = 3 + (klass->rank > 1? 2: 1);
2299 mono_class_setup_interfaces (klass, &error);
2300 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2302 if (klass->rank == 1 && klass->element_class->rank) {
2307 if (klass->interface_count) {
2308 count_generic = generic_array_methods (klass);
2309 first_generic = count;
2310 count += klass->interface_count * count_generic;
2313 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2315 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2316 sig->ret = &mono_defaults.void_class->byval_arg;
2317 sig->pinvoke = TRUE;
2318 sig->hasthis = TRUE;
2319 for (i = 0; i < klass->rank; ++i)
2320 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2322 amethod = create_array_method (klass, ".ctor", sig);
2323 methods [method_num++] = amethod;
2324 if (klass->rank > 1) {
2325 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2326 sig->ret = &mono_defaults.void_class->byval_arg;
2327 sig->pinvoke = TRUE;
2328 sig->hasthis = TRUE;
2329 for (i = 0; i < klass->rank * 2; ++i)
2330 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2332 amethod = create_array_method (klass, ".ctor", sig);
2333 methods [method_num++] = amethod;
2337 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2338 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2339 sig->ret = &mono_defaults.void_class->byval_arg;
2340 sig->pinvoke = TRUE;
2341 sig->hasthis = TRUE;
2342 for (i = 0; i < klass->rank + 1; ++i)
2343 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2344 amethod = create_array_method (klass, ".ctor", sig);
2345 methods [method_num++] = amethod;
2348 /* element Get (idx11, [idx2, ...]) */
2349 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2350 sig->ret = &klass->element_class->byval_arg;
2351 sig->pinvoke = TRUE;
2352 sig->hasthis = TRUE;
2353 for (i = 0; i < klass->rank; ++i)
2354 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2355 amethod = create_array_method (klass, "Get", sig);
2356 methods [method_num++] = amethod;
2357 /* element& Address (idx11, [idx2, ...]) */
2358 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2359 sig->ret = &klass->element_class->this_arg;
2360 sig->pinvoke = TRUE;
2361 sig->hasthis = TRUE;
2362 for (i = 0; i < klass->rank; ++i)
2363 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2364 amethod = create_array_method (klass, "Address", sig);
2365 methods [method_num++] = amethod;
2366 /* void Set (idx11, [idx2, ...], element) */
2367 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2368 sig->ret = &mono_defaults.void_class->byval_arg;
2369 sig->pinvoke = TRUE;
2370 sig->hasthis = TRUE;
2371 for (i = 0; i < klass->rank; ++i)
2372 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2373 sig->params [i] = &klass->element_class->byval_arg;
2374 amethod = create_array_method (klass, "Set", sig);
2375 methods [method_num++] = amethod;
2377 GHashTable *cache = g_hash_table_new (NULL, NULL);
2378 for (i = 0; i < klass->interface_count; i++)
2379 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic, cache);
2380 g_hash_table_destroy (cache);
2381 } else if (mono_class_has_static_metadata (klass)) {
2383 int first_idx = mono_class_get_first_method_idx (klass);
2385 count = mono_class_get_method_count (klass);
2386 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2387 for (i = 0; i < count; ++i) {
2388 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, first_idx + i + 1);
2389 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2391 mono_class_set_type_load_failure (klass, "Could not load method %d due to %s", i, mono_error_get_message (&error));
2392 mono_error_cleanup (&error);
2396 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * 1);
2400 if (MONO_CLASS_IS_INTERFACE (klass)) {
2402 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2403 for (i = 0; i < count; ++i) {
2404 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2405 methods [i]->slot = slot++;
2409 mono_image_lock (klass->image);
2411 if (!klass->methods) {
2412 mono_class_set_method_count (klass, count);
2414 /* Needed because of the double-checking locking pattern */
2415 mono_memory_barrier ();
2417 klass->methods = methods;
2420 mono_image_unlock (klass->image);
2424 * mono_class_get_method_by_index:
2426 * Returns klass->methods [index], initializing klass->methods if neccesary.
2428 * LOCKING: Acquires the loader lock.
2431 mono_class_get_method_by_index (MonoClass *klass, int index)
2435 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2436 /* Avoid calling setup_methods () if possible */
2437 if (gklass && !klass->methods) {
2440 m = mono_class_inflate_generic_method_full_checked (
2441 gklass->container_class->methods [index], klass, mono_class_get_context (klass), &error);
2442 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2444 * If setup_methods () is called later for this class, no duplicates are created,
2445 * since inflate_generic_method guarantees that only one instance of a method
2446 * is created for each context.
2449 mono_class_setup_methods (klass);
2450 g_assert (m == klass->methods [index]);
2454 mono_class_setup_methods (klass);
2455 if (mono_class_has_failure (klass)) /*FIXME do proper error handling*/
2457 g_assert (index >= 0 && index < mono_class_get_method_count (klass));
2458 return klass->methods [index];
2463 * mono_class_get_inflated_method:
2465 * Given an inflated class CLASS and a method METHOD which should be a method of
2466 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2469 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2471 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2474 g_assert (method->klass == gklass);
2476 mono_class_setup_methods (gklass);
2477 g_assert (!mono_class_has_failure (gklass)); /*FIXME do proper error handling*/
2479 mcount = mono_class_get_method_count (gklass);
2480 for (i = 0; i < mcount; ++i) {
2481 if (gklass->methods [i] == method) {
2482 if (klass->methods) {
2483 return klass->methods [i];
2486 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2487 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2497 * mono_class_get_vtable_entry:
2499 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2500 * LOCKING: Acquires the loader lock.
2503 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2507 if (klass->rank == 1) {
2509 * szarrays do not overwrite any methods of Array, so we can avoid
2510 * initializing their vtables in some cases.
2512 mono_class_setup_vtable (klass->parent);
2513 if (offset < klass->parent->vtable_size)
2514 return klass->parent->vtable [offset];
2517 if (mono_class_is_ginst (klass)) {
2519 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2520 mono_class_setup_vtable (gklass);
2521 m = gklass->vtable [offset];
2523 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2524 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2526 mono_class_setup_vtable (klass);
2527 if (mono_class_has_failure (klass))
2529 m = klass->vtable [offset];
2536 * mono_class_get_vtable_size:
2538 * Return the vtable size for KLASS.
2541 mono_class_get_vtable_size (MonoClass *klass)
2543 mono_class_setup_vtable (klass);
2545 return klass->vtable_size;
2549 * mono_class_setup_properties:
2551 * Initialize klass->ext.property and klass->ext.properties.
2553 * This method can fail the class.
2556 mono_class_setup_properties (MonoClass *klass)
2558 guint startm, endm, i, j;
2559 guint32 cols [MONO_PROPERTY_SIZE];
2560 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2561 MonoProperty *properties;
2564 MonoClassPropertyInfo *info;
2566 info = mono_class_get_property_info (klass);
2570 if (mono_class_is_ginst (klass)) {
2571 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2573 mono_class_init (gklass);
2574 mono_class_setup_properties (gklass);
2575 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2578 MonoClassPropertyInfo *ginfo = mono_class_get_property_info (gklass);
2579 properties = mono_class_new0 (klass, MonoProperty, ginfo->count + 1);
2581 for (i = 0; i < ginfo->count; i++) {
2583 MonoProperty *prop = &properties [i];
2585 *prop = ginfo->properties [i];
2588 prop->get = mono_class_inflate_generic_method_full_checked (
2589 prop->get, klass, mono_class_get_context (klass), &error);
2591 prop->set = mono_class_inflate_generic_method_full_checked (
2592 prop->set, klass, mono_class_get_context (klass), &error);
2594 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2595 prop->parent = klass;
2598 first = ginfo->first;
2599 count = ginfo->count;
2601 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2602 count = last - first;
2605 mono_class_setup_methods (klass);
2606 if (mono_class_has_failure (klass))
2610 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2611 for (i = first; i < last; ++i) {
2612 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2613 properties [i - first].parent = klass;
2614 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2615 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2617 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2618 int first_idx = mono_class_get_first_method_idx (klass);
2619 for (j = startm; j < endm; ++j) {
2622 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2624 if (klass->image->uncompressed_metadata) {
2626 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2627 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2628 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2630 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2633 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2634 case METHOD_SEMANTIC_SETTER:
2635 properties [i - first].set = method;
2637 case METHOD_SEMANTIC_GETTER:
2638 properties [i - first].get = method;
2647 info = mono_class_alloc0 (klass, sizeof (MonoClassPropertyInfo));
2648 info->first = first;
2649 info->count = count;
2650 info->properties = properties;
2651 mono_memory_barrier ();
2653 /* This might leak 'info' which was allocated from the image mempool */
2654 mono_class_set_property_info (klass, info);
2658 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2660 MonoMethod **om, **retval;
2663 for (om = methods, count = 0; *om; ++om, ++count)
2666 retval = g_new0 (MonoMethod*, count + 1);
2668 for (om = methods, count = 0; *om; ++om, ++count) {
2670 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2671 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2677 /*This method can fail the class.*/
2679 mono_class_setup_events (MonoClass *klass)
2682 guint startm, endm, i, j;
2683 guint32 cols [MONO_EVENT_SIZE];
2684 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2688 MonoClassEventInfo *info = mono_class_get_event_info (klass);
2692 if (mono_class_is_ginst (klass)) {
2693 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
2694 MonoGenericContext *context = NULL;
2696 mono_class_setup_events (gklass);
2697 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to load"))
2700 MonoClassEventInfo *ginfo = mono_class_get_event_info (gklass);
2701 first = ginfo->first;
2702 count = ginfo->count;
2704 events = mono_class_new0 (klass, MonoEvent, count);
2707 context = mono_class_get_context (klass);
2709 for (i = 0; i < count; i++) {
2711 MonoEvent *event = &events [i];
2712 MonoEvent *gevent = &ginfo->events [i];
2714 error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2716 event->parent = klass;
2717 event->name = gevent->name;
2718 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2719 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2720 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2721 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2722 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2723 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2725 #ifndef MONO_SMALL_CONFIG
2726 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2728 event->attrs = gevent->attrs;
2731 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2732 count = last - first;
2735 mono_class_setup_methods (klass);
2736 if (mono_class_has_failure (klass)) {
2741 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2742 for (i = first; i < last; ++i) {
2743 MonoEvent *event = &events [i - first];
2745 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2746 event->parent = klass;
2747 event->attrs = cols [MONO_EVENT_FLAGS];
2748 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2750 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2751 int first_idx = mono_class_get_first_method_idx (klass);
2752 for (j = startm; j < endm; ++j) {
2755 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2757 if (klass->image->uncompressed_metadata) {
2759 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2760 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2761 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2763 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - first_idx];
2766 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2767 case METHOD_SEMANTIC_ADD_ON:
2768 event->add = method;
2770 case METHOD_SEMANTIC_REMOVE_ON:
2771 event->remove = method;
2773 case METHOD_SEMANTIC_FIRE:
2774 event->raise = method;
2776 case METHOD_SEMANTIC_OTHER: {
2777 #ifndef MONO_SMALL_CONFIG
2780 if (event->other == NULL) {
2781 event->other = g_new0 (MonoMethod*, 2);
2783 while (event->other [n])
2785 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2787 event->other [n] = method;
2788 /* NULL terminated */
2789 event->other [n + 1] = NULL;
2800 info = mono_class_alloc0 (klass, sizeof (MonoClassEventInfo));
2801 info->events = events;
2802 info->first = first;
2803 info->count = count;
2805 mono_memory_barrier ();
2807 mono_class_set_event_info (klass, info);
2811 * Global pool of interface IDs, represented as a bitset.
2812 * LOCKING: Protected by the classes lock.
2814 static MonoBitSet *global_interface_bitset = NULL;
2817 * mono_unload_interface_ids:
2818 * @bitset: bit set of interface IDs
2820 * When an image is unloaded, the interface IDs associated with
2821 * the image are put back in the global pool of IDs so the numbers
2825 mono_unload_interface_ids (MonoBitSet *bitset)
2828 mono_bitset_sub (global_interface_bitset, bitset);
2833 mono_unload_interface_id (MonoClass *klass)
2835 if (global_interface_bitset && klass->interface_id) {
2837 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2843 * mono_get_unique_iid:
2844 * \param klass interface
2846 * Assign a unique integer ID to the interface represented by \p klass.
2847 * The ID will positive and as small as possible.
2848 * LOCKING: Acquires the classes lock.
2849 * \returns The new ID.
2852 mono_get_unique_iid (MonoClass *klass)
2856 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2860 if (!global_interface_bitset) {
2861 global_interface_bitset = mono_bitset_new (128, 0);
2864 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2866 int old_size = mono_bitset_size (global_interface_bitset);
2867 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2868 mono_bitset_free (global_interface_bitset);
2869 global_interface_bitset = new_set;
2872 mono_bitset_set (global_interface_bitset, iid);
2873 /* set the bit also in the per-image set */
2874 if (!mono_class_is_ginst (klass)) {
2875 if (klass->image->interface_bitset) {
2876 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2877 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2878 mono_bitset_free (klass->image->interface_bitset);
2879 klass->image->interface_bitset = new_set;
2882 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2884 mono_bitset_set (klass->image->interface_bitset, iid);
2889 #ifndef MONO_SMALL_CONFIG
2890 if (mono_print_vtable) {
2892 char *type_name = mono_type_full_name (&klass->byval_arg);
2893 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
2894 if (gklass && !gklass->context.class_inst->is_open) {
2895 generic_id = gklass->context.class_inst->id;
2896 g_assert (generic_id != 0);
2900 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2905 /* I've confirmed iids safe past 16 bits, however bitset code uses a signed int while testing.
2906 * Once this changes, it should be safe for us to allow 2^32-1 interfaces, until then 2^31-2 is the max. */
2907 g_assert (iid < INT_MAX);
2912 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, GHashTable **ifaces, MonoError *error)
2917 mono_class_setup_interfaces (klass, error);
2918 return_if_nok (error);
2920 for (i = 0; i < klass->interface_count; i++) {
2921 ic = klass->interfaces [i];
2924 *res = g_ptr_array_new ();
2925 if (*ifaces == NULL)
2926 *ifaces = g_hash_table_new (NULL, NULL);
2927 if (g_hash_table_lookup (*ifaces, ic))
2929 /* A gparam is not an implemented interface for the purposes of
2930 * mono_class_get_implemented_interfaces */
2931 if (mono_class_is_gparam (ic))
2933 g_ptr_array_add (*res, ic);
2934 g_hash_table_insert (*ifaces, ic, ic);
2935 mono_class_init (ic);
2936 if (mono_class_has_failure (ic)) {
2937 mono_error_set_type_load_class (error, ic, "Error Loading class");
2941 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2942 return_if_nok (error);
2947 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2949 GPtrArray *res = NULL;
2950 GHashTable *ifaces = NULL;
2952 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2954 g_hash_table_destroy (ifaces);
2955 if (!mono_error_ok (error)) {
2957 g_ptr_array_free (res, TRUE);
2964 compare_interface_ids (const void *p_key, const void *p_element)
2966 const MonoClass *key = (const MonoClass *)p_key;
2967 const MonoClass *element = *(const MonoClass **)p_element;
2969 return (key->interface_id - element->interface_id);
2972 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2974 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2976 MonoClass **result = (MonoClass **)mono_binary_search (
2978 klass->interfaces_packed,
2979 klass->interface_offsets_count,
2980 sizeof (MonoClass *),
2981 compare_interface_ids);
2983 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2990 * mono_class_interface_offset_with_variance:
2992 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2993 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2995 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2997 * FIXME figure out MS disambiguation rules and fix this function.
3000 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
3002 int i = mono_class_interface_offset (klass, itf);
3003 *non_exact_match = FALSE;
3007 if (itf->is_array_special_interface && klass->rank < 2) {
3008 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
3010 for (i = 0; i < klass->interface_offsets_count; i++) {
3011 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
3012 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3013 *non_exact_match = TRUE;
3014 return klass->interface_offsets_packed [i];
3019 if (!mono_class_has_variant_generic_params (itf))
3022 for (i = 0; i < klass->interface_offsets_count; i++) {
3023 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3024 *non_exact_match = TRUE;
3025 return klass->interface_offsets_packed [i];
3033 print_implemented_interfaces (MonoClass *klass)
3037 GPtrArray *ifaces = NULL;
3039 int ancestor_level = 0;
3041 name = mono_type_get_full_name (klass);
3042 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3045 for (i = 0; i < klass->interface_offsets_count; i++)
3046 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3047 klass->interfaces_packed [i]->interface_id,
3048 klass->interface_offsets_packed [i],
3049 mono_class_get_method_count (klass->interfaces_packed [i]),
3050 klass->interfaces_packed [i]->name_space,
3051 klass->interfaces_packed [i]->name );
3052 printf ("Interface flags: ");
3053 for (i = 0; i <= klass->max_interface_id; i++)
3054 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3055 printf ("(%d,T)", i);
3057 printf ("(%d,F)", i);
3059 printf ("Dump interface flags:");
3060 #ifdef COMPRESSED_INTERFACE_BITMAP
3062 const uint8_t* p = klass->interface_bitmap;
3063 i = klass->max_interface_id;
3065 printf (" %d x 00 %02X", p [0], p [1]);
3071 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3072 printf (" %02X", klass->interface_bitmap [i]);
3075 while (klass != NULL) {
3076 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3077 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3078 if (!mono_error_ok (&error)) {
3079 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3080 mono_error_cleanup (&error);
3081 } else if (ifaces) {
3082 for (i = 0; i < ifaces->len; i++) {
3083 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3084 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3085 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3087 mono_class_interface_offset (klass, ic),
3088 mono_class_get_method_count (ic),
3092 g_ptr_array_free (ifaces, TRUE);
3095 klass = klass->parent;
3100 * Return the number of virtual methods.
3101 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3102 * Return -1 on failure.
3103 * FIXME It would be nice if this information could be cached somewhere.
3106 count_virtual_methods (MonoClass *klass)
3108 int i, mcount, vcount = 0;
3110 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3112 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3113 mono_class_setup_methods (klass);
3114 if (mono_class_has_failure (klass))
3117 mcount = mono_class_get_method_count (klass);
3118 for (i = 0; i < mcount; ++i) {
3119 flags = klass->methods [i]->flags;
3120 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3124 int first_idx = mono_class_get_first_method_idx (klass);
3125 mcount = mono_class_get_method_count (klass);
3126 for (i = 0; i < mcount; ++i) {
3127 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3129 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3137 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3145 m = (l + num_ifaces) / 2;
3146 if (interfaces_full [m] == ic)
3148 if (l == num_ifaces)
3150 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3159 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3161 int i = find_interface (num_ifaces, interfaces_full, ic);
3165 interface_offsets_full [i] = offset;
3168 for (i = 0; i < num_ifaces; ++i) {
3169 if (interfaces_full [i]) {
3171 if (interfaces_full [i]->interface_id < ic->interface_id)
3174 while (end < num_ifaces && interfaces_full [end]) end++;
3175 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3176 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3178 interfaces_full [i] = ic;
3179 interface_offsets_full [i] = offset;
3185 #ifdef COMPRESSED_INTERFACE_BITMAP
3188 * Compressed interface bitmap design.
3190 * Interface bitmaps take a large amount of memory, because their size is
3191 * linear with the maximum interface id assigned in the process (each interface
3192 * is assigned a unique id as it is loaded). The number of interface classes
3193 * is high because of the many implicit interfaces implemented by arrays (we'll
3194 * need to lazy-load them in the future).
3195 * Most classes implement a very small number of interfaces, so the bitmap is
3196 * sparse. This bitmap needs to be checked by interface casts, so access to the
3197 * needed bit must be fast and doable with few jit instructions.
3199 * The current compression format is as follows:
3200 * *) it is a sequence of one or more two-byte elements
3201 * *) the first byte in the element is the count of empty bitmap bytes
3202 * at the current bitmap position
3203 * *) the second byte in the element is an actual bitmap byte at the current
3206 * As an example, the following compressed bitmap bytes:
3207 * 0x07 0x01 0x00 0x7
3208 * correspond to the following bitmap:
3209 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3211 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3212 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3213 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3217 * mono_compress_bitmap:
3218 * \param dest destination buffer
3219 * \param bitmap bitmap buffer
3220 * \param size size of \p bitmap in bytes
3222 * This is a mono internal function.
3223 * The \p bitmap data is compressed into a format that is small but
3224 * still searchable in few instructions by the JIT and runtime.
3225 * The compressed data is stored in the buffer pointed to by the
3226 * \p dest array. Passing a NULL value for \p dest allows to just compute
3227 * the size of the buffer.
3228 * This compression algorithm assumes the bits set in the bitmap are
3229 * few and far between, like in interface bitmaps.
3230 * \returns The size of the compressed bitmap in bytes.
3233 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3237 const uint8_t *end = bitmap + size;
3238 while (bitmap < end) {
3239 if (*bitmap || numz == 255) {
3263 * mono_class_interface_match:
3264 * \param bitmap a compressed bitmap buffer
3265 * \param id the index to check in the bitmap
3267 * This is a mono internal function.
3268 * Checks if a bit is set in a compressed interface bitmap. \p id must
3269 * be already checked for being smaller than the maximum id encoded in the
3272 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3276 mono_class_interface_match (const uint8_t *bitmap, int id)
3279 id -= bitmap [0] * 8;
3283 return bitmap [1] & (1 << id);
3292 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3293 * LOCKING: Acquires the loader lock.
3296 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3300 int i, j, num_ifaces;
3302 MonoClass **interfaces_full = NULL;
3303 int *interface_offsets_full = NULL;
3305 GPtrArray **ifaces_array = NULL;
3306 int interface_offsets_count;
3308 mono_loader_lock ();
3310 mono_class_setup_supertypes (klass);
3312 /* compute maximum number of slots and maximum interface id */
3314 num_ifaces = 0; /* this can include duplicated ones */
3315 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3316 for (j = 0; j < klass->idepth; j++) {
3317 k = klass->supertypes [j];
3319 num_ifaces += k->interface_count;
3320 for (i = 0; i < k->interface_count; i++) {
3321 ic = k->interfaces [i];
3323 /* A gparam does not have any interface_id set. */
3324 if (! mono_class_is_gparam (ic))
3325 mono_class_init (ic);
3327 if (max_iid < ic->interface_id)
3328 max_iid = ic->interface_id;
3330 ifaces = mono_class_get_implemented_interfaces (k, &error);
3331 if (!mono_error_ok (&error)) {
3332 char *name = mono_type_get_full_name (k);
3333 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3335 mono_error_cleanup (&error);
3340 num_ifaces += ifaces->len;
3341 for (i = 0; i < ifaces->len; ++i) {
3342 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3343 if (max_iid < ic->interface_id)
3344 max_iid = ic->interface_id;
3346 ifaces_array [j] = ifaces;
3350 if (MONO_CLASS_IS_INTERFACE (klass)) {
3352 if (max_iid < klass->interface_id)
3353 max_iid = klass->interface_id;
3356 /* compute vtable offset for interfaces */
3357 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3358 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3360 for (i = 0; i < num_ifaces; i++)
3361 interface_offsets_full [i] = -1;
3363 /* skip the current class */
3364 for (j = 0; j < klass->idepth - 1; j++) {
3365 k = klass->supertypes [j];
3366 ifaces = ifaces_array [j];
3369 for (i = 0; i < ifaces->len; ++i) {
3371 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3373 /*Force the sharing of interface offsets between parent and subtypes.*/
3374 io = mono_class_interface_offset (k, ic);
3376 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3381 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3382 ifaces = ifaces_array [klass->idepth - 1];
3384 for (i = 0; i < ifaces->len; ++i) {
3386 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3387 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3389 count = count_virtual_methods (ic);
3391 char *name = mono_type_get_full_name (ic);
3392 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3401 if (MONO_CLASS_IS_INTERFACE (klass))
3402 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3404 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3405 if (interface_offsets_full [i] != -1)
3406 interface_offsets_count ++;
3409 /* Publish the data */
3410 klass->max_interface_id = max_iid;
3412 * We might get called multiple times:
3413 * - mono_class_init ()
3414 * - mono_class_setup_vtable ().
3415 * - mono_class_setup_interface_offsets ().
3416 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3417 * means we have to overwrite those when called from other places (#4440).
3419 if (klass->interfaces_packed) {
3421 g_assert (klass->interface_offsets_count == interface_offsets_count);
3425 klass->interface_offsets_count = interface_offsets_count;
3426 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3427 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3428 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3429 #ifdef COMPRESSED_INTERFACE_BITMAP
3430 bitmap = g_malloc0 (bsize);
3432 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3434 for (i = 0; i < interface_offsets_count; i++) {
3435 guint32 id = interfaces_full [i]->interface_id;
3436 bitmap [id >> 3] |= (1 << (id & 7));
3437 klass->interfaces_packed [i] = interfaces_full [i];
3438 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3440 #ifdef COMPRESSED_INTERFACE_BITMAP
3441 i = mono_compress_bitmap (NULL, bitmap, bsize);
3442 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3443 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3446 klass->interface_bitmap = bitmap;
3450 mono_loader_unlock ();
3452 g_free (interfaces_full);
3453 g_free (interface_offsets_full);
3454 for (i = 0; i < klass->idepth; i++) {
3455 ifaces = ifaces_array [i];
3457 g_ptr_array_free (ifaces, TRUE);
3459 g_free (ifaces_array);
3461 //printf ("JUST DONE: ");
3462 //print_implemented_interfaces (klass);
3468 * Setup interface offsets for interfaces.
3470 * - klass->max_interface_id
3471 * - klass->interface_offsets_count
3472 * - klass->interfaces_packed
3473 * - klass->interface_offsets_packed
3474 * - klass->interface_bitmap
3476 * This function can fail @class.
3479 mono_class_setup_interface_offsets (MonoClass *klass)
3481 setup_interface_offsets (klass, 0, FALSE);
3484 /*Checks if @klass has @parent as one of it's parents type gtd
3488 * Bar<T> : Foo<Bar<Bar<T>>>
3492 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3494 klass = mono_class_get_generic_type_definition (klass);
3495 parent = mono_class_get_generic_type_definition (parent);
3496 mono_class_setup_supertypes (klass);
3497 mono_class_setup_supertypes (parent);
3499 return klass->idepth >= parent->idepth &&
3500 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3504 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3506 MonoGenericInst *ginst;
3509 if (!mono_class_is_ginst (klass)) {
3510 mono_class_setup_vtable_full (klass, in_setup);
3511 return !mono_class_has_failure (klass);
3514 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3515 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3518 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3519 for (i = 0; i < ginst->type_argc; ++i) {
3521 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3523 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3524 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3525 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3527 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3528 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3536 * mono_class_setup_vtable:
3538 * Creates the generic vtable of CLASS.
3539 * Initializes the following fields in MonoClass:
3542 * Plus all the fields initialized by setup_interface_offsets ().
3543 * If there is an error during vtable construction, klass->has_failure
3544 * is set and details are stored in a MonoErrorBoxed.
3546 * LOCKING: Acquires the loader lock.
3549 mono_class_setup_vtable (MonoClass *klass)
3551 mono_class_setup_vtable_full (klass, NULL);
3555 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3558 MonoMethod **overrides;
3559 MonoGenericContext *context;
3567 if (MONO_CLASS_IS_INTERFACE (klass)) {
3568 /* This sets method->slot for all methods if this is an interface */
3569 mono_class_setup_methods (klass);
3573 if (mono_class_has_failure (klass))
3576 if (g_list_find (in_setup, klass))
3579 mono_loader_lock ();
3581 if (klass->vtable) {
3582 mono_loader_unlock ();
3586 UnlockedIncrement (&mono_stats.generic_vtable_count);
3587 in_setup = g_list_prepend (in_setup, klass);
3589 if (mono_class_is_ginst (klass)) {
3590 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3591 mono_loader_unlock ();
3592 g_list_remove (in_setup, klass);
3596 context = mono_class_get_context (klass);
3597 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3599 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3600 type_token = klass->type_token;
3603 if (image_is_dynamic (klass->image)) {
3604 /* Generic instances can have zero method overrides without causing any harm.
3605 * This is true since we don't do layout all over again for them, we simply inflate
3606 * the layout of the parent.
3608 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3609 if (!is_ok (&error)) {
3610 mono_loader_unlock ();
3611 g_list_remove (in_setup, klass);
3612 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3613 mono_error_cleanup (&error);
3617 /* The following call fails if there are missing methods in the type */
3618 /* FIXME it's probably a good idea to avoid this for generic instances. */
3619 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3623 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3625 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3629 mono_loader_unlock ();
3630 g_list_remove (in_setup, klass);
3635 #define DEBUG_INTERFACE_VTABLE_CODE 0
3636 #define TRACE_INTERFACE_VTABLE_CODE 0
3637 #define VERIFY_INTERFACE_VTABLE_CODE 0
3638 #define VTABLE_SELECTOR (1)
3640 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3641 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3642 if (!(VTABLE_SELECTOR)) break; \
3646 #define DEBUG_INTERFACE_VTABLE(stmt)
3649 #if TRACE_INTERFACE_VTABLE_CODE
3650 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3651 if (!(VTABLE_SELECTOR)) break; \
3655 #define TRACE_INTERFACE_VTABLE(stmt)
3658 #if VERIFY_INTERFACE_VTABLE_CODE
3659 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3660 if (!(VTABLE_SELECTOR)) break; \
3664 #define VERIFY_INTERFACE_VTABLE(stmt)
3668 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3670 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3674 GString *res = g_string_new ("");
3676 g_string_append_c (res, '(');
3677 for (i = 0; i < sig->param_count; ++i) {
3679 g_string_append_c (res, ',');
3680 mono_type_get_desc (res, sig->params [i], include_namespace);
3682 g_string_append (res, ")=>");
3683 if (sig->ret != NULL) {
3684 mono_type_get_desc (res, sig->ret, include_namespace);
3686 g_string_append (res, "NULL");
3689 g_string_free (res, FALSE);
3693 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3694 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3695 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3696 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3704 is_wcf_hack_disabled (void)
3706 static gboolean disabled;
3707 static gboolean inited = FALSE;
3709 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3716 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3718 MonoMethodSignature *cmsig, *imsig;
3719 if (strcmp (im->name, cm->name) == 0) {
3720 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3721 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3724 if (! slot_is_empty) {
3725 if (require_newslot) {
3726 if (! interface_is_explicitly_implemented_by_class) {
3727 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3730 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3731 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3735 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3738 cmsig = mono_method_signature (cm);
3739 imsig = mono_method_signature (im);
3740 if (!cmsig || !imsig) {
3741 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3745 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3746 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3747 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3748 TRACE_INTERFACE_VTABLE (printf ("]"));
3751 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3752 if (mono_security_core_clr_enabled ())
3753 mono_security_core_clr_check_override (klass, cm, im);
3755 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3756 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3757 char *body_name = mono_method_full_name (cm, TRUE);
3758 char *decl_name = mono_method_full_name (im, TRUE);
3759 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3767 MonoClass *ic = im->klass;
3768 const char *ic_name_space = ic->name_space;
3769 const char *ic_name = ic->name;
3772 if (! require_newslot) {
3773 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3776 if (cm->klass->rank == 0) {
3777 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3780 cmsig = mono_method_signature (cm);
3781 imsig = mono_method_signature (im);
3782 if (!cmsig || !imsig) {
3783 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3787 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3788 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3789 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3790 TRACE_INTERFACE_VTABLE (printf ("]"));
3793 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3794 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3797 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3798 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3801 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))) {
3802 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3806 subname = strstr (cm->name, ic_name_space);
3807 if (subname != cm->name) {
3808 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3811 subname += strlen (ic_name_space);
3812 if (subname [0] != '.') {
3813 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3817 if (strstr (subname, ic_name) != subname) {
3818 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3821 subname += strlen (ic_name);
3822 if (subname [0] != '.') {
3823 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3827 if (strcmp (subname, im->name) != 0) {
3828 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3832 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3833 if (mono_security_core_clr_enabled ())
3834 mono_security_core_clr_check_override (klass, cm, im);
3836 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3837 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3838 char *body_name = mono_method_full_name (cm, TRUE);
3839 char *decl_name = mono_method_full_name (im, TRUE);
3840 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3850 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3852 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3853 MonoMethod *method = key;
3854 MonoMethod *override = value;
3855 MonoClass *method_class = mono_method_get_class (method);
3856 MonoClass *override_class = mono_method_get_class (override);
3858 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3859 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3860 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3863 print_overrides (GHashTable *override_map, const char *message) {
3865 printf ("Override map \"%s\" START:\n", message);
3866 g_hash_table_foreach (override_map, foreach_override, NULL);
3867 printf ("Override map \"%s\" END.\n", message);
3869 printf ("Override map \"%s\" EMPTY.\n", message);
3873 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3874 char *full_name = mono_type_full_name (&klass->byval_arg);
3878 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3880 if (print_interfaces) {
3881 print_implemented_interfaces (klass);
3882 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3885 if (klass->parent) {
3886 parent_size = klass->parent->vtable_size;
3890 for (i = 0; i < size; ++i) {
3891 MonoMethod *cm = vtable [i];
3892 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3893 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3895 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3903 #if VERIFY_INTERFACE_VTABLE_CODE
3905 mono_method_try_get_vtable_index (MonoMethod *method)
3907 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3908 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3909 if (imethod->declaring->is_generic)
3910 return imethod->declaring->slot;
3912 return method->slot;
3916 mono_class_verify_vtable (MonoClass *klass)
3919 char *full_name = mono_type_full_name (&klass->byval_arg);
3921 printf ("*** Verifying VTable of class '%s' \n", full_name);
3925 if (!klass->methods)
3928 count = mono_class_method_count (klass);
3929 for (i = 0; i < count; ++i) {
3930 MonoMethod *cm = klass->methods [i];
3933 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3937 full_name = mono_method_full_name (cm, TRUE);
3939 slot = mono_method_try_get_vtable_index (cm);
3941 if (slot >= klass->vtable_size) {
3942 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3946 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3947 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3948 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3949 g_free (other_name);
3952 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3959 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3962 char *method_signature;
3965 for (index = 0; index < onum; ++index) {
3966 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3967 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3969 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3970 type_name = mono_type_full_name (&klass->byval_arg);
3971 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3972 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3973 g_free (method_signature);
3975 mono_class_setup_methods (klass);
3976 if (mono_class_has_failure (klass)) {
3977 char *name = mono_type_get_full_name (klass);
3978 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3982 mcount = mono_class_get_method_count (klass);
3983 for (index = 0; index < mcount; ++index) {
3984 MonoMethod *cm = klass->methods [index];
3985 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3987 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3988 g_free (method_signature);
3993 mono_method_get_method_definition (MonoMethod *method)
3995 while (method->is_inflated)
3996 method = ((MonoMethodInflated*)method)->declaring;
4001 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4005 for (i = 0; i < onum; ++i) {
4006 MonoMethod *decl = overrides [i * 2];
4007 MonoMethod *body = overrides [i * 2 + 1];
4009 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4010 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4014 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4015 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4016 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4018 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4022 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4023 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4024 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4026 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4030 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4031 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4035 body = mono_method_get_method_definition (body);
4036 decl = mono_method_get_method_definition (decl);
4038 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4039 char *body_name = mono_method_full_name (body, TRUE);
4040 char *decl_name = mono_method_full_name (decl, TRUE);
4041 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4051 mono_class_need_stelemref_method (MonoClass *klass)
4053 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4057 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4060 dslot = mono_method_get_vtable_slot (decl);
4062 mono_class_set_type_load_failure (klass, "");
4066 dslot += mono_class_interface_offset (klass, decl->klass);
4067 vtable [dslot] = override;
4068 if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4070 * If override from an interface, then it is an override of a default interface method,
4071 * don't override its slot.
4073 vtable [dslot]->slot = dslot;
4076 if (mono_security_core_clr_enabled ())
4077 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4083 * LOCKING: this is supposed to be called with the loader lock held.
4086 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4090 MonoMethod **vtable = NULL;
4091 int i, max_vtsize = 0, cur_slot = 0;
4093 GPtrArray *ifaces = NULL;
4094 GHashTable *override_map = NULL;
4096 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4097 int first_non_interface_slot;
4099 GSList *virt_methods = NULL, *l;
4100 int stelemref_slot = 0;
4105 if (overrides && !verify_class_overrides (klass, overrides, onum))
4108 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4109 if (!mono_error_ok (&error)) {
4110 char *name = mono_type_get_full_name (klass);
4111 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4113 mono_error_cleanup (&error);
4115 } else if (ifaces) {
4116 for (i = 0; i < ifaces->len; i++) {
4117 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4118 max_vtsize += mono_class_get_method_count (ic);
4120 g_ptr_array_free (ifaces, TRUE);
4124 if (klass->parent) {
4125 mono_class_init (klass->parent);
4126 mono_class_setup_vtable_full (klass->parent, in_setup);
4128 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4131 max_vtsize += klass->parent->vtable_size;
4132 cur_slot = klass->parent->vtable_size;
4135 max_vtsize += mono_class_get_method_count (klass);
4137 /*Array have a slot for stelemref*/
4138 if (mono_class_need_stelemref_method (klass)) {
4139 stelemref_slot = cur_slot;
4144 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4146 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4147 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4150 max_iid = klass->max_interface_id;
4151 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4153 /* Optimized version for generic instances */
4154 if (mono_class_is_ginst (klass)) {
4156 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4159 mono_class_setup_vtable_full (gklass, in_setup);
4160 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4163 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4164 klass->vtable_size = gklass->vtable_size;
4165 for (i = 0; i < gklass->vtable_size; ++i)
4166 if (gklass->vtable [i]) {
4167 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4168 if (!mono_error_ok (&error)) {
4169 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4170 mono_error_cleanup (&error);
4174 tmp [i]->slot = gklass->vtable [i]->slot;
4176 mono_memory_barrier ();
4177 klass->vtable = tmp;
4179 /* Have to set method->slot for abstract virtual methods */
4180 if (klass->methods && gklass->methods) {
4181 int mcount = mono_class_get_method_count (klass);
4182 for (i = 0; i < mcount; ++i)
4183 if (klass->methods [i]->slot == -1)
4184 klass->methods [i]->slot = gklass->methods [i]->slot;
4190 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4192 if (klass->parent && klass->parent->vtable_size) {
4193 MonoClass *parent = klass->parent;
4196 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4198 // Also inherit parent interface vtables, just as a starting point.
4199 // This is needed otherwise bug-77127.exe fails when the property methods
4200 // have different names in the iterface and the class, because for child
4201 // classes the ".override" information is not used anymore.
4202 for (i = 0; i < parent->interface_offsets_count; i++) {
4203 MonoClass *parent_interface = parent->interfaces_packed [i];
4204 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4205 /*FIXME this is now dead code as this condition will never hold true.
4206 Since interface offsets are inherited then the offset of an interface implemented
4207 by a parent will never be the out of it's vtable boundary.
4209 if (interface_offset >= parent->vtable_size) {
4210 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4213 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4214 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4215 int mcount = mono_class_get_method_count (parent_interface);
4216 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4217 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4218 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4219 parent_interface_offset + j, parent_interface_offset, j,
4220 interface_offset + j, interface_offset, j));
4227 /*Array have a slot for stelemref*/
4228 if (mono_class_need_stelemref_method (klass)) {
4229 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4231 method->slot = stelemref_slot;
4233 g_assert (method->slot == stelemref_slot);
4235 vtable [stelemref_slot] = method;
4238 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4240 /* Process overrides from interface default methods */
4241 // FIXME: Ordering between interfaces
4242 for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4243 ic = klass->interfaces_packed [ifindex];
4245 mono_class_setup_methods (ic);
4246 if (mono_class_has_failure (ic))
4249 MonoMethod **iface_overrides;
4251 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4253 for (int i = 0; i < iface_onum; i++) {
4254 MonoMethod *decl = iface_overrides [i*2];
4255 MonoMethod *override = iface_overrides [i*2 + 1];
4256 if (!apply_override (klass, vtable, decl, override))
4260 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4261 g_hash_table_insert (override_map, decl, override);
4263 g_free (iface_overrides);
4267 /* override interface methods */
4268 for (i = 0; i < onum; i++) {
4269 MonoMethod *decl = overrides [i*2];
4270 MonoMethod *override = overrides [i*2 + 1];
4271 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4272 if (!apply_override (klass, vtable, decl, override))
4276 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4277 g_hash_table_insert (override_map, decl, override);
4281 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4282 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4285 * Create a list of virtual methods to avoid calling
4286 * mono_class_get_virtual_methods () which is slow because of the metadata
4290 gpointer iter = NULL;
4293 virt_methods = NULL;
4294 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4295 virt_methods = g_slist_prepend (virt_methods, cm);
4297 if (mono_class_has_failure (klass))
4301 // Loop on all implemented interfaces...
4302 for (i = 0; i < klass->interface_offsets_count; i++) {
4303 MonoClass *parent = klass->parent;
4305 gboolean interface_is_explicitly_implemented_by_class;
4308 ic = klass->interfaces_packed [i];
4309 ic_offset = mono_class_interface_offset (klass, ic);
4311 mono_class_setup_methods (ic);
4312 if (mono_class_has_failure (ic))
4315 // Check if this interface is explicitly implemented (instead of just inherited)
4316 if (parent != NULL) {
4317 int implemented_interfaces_index;
4318 interface_is_explicitly_implemented_by_class = FALSE;
4319 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4320 if (ic == klass->interfaces [implemented_interfaces_index]) {
4321 interface_is_explicitly_implemented_by_class = TRUE;
4326 interface_is_explicitly_implemented_by_class = TRUE;
4329 // Loop on all interface methods...
4330 int mcount = mono_class_get_method_count (ic);
4331 for (im_index = 0; im_index < mcount; im_index++) {
4332 MonoMethod *im = ic->methods [im_index];
4333 int im_slot = ic_offset + im->slot;
4334 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4336 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4339 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4341 // If there is an explicit implementation, just use it right away,
4342 // otherwise look for a matching method
4343 if (override_im == NULL) {
4347 // First look for a suitable method among the class methods
4348 for (l = virt_methods; l; l = l->next) {
4349 cm = (MonoMethod *)l->data;
4350 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)));
4351 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4352 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4353 vtable [im_slot] = cm;
4354 /* Why do we need this? */
4359 TRACE_INTERFACE_VTABLE (printf ("\n"));
4360 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4364 // If the slot is still empty, look in all the inherited virtual methods...
4365 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4366 MonoClass *parent = klass->parent;
4367 // Reverse order, so that last added methods are preferred
4368 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4369 MonoMethod *cm = parent->vtable [cm_index];
4371 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));
4372 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4373 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4374 vtable [im_slot] = cm;
4375 /* Why do we need this? */
4381 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4383 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4387 if (vtable [im_slot] == NULL) {
4388 if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4389 TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
4390 vtable [im_slot] = im;
4394 g_assert (vtable [im_slot] == override_im);
4399 // If the class is not abstract, check that all its interface slots are full.
4400 // The check is done here and not directly at the end of the loop above because
4401 // it can happen (for injected generic array interfaces) that the same slot is
4402 // processed multiple times (those interfaces have overlapping slots), and it
4403 // will not always be the first pass the one that fills the slot.
4404 if (!mono_class_is_abstract (klass)) {
4405 for (i = 0; i < klass->interface_offsets_count; i++) {
4409 ic = klass->interfaces_packed [i];
4410 ic_offset = mono_class_interface_offset (klass, ic);
4412 int mcount = mono_class_get_method_count (ic);
4413 for (im_index = 0; im_index < mcount; im_index++) {
4414 MonoMethod *im = ic->methods [im_index];
4415 int im_slot = ic_offset + im->slot;
4417 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4420 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4421 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4422 if (vtable [im_slot] == NULL) {
4423 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4430 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4431 for (l = virt_methods; l; l = l->next) {
4432 cm = (MonoMethod *)l->data;
4434 * If the method is REUSE_SLOT, we must check in the
4435 * base class for a method to override.
4437 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4439 for (k = klass->parent; k ; k = k->parent) {
4444 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4445 MonoMethodSignature *cmsig, *m1sig;
4447 cmsig = mono_method_signature (cm);
4448 m1sig = mono_method_signature (m1);
4450 if (!cmsig || !m1sig) {
4451 /* FIXME proper error message */
4452 mono_class_set_type_load_failure (klass, "");
4456 if (!strcmp(cm->name, m1->name) &&
4457 mono_metadata_signature_equal (cmsig, m1sig)) {
4459 if (mono_security_core_clr_enabled ())
4460 mono_security_core_clr_check_override (klass, cm, m1);
4462 slot = mono_method_get_vtable_slot (m1);
4466 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4467 char *body_name = mono_method_full_name (cm, TRUE);
4468 char *decl_name = mono_method_full_name (m1, TRUE);
4469 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4475 g_assert (cm->slot < max_vtsize);
4477 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4478 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4479 mono_method_full_name (m1, 1), m1,
4480 mono_method_full_name (cm, 1), cm));
4481 g_hash_table_insert (override_map, m1, cm);
4485 if (mono_class_has_failure (k))
4495 /*Non final newslot methods must be given a non-interface vtable slot*/
4496 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4500 cm->slot = cur_slot++;
4502 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4503 vtable [cm->slot] = cm;
4506 /* override non interface methods */
4507 for (i = 0; i < onum; i++) {
4508 MonoMethod *decl = overrides [i*2];
4509 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4510 g_assert (decl->slot != -1);
4511 vtable [decl->slot] = overrides [i*2 + 1];
4512 overrides [i * 2 + 1]->slot = decl->slot;
4514 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4515 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4516 mono_method_full_name (decl, 1), decl,
4517 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4518 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4520 if (mono_security_core_clr_enabled ())
4521 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4526 * If a method occupies more than one place in the vtable, and it is
4527 * overriden, then change the other occurances too.
4532 for (i = 0; i < max_vtsize; ++i)
4534 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4536 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4541 g_hash_table_destroy (override_map);
4542 override_map = NULL;
4545 g_slist_free (virt_methods);
4546 virt_methods = NULL;
4548 g_assert (cur_slot <= max_vtsize);
4550 /* Ensure that all vtable slots are filled with concrete instance methods */
4551 if (!mono_class_is_abstract (klass)) {
4552 for (i = 0; i < cur_slot; ++i) {
4553 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4554 char *type_name = mono_type_get_full_name (klass);
4555 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4556 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4558 g_free (method_name);
4565 if (mono_class_is_ginst (klass)) {
4566 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4568 mono_class_init (gklass);
4570 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4572 /* Check that the vtable_size value computed in mono_class_init () is correct */
4573 if (klass->vtable_size)
4574 g_assert (cur_slot == klass->vtable_size);
4575 klass->vtable_size = cur_slot;
4578 /* Try to share the vtable with our parent. */
4579 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4580 mono_memory_barrier ();
4581 klass->vtable = klass->parent->vtable;
4583 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4584 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4585 mono_memory_barrier ();
4586 klass->vtable = tmp;
4589 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4590 if (mono_print_vtable) {
4593 print_implemented_interfaces (klass);
4595 for (i = 0; i <= max_iid; i++)
4596 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4599 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4600 klass->vtable_size, icount);
4602 for (i = 0; i < cur_slot; ++i) {
4607 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4608 mono_method_full_name (cm, TRUE));
4614 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4615 klass->name, max_iid);
4617 for (i = 0; i < klass->interface_count; i++) {
4618 ic = klass->interfaces [i];
4619 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4620 mono_class_interface_offset (klass, ic),
4621 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4624 for (k = klass->parent; k ; k = k->parent) {
4625 for (i = 0; i < k->interface_count; i++) {
4626 ic = k->interfaces [i];
4627 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4628 mono_class_interface_offset (klass, ic),
4629 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4637 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4642 char *name = mono_type_get_full_name (klass);
4643 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4647 g_hash_table_destroy (override_map);
4649 g_slist_free (virt_methods);
4654 * mono_method_get_vtable_slot:
4656 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4657 * LOCKING: Acquires the loader lock.
4659 * FIXME Use proper MonoError machinery here.
4662 mono_method_get_vtable_slot (MonoMethod *method)
4664 if (method->slot == -1) {
4665 mono_class_setup_vtable (method->klass);
4666 if (mono_class_has_failure (method->klass))
4668 if (method->slot == -1) {
4672 if (!mono_class_is_ginst (method->klass)) {
4673 g_assert (method->is_inflated);
4674 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4677 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4678 g_assert (mono_class_is_ginst (method->klass));
4679 gklass = mono_class_get_generic_class (method->klass)->container_class;
4680 mono_class_setup_methods (method->klass);
4681 g_assert (method->klass->methods);
4682 mcount = mono_class_get_method_count (method->klass);
4683 for (i = 0; i < mcount; ++i) {
4684 if (method->klass->methods [i] == method)
4687 g_assert (i < mcount);
4688 g_assert (gklass->methods);
4689 method->slot = gklass->methods [i]->slot;
4691 g_assert (method->slot != -1);
4693 return method->slot;
4697 * mono_method_get_vtable_index:
4698 * \param method a method
4700 * Returns the index into the runtime vtable to access the method or,
4701 * in the case of a virtual generic method, the virtual generic method
4702 * thunk. Returns -1 on failure.
4704 * FIXME Use proper MonoError machinery here.
4707 mono_method_get_vtable_index (MonoMethod *method)
4709 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4710 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4711 if (imethod->declaring->is_generic)
4712 return mono_method_get_vtable_slot (imethod->declaring);
4714 return mono_method_get_vtable_slot (method);
4717 static MonoMethod *default_ghc = NULL;
4718 static MonoMethod *default_finalize = NULL;
4719 static int finalize_slot = -1;
4720 static int ghc_slot = -1;
4723 initialize_object_slots (MonoClass *klass)
4728 if (klass == mono_defaults.object_class) {
4729 mono_class_setup_vtable (klass);
4730 for (i = 0; i < klass->vtable_size; ++i) {
4731 MonoMethod *cm = klass->vtable [i];
4733 if (!strcmp (cm->name, "GetHashCode"))
4735 else if (!strcmp (cm->name, "Finalize"))
4739 g_assert (ghc_slot > 0);
4740 default_ghc = klass->vtable [ghc_slot];
4742 g_assert (finalize_slot > 0);
4743 default_finalize = klass->vtable [finalize_slot];
4748 MonoMethod *array_method;
4750 } GenericArrayMethodInfo;
4752 static int generic_array_method_num = 0;
4753 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4756 generic_array_methods (MonoClass *klass)
4758 int i, count_generic = 0, mcount;
4759 GList *list = NULL, *tmp;
4760 if (generic_array_method_num)
4761 return generic_array_method_num;
4762 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4763 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4764 mcount = mono_class_get_method_count (klass->parent);
4765 for (i = 0; i < mcount; i++) {
4766 MonoMethod *m = klass->parent->methods [i];
4767 if (!strncmp (m->name, "InternalArray__", 15)) {
4769 list = g_list_prepend (list, m);
4772 list = g_list_reverse (list);
4773 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4775 for (tmp = list; tmp; tmp = tmp->next) {
4776 const char *mname, *iname;
4778 MonoMethod *m = (MonoMethod *)tmp->data;
4779 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4780 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4782 generic_array_method_info [i].array_method = m;
4783 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4784 iname = "System.Collections.Generic.ICollection`1.";
4785 mname = m->name + 27;
4786 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4787 iname = "System.Collections.Generic.IEnumerable`1.";
4788 mname = m->name + 27;
4789 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4790 iname = "System.Collections.Generic.IReadOnlyList`1.";
4791 mname = m->name + strlen (ireadonlylist_prefix);
4792 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4793 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4794 mname = m->name + strlen (ireadonlycollection_prefix);
4795 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4796 iname = "System.Collections.Generic.IList`1.";
4797 mname = m->name + 15;
4799 g_assert_not_reached ();
4802 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4803 strcpy (name, iname);
4804 strcpy (name + strlen (iname), mname);
4805 generic_array_method_info [i].name = name;
4808 /*g_print ("array generic methods: %d\n", count_generic);*/
4810 generic_array_method_num = count_generic;
4812 return generic_array_method_num;
4816 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4818 MonoGenericContext tmp_context;
4821 tmp_context.class_inst = NULL;
4822 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4823 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4825 for (i = 0; i < generic_array_method_num; i++) {
4827 MonoMethod *m = generic_array_method_info [i].array_method;
4828 MonoMethod *inflated, *helper;
4830 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4831 mono_error_assert_ok (&error);
4832 helper = g_hash_table_lookup (cache, inflated);
4834 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4835 g_hash_table_insert (cache, inflated, helper);
4837 methods [pos ++] = helper;
4842 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4844 int null_length = strlen ("(null)");
4845 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4846 char *s = (char *)mono_image_alloc (image, len);
4849 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4850 g_assert (result == len - 1);
4857 * \param klass the class to initialize
4859 * Compute the \c instance_size, \c class_size and other infos that cannot be
4860 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4861 * Initializes the following fields in \p klass:
4862 * - all the fields initialized by \c mono_class_init_sizes
4867 * LOCKING: Acquires the loader lock.
4869 * \returns TRUE on success or FALSE if there was a problem in loading
4870 * the type (incorrect assemblies, missing assemblies, methods, etc).
4873 mono_class_init (MonoClass *klass)
4875 int i, vtable_size = 0, array_method_count = 0;
4876 MonoCachedClassInfo cached_info;
4877 gboolean has_cached_info;
4878 gboolean locked = FALSE;
4879 gboolean ghcimpl = FALSE;
4880 gboolean has_cctor = FALSE;
4881 int first_iface_slot = 0;
4885 /* Double-checking locking pattern */
4886 if (klass->inited || mono_class_has_failure (klass))
4887 return !mono_class_has_failure (klass);
4889 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4892 * This function can recursively call itself.
4894 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4895 if (g_slist_find (init_list, klass)) {
4896 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4897 goto leave_no_init_pending;
4899 init_list = g_slist_prepend (init_list, klass);
4900 mono_native_tls_set_value (init_pending_tls_id, init_list);
4903 * We want to avoid doing complicated work inside locks, so we compute all the required
4904 * information and write it to @klass inside a lock.
4907 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4908 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4912 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4913 MonoClass *element_class = klass->element_class;
4914 if (!element_class->inited)
4915 mono_class_init (element_class);
4916 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4920 UnlockedIncrement (&mono_stats.initialized_class_count);
4922 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4923 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4925 mono_class_init (gklass);
4926 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4929 mono_class_setup_interface_id (klass);
4932 if (klass->parent && !klass->parent->inited)
4933 mono_class_init (klass->parent);
4935 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4937 /* Compute instance size etc. */
4938 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4939 if (mono_class_has_failure (klass))
4942 mono_class_setup_supertypes (klass);
4945 initialize_object_slots (klass);
4948 * Initialize the rest of the data without creating a generic vtable if possible.
4949 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4950 * also avoid computing a generic vtable.
4952 if (has_cached_info) {
4954 vtable_size = cached_info.vtable_size;
4955 ghcimpl = cached_info.ghcimpl;
4956 has_cctor = cached_info.has_cctor;
4957 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4958 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4959 * The first slot if for array with.
4961 static int szarray_vtable_size[2] = { 0 };
4963 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4966 if (!szarray_vtable_size [slot]) {
4967 mono_class_setup_vtable (klass);
4968 szarray_vtable_size [slot] = klass->vtable_size;
4969 vtable_size = klass->vtable_size;
4971 vtable_size = szarray_vtable_size[slot];
4973 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4974 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4976 /* Generic instance case */
4977 ghcimpl = gklass->ghcimpl;
4978 has_cctor = gklass->has_cctor;
4980 mono_class_setup_vtable (gklass);
4981 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4984 vtable_size = gklass->vtable_size;
4988 /* ghcimpl is not currently used
4990 if (klass->parent) {
4991 MonoMethod *cmethod = klass->vtable [ghc_slot];
4992 if (cmethod->is_inflated)
4993 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4994 if (cmethod == default_ghc) {
5000 /* C# doesn't allow interfaces to have cctors */
5001 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5002 MonoMethod *cmethod = NULL;
5004 if (mono_class_is_ginst (klass)) {
5005 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5007 /* Generic instance case */
5008 ghcimpl = gklass->ghcimpl;
5009 has_cctor = gklass->has_cctor;
5010 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5011 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5012 /* The find_method function ignores the 'flags' argument */
5013 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5016 mono_class_setup_methods (klass);
5017 if (mono_class_has_failure (klass))
5020 int mcount = mono_class_get_method_count (klass);
5021 for (i = 0; i < mcount; ++i) {
5022 MonoMethod *method = klass->methods [i];
5023 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5024 (strcmp (".cctor", method->name) == 0)) {
5034 array_method_count = 3 + (klass->rank > 1? 2: 1);
5036 if (klass->interface_count) {
5037 int count_generic = generic_array_methods (klass);
5038 array_method_count += klass->interface_count * count_generic;
5042 if (klass->parent) {
5043 if (!klass->parent->vtable_size)
5044 mono_class_setup_vtable (klass->parent);
5045 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5047 g_assert (klass->parent->vtable_size);
5048 first_iface_slot = klass->parent->vtable_size;
5049 if (mono_class_need_stelemref_method (klass))
5054 * Do the actual changes to @klass inside the loader lock
5056 mono_loader_lock ();
5059 if (klass->inited || mono_class_has_failure (klass)) {
5060 mono_loader_unlock ();
5061 /* Somebody might have gotten in before us */
5062 return !mono_class_has_failure (klass);
5065 UnlockedIncrement (&mono_stats.initialized_class_count);
5067 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5068 UnlockedIncrement (&mono_stats.generic_class_count);
5070 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5071 klass->nested_classes_inited = TRUE;
5072 klass->ghcimpl = ghcimpl;
5073 klass->has_cctor = has_cctor;
5075 klass->vtable_size = vtable_size;
5076 if (has_cached_info) {
5077 klass->has_finalize = cached_info.has_finalize;
5078 klass->has_finalize_inited = TRUE;
5081 mono_class_set_method_count (klass, array_method_count);
5083 mono_loader_unlock ();
5086 setup_interface_offsets (klass, first_iface_slot, TRUE);
5088 if (mono_security_core_clr_enabled ())
5089 mono_security_core_clr_check_inheritance (klass);
5091 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5092 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5097 init_list = mono_native_tls_get_value (init_pending_tls_id);
5098 init_list = g_slist_remove (init_list, klass);
5099 mono_native_tls_set_value (init_pending_tls_id, init_list);
5101 leave_no_init_pending:
5103 mono_loader_unlock ();
5105 /* Leave this for last */
5106 mono_loader_lock ();
5108 mono_loader_unlock ();
5110 return !mono_class_has_failure (klass);
5114 * mono_class_has_finalizer:
5116 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5120 mono_class_has_finalizer (MonoClass *klass)
5122 gboolean has_finalize = FALSE;
5124 if (klass->has_finalize_inited)
5125 return klass->has_finalize;
5127 /* Interfaces and valuetypes are not supposed to have finalizers */
5128 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5129 MonoMethod *cmethod = NULL;
5131 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5132 } else if (mono_class_is_ginst (klass)) {
5133 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5135 has_finalize = mono_class_has_finalizer (gklass);
5136 } else if (klass->parent && klass->parent->has_finalize) {
5137 has_finalize = TRUE;
5139 if (klass->parent) {
5141 * Can't search in metadata for a method named Finalize, because that
5142 * ignores overrides.
5144 mono_class_setup_vtable (klass);
5145 if (mono_class_has_failure (klass))
5148 cmethod = klass->vtable [finalize_slot];
5152 g_assert (klass->vtable_size > finalize_slot);
5154 if (klass->parent) {
5155 if (cmethod->is_inflated)
5156 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5157 if (cmethod != default_finalize)
5158 has_finalize = TRUE;
5164 mono_loader_lock ();
5165 if (!klass->has_finalize_inited) {
5166 klass->has_finalize = has_finalize ? 1 : 0;
5168 mono_memory_barrier ();
5169 klass->has_finalize_inited = TRUE;
5171 mono_loader_unlock ();
5173 return klass->has_finalize;
5177 mono_is_corlib_image (MonoImage *image)
5179 return image == mono_defaults.corlib;
5183 * LOCKING: this assumes the loader lock is held
5186 mono_class_setup_mono_type (MonoClass *klass)
5188 const char *name = klass->name;
5189 const char *nspace = klass->name_space;
5190 gboolean is_corlib = mono_is_corlib_image (klass->image);
5192 klass->this_arg.byref = 1;
5193 klass->this_arg.data.klass = klass;
5194 klass->this_arg.type = MONO_TYPE_CLASS;
5195 klass->byval_arg.data.klass = klass;
5196 klass->byval_arg.type = MONO_TYPE_CLASS;
5198 if (is_corlib && !strcmp (nspace, "System")) {
5199 if (!strcmp (name, "ValueType")) {
5201 * do not set the valuetype bit for System.ValueType.
5202 * klass->valuetype = 1;
5204 klass->blittable = TRUE;
5205 } else if (!strcmp (name, "Enum")) {
5207 * do not set the valuetype bit for System.Enum.
5208 * klass->valuetype = 1;
5210 klass->valuetype = 0;
5211 klass->enumtype = 0;
5212 } else if (!strcmp (name, "Object")) {
5213 klass->byval_arg.type = MONO_TYPE_OBJECT;
5214 klass->this_arg.type = MONO_TYPE_OBJECT;
5215 } else if (!strcmp (name, "String")) {
5216 klass->byval_arg.type = MONO_TYPE_STRING;
5217 klass->this_arg.type = MONO_TYPE_STRING;
5218 } else if (!strcmp (name, "TypedReference")) {
5219 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5220 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5224 if (klass->valuetype) {
5225 int t = MONO_TYPE_VALUETYPE;
5227 if (is_corlib && !strcmp (nspace, "System")) {
5230 if (!strcmp (name, "Boolean")) {
5231 t = MONO_TYPE_BOOLEAN;
5232 } else if (!strcmp(name, "Byte")) {
5234 klass->blittable = TRUE;
5238 if (!strcmp (name, "Char")) {
5243 if (!strcmp (name, "Double")) {
5245 klass->blittable = TRUE;
5249 if (!strcmp (name, "Int32")) {
5251 klass->blittable = TRUE;
5252 } else if (!strcmp(name, "Int16")) {
5254 klass->blittable = TRUE;
5255 } else if (!strcmp(name, "Int64")) {
5257 klass->blittable = TRUE;
5258 } else if (!strcmp(name, "IntPtr")) {
5260 klass->blittable = TRUE;
5264 if (!strcmp (name, "Single")) {
5266 klass->blittable = TRUE;
5267 } else if (!strcmp(name, "SByte")) {
5269 klass->blittable = TRUE;
5273 if (!strcmp (name, "UInt32")) {
5275 klass->blittable = TRUE;
5276 } else if (!strcmp(name, "UInt16")) {
5278 klass->blittable = TRUE;
5279 } else if (!strcmp(name, "UInt64")) {
5281 klass->blittable = TRUE;
5282 } else if (!strcmp(name, "UIntPtr")) {
5284 klass->blittable = TRUE;
5288 if (!strcmp (name, "TypedReference")) {
5289 t = MONO_TYPE_TYPEDBYREF;
5290 klass->blittable = TRUE;
5294 if (!strcmp (name, "Void")) {
5302 klass->byval_arg.type = (MonoTypeEnum)t;
5303 klass->this_arg.type = (MonoTypeEnum)t;
5306 if (MONO_CLASS_IS_INTERFACE (klass)) {
5307 klass->interface_id = mono_get_unique_iid (klass);
5309 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5310 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5311 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5312 * MS returns diferrent types based on which instance is called. For example:
5313 * object obj = new byte[10][];
5314 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5315 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5318 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5319 klass->is_array_special_interface = 1;
5326 * COM initialization is delayed until needed.
5327 * However when a [ComImport] attribute is present on a type it will trigger
5328 * the initialization. This is not a problem unless the BCL being executed
5329 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5332 init_com_from_comimport (MonoClass *klass)
5334 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5335 if (mono_security_core_clr_enabled ()) {
5336 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5337 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5338 /* but it can not be made available for application (i.e. user code) since all COM calls
5339 * are considered native calls. In this case we fail with a TypeLoadException (just like
5340 * Silverlight 2 does */
5341 mono_class_set_type_load_failure (klass, "");
5346 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5348 #endif /*DISABLE_COM*/
5351 * LOCKING: this assumes the loader lock is held
5354 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5356 gboolean system_namespace;
5357 gboolean is_corlib = mono_is_corlib_image (klass->image);
5359 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5361 /* if root of the hierarchy */
5362 if (system_namespace && !strcmp (klass->name, "Object")) {
5363 klass->parent = NULL;
5364 klass->instance_size = sizeof (MonoObject);
5367 if (!strcmp (klass->name, "<Module>")) {
5368 klass->parent = NULL;
5369 klass->instance_size = 0;
5373 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5374 /* Imported COM Objects always derive from __ComObject. */
5376 if (MONO_CLASS_IS_IMPORT (klass)) {
5377 init_com_from_comimport (klass);
5378 if (parent == mono_defaults.object_class)
5379 parent = mono_class_get_com_object_class ();
5383 /* set the parent to something useful and safe, but mark the type as broken */
5384 parent = mono_defaults.object_class;
5385 mono_class_set_type_load_failure (klass, "");
5389 klass->parent = parent;
5391 if (mono_class_is_ginst (parent) && !parent->name) {
5393 * If the parent is a generic instance, we may get
5394 * called before it is fully initialized, especially
5395 * before it has its name.
5400 #ifndef DISABLE_REMOTING
5401 klass->marshalbyref = parent->marshalbyref;
5402 klass->contextbound = parent->contextbound;
5405 klass->delegate = parent->delegate;
5407 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5408 mono_class_set_is_com_object (klass);
5410 if (system_namespace) {
5411 #ifndef DISABLE_REMOTING
5412 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5413 klass->marshalbyref = 1;
5415 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5416 klass->contextbound = 1;
5418 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5419 klass->delegate = 1;
5422 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5423 (strcmp (klass->parent->name_space, "System") == 0)))
5424 klass->valuetype = 1;
5425 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5426 klass->valuetype = klass->enumtype = 1;
5428 /*klass->enumtype = klass->parent->enumtype; */
5430 /* initialize com types if COM interfaces are present */
5432 if (MONO_CLASS_IS_IMPORT (klass))
5433 init_com_from_comimport (klass);
5435 klass->parent = NULL;
5441 * mono_class_setup_supertypes:
5444 * Build the data structure needed to make fast type checks work.
5445 * This currently sets two fields in @class:
5446 * - idepth: distance between @class and System.Object in the type
5448 * - supertypes: array of classes: each element has a class in the hierarchy
5449 * starting from @class up to System.Object
5451 * LOCKING: Acquires the loader lock.
5454 mono_class_setup_supertypes (MonoClass *klass)
5457 MonoClass **supertypes;
5459 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5463 if (klass->parent && !klass->parent->supertypes)
5464 mono_class_setup_supertypes (klass->parent);
5466 idepth = klass->parent->idepth + 1;
5470 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5471 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5473 if (klass->parent) {
5474 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5477 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5478 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5480 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5483 mono_memory_barrier ();
5485 mono_loader_lock ();
5486 klass->idepth = idepth;
5487 /* Needed so idepth is visible before supertypes is set */
5488 mono_memory_barrier ();
5489 klass->supertypes = supertypes;
5490 mono_loader_unlock ();
5494 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5496 return mono_class_get_generic_class (gclass)->container_class == user_data;
5500 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5502 MonoClass *gtd = (MonoClass*)user_data;
5503 /* Only try to fix generic instances of @gtd */
5504 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5507 /* Check if the generic instance has no parent. */
5508 if (gtd->parent && !gclass->parent)
5509 mono_generic_class_setup_parent (gclass, gtd);
5515 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5517 mono_class_set_type_load_failure (klass, "%s", msg);
5518 mono_error_set_type_load_class (error, klass, "%s", msg);
5522 * mono_class_create_from_typedef:
5523 * \param image: image where the token is valid
5524 * \param type_token: typedef token
5525 * \param error: used to return any error found while creating the type
5527 * Create the MonoClass* representing the specified type token.
5528 * \p type_token must be a TypeDef token.
5530 * FIXME: don't return NULL on failure, just let the caller figure it out.
5533 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5535 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5536 MonoClass *klass, *parent = NULL;
5537 guint32 cols [MONO_TYPEDEF_SIZE];
5538 guint32 cols_next [MONO_TYPEDEF_SIZE];
5539 guint tidx = mono_metadata_token_index (type_token);
5540 MonoGenericContext *context = NULL;
5541 const char *name, *nspace;
5543 MonoClass **interfaces;
5544 guint32 field_last, method_last;
5545 guint32 nesting_tokeen;
5549 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5550 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5554 mono_loader_lock ();
5556 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5557 mono_loader_unlock ();
5561 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5563 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5564 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5566 if (mono_metadata_has_generic_params (image, type_token)) {
5567 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5568 klass->class_kind = MONO_CLASS_GTD;
5569 UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
5572 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5573 klass->class_kind = MONO_CLASS_DEF;
5574 UnlockedAdd (&classes_size, sizeof (MonoClassDef));
5579 klass->name_space = nspace;
5581 MONO_PROFILER_RAISE (class_loading, (klass));
5583 klass->image = image;
5584 klass->type_token = type_token;
5585 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5587 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5590 * Check whether we're a generic type definition.
5592 if (mono_class_is_gtd (klass)) {
5593 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5594 generic_container->owner.klass = klass;
5595 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5596 context = &generic_container->context;
5597 mono_class_set_generic_container (klass, generic_container);
5598 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5599 canonical_inst->type = MONO_TYPE_GENERICINST;
5600 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5601 enable_gclass_recording ();
5604 if (cols [MONO_TYPEDEF_EXTENDS]) {
5606 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5608 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5609 /*WARNING: this must satisfy mono_metadata_type_hash*/
5610 klass->this_arg.byref = 1;
5611 klass->this_arg.data.klass = klass;
5612 klass->this_arg.type = MONO_TYPE_CLASS;
5613 klass->byval_arg.data.klass = klass;
5614 klass->byval_arg.type = MONO_TYPE_CLASS;
5616 parent = mono_class_get_checked (image, parent_token, error);
5617 if (parent && context) /* Always inflate */
5618 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5620 if (parent == NULL) {
5621 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5622 goto parent_failure;
5625 for (tmp = parent; tmp; tmp = tmp->parent) {
5627 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5628 goto parent_failure;
5630 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5631 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5632 goto parent_failure;
5637 mono_class_setup_parent (klass, parent);
5639 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5640 mono_class_setup_mono_type (klass);
5642 if (mono_class_is_gtd (klass))
5643 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5646 * This might access klass->byval_arg for recursion generated by generic constraints,
5647 * so it has to come after setup_mono_type ().
5649 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5650 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5651 if (!mono_error_ok (error)) {
5652 /*FIXME implement a mono_class_set_failure_from_mono_error */
5653 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5654 mono_loader_unlock ();
5655 MONO_PROFILER_RAISE (class_failed, (klass));
5660 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5664 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5668 klass->cast_class = klass->element_class = klass;
5669 if (mono_is_corlib_image (klass->image)) {
5670 switch (klass->byval_arg.type) {
5672 if (mono_defaults.byte_class)
5673 klass->cast_class = mono_defaults.byte_class;
5676 if (mono_defaults.sbyte_class)
5677 mono_defaults.sbyte_class = klass;
5680 if (mono_defaults.uint16_class)
5681 mono_defaults.uint16_class = klass;
5684 if (mono_defaults.int16_class)
5685 klass->cast_class = mono_defaults.int16_class;
5688 if (mono_defaults.uint32_class)
5689 mono_defaults.uint32_class = klass;
5692 if (mono_defaults.int32_class)
5693 klass->cast_class = mono_defaults.int32_class;
5696 if (mono_defaults.uint64_class)
5697 mono_defaults.uint64_class = klass;
5700 if (mono_defaults.int64_class)
5701 klass->cast_class = mono_defaults.int64_class;
5706 if (!klass->enumtype) {
5707 if (!mono_metadata_interfaces_from_typedef_full (
5708 image, type_token, &interfaces, &icount, FALSE, context, error)){
5710 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5711 mono_loader_unlock ();
5712 MONO_PROFILER_RAISE (class_failed, (klass));
5716 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5717 g_assert(icount <= 65535);
5719 klass->interfaces = interfaces;
5720 klass->interface_count = icount;
5721 klass->interfaces_inited = 1;
5724 /*g_print ("Load class %s\n", name);*/
5727 * Compute the field and method lists
5729 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5730 mono_class_set_first_field_idx (klass, first_field_idx);
5731 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5732 mono_class_set_first_method_idx (klass, first_method_idx);
5734 if (tt->rows > tidx){
5735 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5736 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5737 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5739 field_last = image->tables [MONO_TABLE_FIELD].rows;
5740 method_last = image->tables [MONO_TABLE_METHOD].rows;
5743 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5744 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5745 mono_class_set_field_count (klass, field_last - first_field_idx);
5746 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5747 mono_class_set_method_count (klass, method_last - first_method_idx);
5749 /* reserve space to store vector pointer in arrays */
5750 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5751 klass->instance_size += 2 * sizeof (gpointer);
5752 g_assert (mono_class_get_field_count (klass) == 0);
5755 if (klass->enumtype) {
5756 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5757 if (!enum_basetype) {
5758 /*set it to a default value as the whole runtime can't handle this to be null*/
5759 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5760 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5761 mono_loader_unlock ();
5762 MONO_PROFILER_RAISE (class_failed, (klass));
5765 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5769 * If we're a generic type definition, load the constraints.
5770 * We must do this after the class has been constructed to make certain recursive scenarios
5773 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5774 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5775 mono_loader_unlock ();
5776 MONO_PROFILER_RAISE (class_failed, (klass));
5780 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5781 if (!strncmp (name, "Vector", 6))
5782 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");
5783 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5784 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5785 klass->simd_type = 1;
5788 mono_loader_unlock ();
5790 MONO_PROFILER_RAISE (class_loaded, (klass));
5795 if (mono_class_is_gtd (klass))
5796 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5798 mono_class_setup_mono_type (klass);
5799 mono_loader_unlock ();
5800 MONO_PROFILER_RAISE (class_failed, (klass));
5804 /** Is klass a Nullable<T> ginst? */
5806 mono_class_is_nullable (MonoClass *klass)
5808 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5809 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5813 /** if klass is T? return T */
5815 mono_class_get_nullable_param (MonoClass *klass)
5817 g_assert (mono_class_is_nullable (klass));
5818 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5822 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5826 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5828 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5829 if (!mono_error_ok (&error)) {
5830 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5831 klass->parent = mono_defaults.object_class;
5832 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5833 mono_error_cleanup (&error);
5836 mono_loader_lock ();
5838 mono_class_setup_parent (klass, klass->parent);
5840 if (klass->enumtype) {
5841 klass->cast_class = gtd->cast_class;
5842 klass->element_class = gtd->element_class;
5844 mono_loader_unlock ();
5848 mono_type_is_primitive (MonoType *type)
5850 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5851 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5855 * Create the `MonoClass' for an instantiation of a generic type.
5856 * We only do this if we actually need it.
5859 mono_generic_class_get_class (MonoGenericClass *gclass)
5861 MonoClass *klass, *gklass;
5863 if (gclass->cached_class)
5864 return gclass->cached_class;
5866 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5868 gklass = gclass->container_class;
5870 if (gklass->nested_in) {
5871 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5872 klass->nested_in = gklass->nested_in;
5875 klass->name = gklass->name;
5876 klass->name_space = gklass->name_space;
5878 klass->image = gklass->image;
5879 klass->type_token = gklass->type_token;
5881 klass->class_kind = MONO_CLASS_GINST;
5883 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5885 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5886 klass->this_arg.type = klass->byval_arg.type;
5887 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5888 klass->this_arg.byref = TRUE;
5889 klass->enumtype = gklass->enumtype;
5890 klass->valuetype = gklass->valuetype;
5893 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5894 g_assert (gclass->context.class_inst);
5895 g_assert (gclass->context.class_inst->type_argc > 0);
5896 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5897 klass->simd_type = 1;
5899 klass->is_array_special_interface = gklass->is_array_special_interface;
5901 klass->cast_class = klass->element_class = klass;
5903 if (gclass->is_dynamic) {
5905 * 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.
5906 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5907 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5909 if (!gklass->wastypebuilder)
5912 if (klass->enumtype) {
5914 * For enums, gklass->fields might not been set, but instance_size etc. is
5915 * already set in mono_reflection_create_internal_class (). For non-enums,
5916 * these will be computed normally in mono_class_layout_fields ().
5918 klass->instance_size = gklass->instance_size;
5919 klass->sizes.class_size = gklass->sizes.class_size;
5920 klass->size_inited = 1;
5924 mono_loader_lock ();
5926 if (gclass->cached_class) {
5927 mono_loader_unlock ();
5928 return gclass->cached_class;
5931 if (record_gclass_instantiation > 0)
5932 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5934 if (mono_class_is_nullable (klass))
5935 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5937 MONO_PROFILER_RAISE (class_loading, (klass));
5939 mono_generic_class_setup_parent (klass, gklass);
5941 if (gclass->is_dynamic)
5942 mono_class_setup_supertypes (klass);
5944 mono_memory_barrier ();
5945 gclass->cached_class = klass;
5947 MONO_PROFILER_RAISE (class_loaded, (klass));
5949 ++class_ginst_count;
5950 inflated_classes_size += sizeof (MonoClassGenericInst);
5952 mono_loader_unlock ();
5958 get_image_for_container (MonoGenericContainer *container)
5961 if (container->is_anonymous) {
5962 result = container->owner.image;
5965 if (container->is_method) {
5966 MonoMethod *method = container->owner.method;
5967 g_assert_checked (method);
5968 klass = method->klass;
5970 klass = container->owner.klass;
5972 g_assert_checked (klass);
5973 result = klass->image;
5980 get_image_for_generic_param (MonoGenericParam *param)
5982 MonoGenericContainer *container = mono_generic_param_owner (param);
5983 g_assert_checked (container);
5984 return get_image_for_container (container);
5987 // Make a string in the designated image consisting of a single integer.
5988 #define INT_STRING_SIZE 16
5990 make_generic_name_string (MonoImage *image, int num)
5992 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5993 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5997 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5998 // pinfo is derived from param by the caller for us.
6000 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6002 MonoClass *klass, **ptr;
6004 MonoGenericContainer *container = mono_generic_param_owner (param);
6005 g_assert_checked (container);
6007 MonoImage *image = get_image_for_container (container);
6008 gboolean is_mvar = container->is_method;
6009 gboolean is_anonymous = container->is_anonymous;
6011 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6012 klass->class_kind = MONO_CLASS_GPARAM;
6013 UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
6014 UnlockedIncrement (&class_gparam_count);
6017 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6019 int n = mono_generic_param_num (param);
6020 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6024 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6025 } else if (is_mvar) {
6026 MonoMethod *omethod = container->owner.method;
6027 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6029 MonoClass *oklass = container->owner.klass;
6030 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6033 MONO_PROFILER_RAISE (class_loading, (klass));
6035 // Count non-NULL items in pinfo->constraints
6038 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6042 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6043 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6045 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6046 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6048 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6051 if (count - pos > 0) {
6052 klass->interface_count = count - pos;
6053 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6054 klass->interfaces_inited = TRUE;
6055 for (i = pos; i < count; i++)
6056 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6059 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6061 klass->inited = TRUE;
6062 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6063 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6065 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6066 klass->this_arg.type = klass->byval_arg.type;
6067 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6068 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6069 klass->this_arg.byref = TRUE;
6071 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6072 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6074 /*Init these fields to sane values*/
6075 klass->min_align = 1;
6077 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6078 * constrained to, the JIT depends on this.
6080 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6081 mono_memory_barrier ();
6082 klass->size_inited = 1;
6084 mono_class_setup_supertypes (klass);
6086 if (count - pos > 0) {
6087 mono_class_setup_vtable (klass->parent);
6088 if (mono_class_has_failure (klass->parent))
6089 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6091 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6097 #define FAST_CACHE_SIZE 16
6100 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6101 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6102 * we cache the MonoClasses.
6103 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6104 * LOCKING: Takes the image lock depending on @take_lock.
6107 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6109 int n = mono_generic_param_num (param);
6110 MonoImage *image = get_image_for_generic_param (param);
6111 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6112 MonoClass *klass = NULL;
6117 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6118 // For high numbers or constraints we have to use pointer hashes.
6119 if (param->gshared_constraint) {
6120 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6123 mono_image_lock (image);
6124 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6126 mono_image_unlock (image);
6131 if (n < FAST_CACHE_SIZE) {
6133 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6135 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6137 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6140 mono_image_lock (image);
6141 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6143 mono_image_unlock (image);
6150 * LOCKING: Image lock (param->image) must be held
6153 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6155 int n = mono_generic_param_num (param);
6156 MonoImage *image = get_image_for_generic_param (param);
6157 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6161 if (param->gshared_constraint) {
6162 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6164 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6165 mono_memory_barrier ();
6167 image->mvar_cache_constrained = ht;
6169 image->var_cache_constrained = ht;
6171 g_hash_table_insert (ht, param, klass);
6172 } else if (n < FAST_CACHE_SIZE) {
6174 /* Requires locking to avoid droping an already published class */
6175 if (!image->mvar_cache_fast)
6176 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6177 image->mvar_cache_fast [n] = klass;
6179 if (!image->var_cache_fast)
6180 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6181 image->var_cache_fast [n] = klass;
6184 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6186 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6188 ht = g_hash_table_new (NULL, NULL);
6189 mono_memory_barrier ();
6191 image->mvar_cache_slow = ht;
6193 image->var_cache_slow = ht;
6196 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6201 * LOCKING: Acquires the image lock (@image).
6204 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6206 MonoImage *image = get_image_for_generic_param (param);
6207 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6208 MonoClass *klass, *klass2;
6210 // If a klass already exists for this object and is cached, return it.
6211 if (pinfo) // Non-anonymous
6212 klass = pinfo->pklass;
6214 klass = get_anon_gparam_class (param, TRUE);
6219 // Create a new klass
6220 klass = make_generic_param_class (param, pinfo);
6222 // Now we need to cache the klass we created.
6223 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6224 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6225 // and allow our newly-created klass object to just leak.
6226 mono_memory_barrier ();
6228 mono_image_lock (image);
6230 // Here "klass2" refers to the klass potentially created by the other thread.
6231 if (pinfo) // Repeat check from above
6232 klass2 = pinfo->pklass;
6234 klass2 = get_anon_gparam_class (param, FALSE);
6241 pinfo->pklass = klass;
6243 set_anon_gparam_class (param, klass);
6245 mono_image_unlock (image);
6247 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6249 MONO_PROFILER_RAISE (class_failed, (klass2));
6251 MONO_PROFILER_RAISE (class_loaded, (klass));
6257 * mono_class_from_generic_parameter:
6258 * \param param Parameter to find/construct a class for.
6259 * \param arg2 Is ignored.
6260 * \param arg3 Is ignored.
6263 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6265 return mono_class_from_generic_parameter_internal (param);
6269 * mono_ptr_class_get:
6272 mono_ptr_class_get (MonoType *type)
6275 MonoClass *el_class;
6279 el_class = mono_class_from_mono_type (type);
6280 image = el_class->image;
6282 mono_image_lock (image);
6283 if (image->ptr_cache) {
6284 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6285 mono_image_unlock (image);
6289 mono_image_unlock (image);
6291 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6293 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6294 ++class_pointer_count;
6296 result->parent = NULL; /* no parent for PTR types */
6297 result->name_space = el_class->name_space;
6298 name = g_strdup_printf ("%s*", el_class->name);
6299 result->name = mono_image_strdup (image, name);
6300 result->class_kind = MONO_CLASS_POINTER;
6303 MONO_PROFILER_RAISE (class_loading, (result));
6305 result->image = el_class->image;
6306 result->inited = TRUE;
6307 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6308 result->cast_class = result->element_class = el_class;
6309 result->blittable = TRUE;
6311 result->byval_arg.type = MONO_TYPE_PTR;
6312 result->this_arg.type = result->byval_arg.type;
6313 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6314 result->this_arg.byref = TRUE;
6316 mono_class_setup_supertypes (result);
6318 mono_image_lock (image);
6319 if (image->ptr_cache) {
6321 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6322 mono_image_unlock (image);
6323 MONO_PROFILER_RAISE (class_failed, (result));
6327 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6329 g_hash_table_insert (image->ptr_cache, el_class, result);
6330 mono_image_unlock (image);
6332 MONO_PROFILER_RAISE (class_loaded, (result));
6338 mono_fnptr_class_get (MonoMethodSignature *sig)
6340 MonoClass *result, *cached;
6341 static GHashTable *ptr_hash = NULL;
6343 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6345 mono_loader_lock ();
6347 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6348 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6349 mono_loader_unlock ();
6353 result = g_new0 (MonoClass, 1);
6355 result->parent = NULL; /* no parent for PTR types */
6356 result->name_space = "System";
6357 result->name = "MonoFNPtrFakeClass";
6358 result->class_kind = MONO_CLASS_POINTER;
6360 result->image = mono_defaults.corlib; /* need to fix... */
6361 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6362 result->cast_class = result->element_class = result;
6363 result->byval_arg.type = MONO_TYPE_FNPTR;
6364 result->this_arg.type = result->byval_arg.type;
6365 result->this_arg.data.method = result->byval_arg.data.method = sig;
6366 result->this_arg.byref = TRUE;
6367 result->blittable = TRUE;
6368 result->inited = TRUE;
6370 mono_class_setup_supertypes (result);
6372 mono_loader_lock ();
6374 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6377 mono_loader_unlock ();
6381 MONO_PROFILER_RAISE (class_loading, (result));
6383 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6384 ++class_pointer_count;
6386 g_hash_table_insert (ptr_hash, sig, result);
6388 mono_loader_unlock ();
6390 MONO_PROFILER_RAISE (class_loaded, (result));
6396 * mono_class_from_mono_type:
6397 * \param type describes the type to return
6398 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6401 mono_class_from_mono_type (MonoType *type)
6403 switch (type->type) {
6404 case MONO_TYPE_OBJECT:
6405 return type->data.klass? type->data.klass: mono_defaults.object_class;
6406 case MONO_TYPE_VOID:
6407 return type->data.klass? type->data.klass: mono_defaults.void_class;
6408 case MONO_TYPE_BOOLEAN:
6409 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6410 case MONO_TYPE_CHAR:
6411 return type->data.klass? type->data.klass: mono_defaults.char_class;
6413 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6415 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6417 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6419 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6421 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6423 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6425 return type->data.klass? type->data.klass: mono_defaults.int_class;
6427 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6429 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6431 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6433 return type->data.klass? type->data.klass: mono_defaults.single_class;
6435 return type->data.klass? type->data.klass: mono_defaults.double_class;
6436 case MONO_TYPE_STRING:
6437 return type->data.klass? type->data.klass: mono_defaults.string_class;
6438 case MONO_TYPE_TYPEDBYREF:
6439 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6440 case MONO_TYPE_ARRAY:
6441 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6443 return mono_ptr_class_get (type->data.type);
6444 case MONO_TYPE_FNPTR:
6445 return mono_fnptr_class_get (type->data.method);
6446 case MONO_TYPE_SZARRAY:
6447 return mono_array_class_get (type->data.klass, 1);
6448 case MONO_TYPE_CLASS:
6449 case MONO_TYPE_VALUETYPE:
6450 return type->data.klass;
6451 case MONO_TYPE_GENERICINST:
6452 return mono_generic_class_get_class (type->data.generic_class);
6453 case MONO_TYPE_MVAR:
6455 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6457 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6458 g_assert_not_reached ();
6461 // Yes, this returns NULL, even if it is documented as not doing so, but there
6462 // is no way for the code to make it this far, due to the assert above.
6467 * mono_type_retrieve_from_typespec
6468 * \param image context where the image is created
6469 * \param type_spec typespec token
6470 * \param context the generic context used to evaluate generic instantiations in
6473 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6475 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6477 *did_inflate = FALSE;
6482 if (context && (context->class_inst || context->method_inst)) {
6483 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6485 if (!mono_error_ok (error)) {
6491 *did_inflate = TRUE;
6498 * mono_class_create_from_typespec
6499 * \param image context where the image is created
6500 * \param type_spec typespec token
6501 * \param context the generic context used to evaluate generic instantiations in
6504 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6507 gboolean inflated = FALSE;
6508 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6509 return_val_if_nok (error, NULL);
6510 ret = mono_class_from_mono_type (t);
6512 mono_metadata_free_type (t);
6517 * mono_bounded_array_class_get:
6518 * \param element_class element class
6519 * \param rank the dimension of the array class
6520 * \param bounded whenever the array has non-zero bounds
6521 * \returns A class object describing the array with element type \p element_type and
6522 * dimension \p rank.
6525 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6528 MonoClass *klass, *cached, *k;
6529 MonoClass *parent = NULL;
6530 GSList *list, *rootlist = NULL;
6534 g_assert (rank <= 255);
6537 /* bounded only matters for one-dimensional arrays */
6540 image = eclass->image;
6544 if (rank == 1 && !bounded) {
6546 * This case is very frequent not just during compilation because of calls
6547 * from mono_class_from_mono_type (), mono_array_new (),
6548 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6550 mono_os_mutex_lock (&image->szarray_cache_lock);
6551 if (!image->szarray_cache)
6552 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6553 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6554 mono_os_mutex_unlock (&image->szarray_cache_lock);
6556 mono_loader_lock ();
6557 if (!image->array_cache)
6558 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6559 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6560 for (list = rootlist; list; list = list->next) {
6561 k = (MonoClass *)list->data;
6562 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6567 mono_loader_unlock ();
6572 parent = mono_defaults.array_class;
6573 if (!parent->inited)
6574 mono_class_init (parent);
6576 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6578 klass->image = image;
6579 klass->name_space = eclass->name_space;
6580 klass->class_kind = MONO_CLASS_ARRAY;
6582 nsize = strlen (eclass->name);
6583 name = (char *)g_malloc (nsize + 2 + rank + 1);
6584 memcpy (name, eclass->name, nsize);
6587 memset (name + nsize + 1, ',', rank - 1);
6589 name [nsize + rank] = '*';
6590 name [nsize + rank + bounded] = ']';
6591 name [nsize + rank + bounded + 1] = 0;
6592 klass->name = mono_image_strdup (image, name);
6595 klass->type_token = 0;
6596 klass->parent = parent;
6597 klass->instance_size = mono_class_instance_size (klass->parent);
6599 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6600 /*Arrays of those two types are invalid.*/
6601 MonoError prepared_error;
6602 error_init (&prepared_error);
6603 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6604 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6605 mono_error_cleanup (&prepared_error);
6606 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6607 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6608 if (!ref_info_handle || eclass->wastypebuilder) {
6609 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6610 g_assert (ref_info_handle && !eclass->wastypebuilder);
6612 /* element_size -1 is ok as this is not an instantitable type*/
6613 klass->sizes.element_size = -1;
6615 klass->sizes.element_size = -1;
6617 mono_class_setup_supertypes (klass);
6619 if (mono_class_is_ginst (eclass))
6620 mono_class_init (eclass);
6621 if (!eclass->size_inited)
6622 mono_class_setup_fields (eclass);
6623 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6624 /*FIXME we fail the array type, but we have to let other fields be set.*/
6626 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6630 if (eclass->enumtype)
6631 klass->cast_class = eclass->element_class;
6633 klass->cast_class = eclass;
6635 switch (klass->cast_class->byval_arg.type) {
6637 klass->cast_class = mono_defaults.byte_class;
6640 klass->cast_class = mono_defaults.int16_class;
6643 #if SIZEOF_VOID_P == 4
6647 klass->cast_class = mono_defaults.int32_class;
6650 #if SIZEOF_VOID_P == 8
6654 klass->cast_class = mono_defaults.int64_class;
6660 klass->element_class = eclass;
6662 if ((rank > 1) || bounded) {
6663 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6664 klass->byval_arg.type = MONO_TYPE_ARRAY;
6665 klass->byval_arg.data.array = at;
6666 at->eklass = eclass;
6668 /* FIXME: complete.... */
6670 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6671 klass->byval_arg.data.klass = eclass;
6673 klass->this_arg = klass->byval_arg;
6674 klass->this_arg.byref = 1;
6677 MonoError prepared_error;
6678 error_init (&prepared_error);
6679 name = mono_type_get_full_name (klass);
6680 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6681 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6682 mono_error_cleanup (&prepared_error);
6686 mono_loader_lock ();
6688 /* Check cache again */
6690 if (rank == 1 && !bounded) {
6691 mono_os_mutex_lock (&image->szarray_cache_lock);
6692 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6693 mono_os_mutex_unlock (&image->szarray_cache_lock);
6695 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6696 for (list = rootlist; list; list = list->next) {
6697 k = (MonoClass *)list->data;
6698 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6705 mono_loader_unlock ();
6709 MONO_PROFILER_RAISE (class_loading, (klass));
6711 UnlockedAdd (&classes_size, sizeof (MonoClassArray));
6712 ++class_array_count;
6714 if (rank == 1 && !bounded) {
6715 mono_os_mutex_lock (&image->szarray_cache_lock);
6716 g_hash_table_insert (image->szarray_cache, eclass, klass);
6717 mono_os_mutex_unlock (&image->szarray_cache_lock);
6719 list = g_slist_append (rootlist, klass);
6720 g_hash_table_insert (image->array_cache, eclass, list);
6723 mono_loader_unlock ();
6725 MONO_PROFILER_RAISE (class_loaded, (klass));
6731 * mono_array_class_get:
6732 * \param element_class element class
6733 * \param rank the dimension of the array class
6734 * \returns A class object describing the array with element type \p element_type and
6735 * dimension \p rank.
6738 mono_array_class_get (MonoClass *eclass, guint32 rank)
6740 return mono_bounded_array_class_get (eclass, rank, FALSE);
6744 * mono_class_instance_size:
6745 * \param klass a class
6747 * Use to get the size of a class in bytes.
6749 * \returns The size of an object instance
6752 mono_class_instance_size (MonoClass *klass)
6754 if (!klass->size_inited)
6755 mono_class_init (klass);
6757 return klass->instance_size;
6761 * mono_class_min_align:
6762 * \param klass a class
6764 * Use to get the computed minimum alignment requirements for the specified class.
6766 * Returns: minimum alignment requirements
6769 mono_class_min_align (MonoClass *klass)
6771 if (!klass->size_inited)
6772 mono_class_init (klass);
6774 return klass->min_align;
6778 * mono_class_value_size:
6779 * \param klass a class
6781 * This function is used for value types, and return the
6782 * space and the alignment to store that kind of value object.
6784 * \returns the size of a value of kind \p klass
6787 mono_class_value_size (MonoClass *klass, guint32 *align)
6791 /* fixme: check disable, because we still have external revereces to
6792 * mscorlib and Dummy Objects
6794 /*g_assert (klass->valuetype);*/
6796 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6799 *align = klass->min_align;
6805 * mono_class_data_size:
6806 * \param klass a class
6808 * \returns The size of the static class data
6811 mono_class_data_size (MonoClass *klass)
6814 mono_class_init (klass);
6815 /* This can happen with dynamically created types */
6816 if (!klass->fields_inited)
6817 mono_class_setup_fields (klass);
6819 /* in arrays, sizes.class_size is unioned with element_size
6820 * and arrays have no static fields
6824 return klass->sizes.class_size;
6828 * Auxiliary routine to mono_class_get_field
6830 * Takes a field index instead of a field token.
6832 static MonoClassField *
6833 mono_class_get_field_idx (MonoClass *klass, int idx)
6835 mono_class_setup_fields (klass);
6836 if (mono_class_has_failure (klass))
6840 int first_field_idx = mono_class_get_first_field_idx (klass);
6841 int fcount = mono_class_get_field_count (klass);
6842 if (klass->image->uncompressed_metadata) {
6844 * first_field_idx points to the FieldPtr table, while idx points into the
6845 * Field table, so we have to do a search.
6847 /*FIXME this is broken for types with multiple fields with the same name.*/
6848 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6851 for (i = 0; i < fcount; ++i)
6852 if (mono_field_get_name (&klass->fields [i]) == name)
6853 return &klass->fields [i];
6854 g_assert_not_reached ();
6857 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6858 return &klass->fields [idx - first_field_idx];
6862 klass = klass->parent;
6868 * mono_class_get_field:
6869 * \param class the class to lookup the field.
6870 * \param field_token the field token
6872 * \returns A \c MonoClassField representing the type and offset of
6873 * the field, or a NULL value if the field does not belong to this
6877 mono_class_get_field (MonoClass *klass, guint32 field_token)
6879 int idx = mono_metadata_token_index (field_token);
6881 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6883 return mono_class_get_field_idx (klass, idx - 1);
6887 * mono_class_get_field_from_name:
6888 * \param klass the class to lookup the field.
6889 * \param name the field name
6891 * Search the class \p klass and its parents for a field with the name \p name.
6893 * \returns The \c MonoClassField pointer of the named field or NULL
6896 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6898 return mono_class_get_field_from_name_full (klass, name, NULL);
6902 * mono_class_get_field_from_name_full:
6903 * \param klass the class to lookup the field.
6904 * \param name the field name
6905 * \param type the type of the fields. This optional.
6907 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6909 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6910 * of its generic type definition.
6912 * \returns The MonoClassField pointer of the named field or NULL
6915 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6919 mono_class_setup_fields (klass);
6920 if (mono_class_has_failure (klass))
6924 int fcount = mono_class_get_field_count (klass);
6925 for (i = 0; i < fcount; ++i) {
6926 MonoClassField *field = &klass->fields [i];
6928 if (strcmp (name, mono_field_get_name (field)) != 0)
6932 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6933 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6938 klass = klass->parent;
6944 * mono_class_get_field_token:
6945 * \param field the field we need the token of
6947 * Get the token of a field. Note that the tokesn is only valid for the image
6948 * the field was loaded from. Don't use this function for fields in dynamic types.
6950 * \returns The token representing the field in the image it was loaded from.
6953 mono_class_get_field_token (MonoClassField *field)
6955 MonoClass *klass = field->parent;
6958 mono_class_setup_fields (klass);
6963 int first_field_idx = mono_class_get_first_field_idx (klass);
6964 int fcount = mono_class_get_field_count (klass);
6965 for (i = 0; i < fcount; ++i) {
6966 if (&klass->fields [i] == field) {
6967 int idx = first_field_idx + i + 1;
6969 if (klass->image->uncompressed_metadata)
6970 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6971 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6974 klass = klass->parent;
6977 g_assert_not_reached ();
6982 mono_field_get_index (MonoClassField *field)
6984 int index = field - field->parent->fields;
6985 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6991 * mono_class_get_field_default_value:
6993 * Return the default value of the field as a pointer into the metadata blob.
6996 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6999 guint32 constant_cols [MONO_CONSTANT_SIZE];
7001 MonoClass *klass = field->parent;
7002 MonoFieldDefaultValue *def_values;
7004 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7006 def_values = mono_class_get_field_def_values (klass);
7008 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7010 mono_class_set_field_def_values (klass, def_values);
7013 field_index = mono_field_get_index (field);
7015 if (!def_values [field_index].data) {
7016 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7020 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7022 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7023 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7024 mono_memory_barrier ();
7025 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7028 *def_type = def_values [field_index].def_type;
7029 return def_values [field_index].data;
7033 mono_property_get_index (MonoProperty *prop)
7035 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7036 int index = prop - info->properties;
7038 g_assert (index >= 0 && index < info->count);
7044 * mono_class_get_property_default_value:
7046 * Return the default value of the field as a pointer into the metadata blob.
7049 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7052 guint32 constant_cols [MONO_CONSTANT_SIZE];
7053 MonoClass *klass = property->parent;
7055 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7057 * We don't cache here because it is not used by C# so it's quite rare, but
7058 * we still do the lookup in klass->ext because that is where the data
7059 * is stored for dynamic assemblies.
7062 if (image_is_dynamic (klass->image)) {
7063 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7064 int prop_index = mono_property_get_index (property);
7065 if (info->def_values && info->def_values [prop_index].data) {
7066 *def_type = info->def_values [prop_index].def_type;
7067 return info->def_values [prop_index].data;
7071 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7075 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7076 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7077 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7081 * mono_class_get_event_token:
7084 mono_class_get_event_token (MonoEvent *event)
7086 MonoClass *klass = event->parent;
7090 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7092 for (i = 0; i < info->count; ++i) {
7093 if (&info->events [i] == event)
7094 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7097 klass = klass->parent;
7100 g_assert_not_reached ();
7105 * mono_class_get_property_from_name:
7106 * \param klass a class
7107 * \param name name of the property to lookup in the specified class
7109 * Use this method to lookup a property in a class
7110 * \returns the \c MonoProperty with the given name, or NULL if the property
7111 * does not exist on the \p klass.
7114 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7118 gpointer iter = NULL;
7119 while ((p = mono_class_get_properties (klass, &iter))) {
7120 if (! strcmp (name, p->name))
7123 klass = klass->parent;
7129 * mono_class_get_property_token:
7130 * \param prop MonoProperty to query
7132 * \returns The ECMA token for the specified property.
7135 mono_class_get_property_token (MonoProperty *prop)
7137 MonoClass *klass = prop->parent;
7141 gpointer iter = NULL;
7142 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7143 while ((p = mono_class_get_properties (klass, &iter))) {
7144 if (&info->properties [i] == prop)
7145 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7149 klass = klass->parent;
7152 g_assert_not_reached ();
7157 * mono_class_name_from_token:
7160 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7162 const char *name, *nspace;
7163 if (image_is_dynamic (image))
7164 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7166 switch (type_token & 0xff000000){
7167 case MONO_TOKEN_TYPE_DEF: {
7168 guint32 cols [MONO_TYPEDEF_SIZE];
7169 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7170 guint tidx = mono_metadata_token_index (type_token);
7172 if (tidx > tt->rows)
7173 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7175 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7176 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7177 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7178 if (strlen (nspace) == 0)
7179 return g_strdup_printf ("%s", name);
7181 return g_strdup_printf ("%s.%s", nspace, name);
7184 case MONO_TOKEN_TYPE_REF: {
7186 guint32 cols [MONO_TYPEREF_SIZE];
7187 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7188 guint tidx = mono_metadata_token_index (type_token);
7191 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7193 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7194 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7195 mono_error_cleanup (&error);
7199 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7200 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7201 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7202 if (strlen (nspace) == 0)
7203 return g_strdup_printf ("%s", name);
7205 return g_strdup_printf ("%s.%s", nspace, name);
7208 case MONO_TOKEN_TYPE_SPEC:
7209 return g_strdup_printf ("Typespec 0x%08x", type_token);
7211 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7216 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7218 if (image_is_dynamic (image))
7219 return g_strdup_printf ("DynamicAssembly %s", image->name);
7221 switch (type_token & 0xff000000){
7222 case MONO_TOKEN_TYPE_DEF:
7223 if (image->assembly)
7224 return mono_stringify_assembly_name (&image->assembly->aname);
7225 else if (image->assembly_name)
7226 return g_strdup (image->assembly_name);
7227 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7228 case MONO_TOKEN_TYPE_REF: {
7230 MonoAssemblyName aname;
7231 guint32 cols [MONO_TYPEREF_SIZE];
7232 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7233 guint32 idx = mono_metadata_token_index (type_token);
7236 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7238 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7239 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7240 mono_error_cleanup (&error);
7243 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7245 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7246 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7247 case MONO_RESOLUTION_SCOPE_MODULE:
7249 return g_strdup ("");
7250 case MONO_RESOLUTION_SCOPE_MODULEREF:
7252 return g_strdup ("");
7253 case MONO_RESOLUTION_SCOPE_TYPEREF:
7255 return g_strdup ("");
7256 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7257 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7258 return mono_stringify_assembly_name (&aname);
7260 g_assert_not_reached ();
7264 case MONO_TOKEN_TYPE_SPEC:
7266 return g_strdup ("");
7268 g_assert_not_reached ();
7275 * mono_class_get_full:
7276 * \param image the image where the class resides
7277 * \param type_token the token for the class
7278 * \param context the generic context used to evaluate generic instantiations in
7279 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7280 * \returns The \c MonoClass that represents \p type_token in \p image
7283 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7287 klass = mono_class_get_checked (image, type_token, &error);
7289 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7290 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7292 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7298 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7303 klass = mono_class_get_checked (image, type_token, error);
7305 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7306 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7311 * mono_class_get_checked:
7312 * \param image the image where the class resides
7313 * \param type_token the token for the class
7314 * \param error error object to return any error
7316 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7319 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7321 MonoClass *klass = NULL;
7325 if (image_is_dynamic (image)) {
7326 int table = mono_metadata_token_table (type_token);
7328 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7329 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7332 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7336 switch (type_token & 0xff000000){
7337 case MONO_TOKEN_TYPE_DEF:
7338 klass = mono_class_create_from_typedef (image, type_token, error);
7340 case MONO_TOKEN_TYPE_REF:
7341 klass = mono_class_from_typeref_checked (image, type_token, error);
7343 case MONO_TOKEN_TYPE_SPEC:
7344 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7347 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7351 /* Generic case, should be avoided for when a better error is possible. */
7352 if (!klass && mono_error_ok (error)) {
7353 char *name = mono_class_name_from_token (image, type_token);
7354 char *assembly = mono_assembly_name_from_token (image, type_token);
7355 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7363 * mono_type_get_checked:
7364 * \param image the image where the type resides
7365 * \param type_token the token for the type
7366 * \param context the generic context used to evaluate generic instantiations in
7367 * \param error Error handling context
7369 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7371 * \returns The MonoType that represents \p type_token in \p image
7374 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7376 MonoType *type = NULL;
7377 gboolean inflated = FALSE;
7381 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7382 if (image_is_dynamic (image)) {
7383 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7384 return_val_if_nok (error, NULL);
7385 return mono_class_get_type (klass);
7388 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7389 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7396 return mono_class_get_type (klass);
7399 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7406 MonoType *tmp = type;
7407 type = mono_class_get_type (mono_class_from_mono_type (type));
7408 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7409 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7410 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7412 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7414 if (type->type != tmp->type)
7417 mono_metadata_free_type (tmp);
7424 * \param image image where the class token will be looked up.
7425 * \param type_token a type token from the image
7426 * \returns the \c MonoClass with the given \p type_token on the \p image
7429 mono_class_get (MonoImage *image, guint32 type_token)
7431 return mono_class_get_full (image, type_token, NULL);
7435 * mono_image_init_name_cache:
7437 * Initializes the class name cache stored in image->name_cache.
7439 * LOCKING: Acquires the corresponding image lock.
7442 mono_image_init_name_cache (MonoImage *image)
7444 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7445 guint32 cols [MONO_TYPEDEF_SIZE];
7448 guint32 i, visib, nspace_index;
7449 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7451 if (image->name_cache)
7454 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7456 if (image_is_dynamic (image)) {
7457 mono_image_lock (image);
7458 if (image->name_cache) {
7459 /* Somebody initialized it before us */
7460 g_hash_table_destroy (the_name_cache);
7462 mono_atomic_store_release (&image->name_cache, the_name_cache);
7464 mono_image_unlock (image);
7468 /* Temporary hash table to avoid lookups in the nspace_table */
7469 name_cache2 = g_hash_table_new (NULL, NULL);
7471 for (i = 1; i <= t->rows; ++i) {
7472 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7473 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7475 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7476 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7478 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7480 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7481 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7483 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7484 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7485 if (!nspace_table) {
7486 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7487 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7488 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7491 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7494 /* Load type names from EXPORTEDTYPES table */
7496 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7497 guint32 cols [MONO_EXP_TYPE_SIZE];
7500 for (i = 0; i < t->rows; ++i) {
7501 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7503 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7504 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7508 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7509 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7511 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7512 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7513 if (!nspace_table) {
7514 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7515 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7516 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7519 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7523 g_hash_table_destroy (name_cache2);
7525 mono_image_lock (image);
7526 if (image->name_cache) {
7527 /* Somebody initialized it before us */
7528 g_hash_table_destroy (the_name_cache);
7530 mono_atomic_store_release (&image->name_cache, the_name_cache);
7532 mono_image_unlock (image);
7535 /*FIXME Only dynamic assemblies should allow this operation.*/
7537 * mono_image_add_to_name_cache:
7540 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7541 const char *name, guint32 index)
7543 GHashTable *nspace_table;
7544 GHashTable *name_cache;
7547 mono_image_init_name_cache (image);
7548 mono_image_lock (image);
7550 name_cache = image->name_cache;
7551 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7552 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7553 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7556 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7557 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7559 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7561 mono_image_unlock (image);
7570 find_nocase (gpointer key, gpointer value, gpointer user_data)
7572 char *name = (char*)key;
7573 FindUserData *data = (FindUserData*)user_data;
7575 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7576 data->value = value;
7580 * mono_class_from_name_case:
7581 * \param image The MonoImage where the type is looked up in
7582 * \param name_space the type namespace
7583 * \param name the type short name.
7584 * \deprecated use the mono_class_from_name_case_checked variant instead.
7586 * Obtains a \c MonoClass with a given namespace and a given name which
7587 * is located in the given \c MonoImage. The namespace and name
7588 * lookups are case insensitive.
7591 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7594 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7595 mono_error_cleanup (&error);
7601 * mono_class_from_name_case_checked:
7602 * \param image The MonoImage where the type is looked up in
7603 * \param name_space the type namespace
7604 * \param name the type short name.
7607 * Obtains a MonoClass with a given namespace and a given name which
7608 * is located in the given MonoImage. The namespace and name
7609 * lookups are case insensitive.
7611 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7612 * was not found. The \p error object will contain information about the problem
7616 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7618 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7619 guint32 cols [MONO_TYPEDEF_SIZE];
7626 if (image_is_dynamic (image)) {
7628 FindUserData user_data;
7630 mono_image_init_name_cache (image);
7631 mono_image_lock (image);
7633 user_data.key = name_space;
7634 user_data.value = NULL;
7635 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7637 if (user_data.value) {
7638 GHashTable *nspace_table = (GHashTable*)user_data.value;
7640 user_data.key = name;
7641 user_data.value = NULL;
7643 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7645 if (user_data.value)
7646 token = GPOINTER_TO_UINT (user_data.value);
7649 mono_image_unlock (image);
7652 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7658 /* add a cache if needed */
7659 for (i = 1; i <= t->rows; ++i) {
7660 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7661 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7663 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7664 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7666 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7668 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7669 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7670 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7671 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7677 return_nested_in (MonoClass *klass, char *nested)
7680 char *s = strchr (nested, '/');
7681 gpointer iter = NULL;
7688 while ((found = mono_class_get_nested_types (klass, &iter))) {
7689 if (strcmp (found->name, nested) == 0) {
7691 return return_nested_in (found, s);
7699 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7701 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7702 MonoImage *file_image;
7709 * The EXPORTEDTYPES table only contains public types, so have to search the
7711 * Note: image->modules contains the contents of the MODULEREF table, while
7712 * the real module list is in the FILE table.
7714 for (i = 0; i < file_table->rows; i++) {
7715 guint32 cols [MONO_FILE_SIZE];
7716 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7717 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7720 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7722 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7723 if (klass || !is_ok (error))
7732 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7734 GHashTable *nspace_table;
7735 MonoImage *loaded_image;
7744 // Checking visited images avoids stack overflows when cyclic references exist.
7745 if (g_hash_table_lookup (visited_images, image))
7748 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7750 if ((nested = strchr (name, '/'))) {
7751 int pos = nested - name;
7752 int len = strlen (name);
7755 memcpy (buf, name, len + 1);
7757 nested = buf + pos + 1;
7761 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7762 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7763 gboolean res = get_class_from_name (image, name_space, name, &klass);
7766 klass = search_modules (image, name_space, name, error);
7771 return klass ? return_nested_in (klass, nested) : NULL;
7777 mono_image_init_name_cache (image);
7778 mono_image_lock (image);
7780 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7783 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7785 mono_image_unlock (image);
7787 if (!token && image_is_dynamic (image) && image->modules) {
7788 /* Search modules as well */
7789 for (i = 0; i < image->module_count; ++i) {
7790 MonoImage *module = image->modules [i];
7792 klass = mono_class_from_name_checked (module, name_space, name, error);
7793 if (klass || !is_ok (error))
7799 klass = search_modules (image, name_space, name, error);
7800 if (klass || !is_ok (error))
7805 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7806 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7807 guint32 cols [MONO_EXP_TYPE_SIZE];
7810 idx = mono_metadata_token_index (token);
7812 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7814 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7815 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7816 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7819 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7821 return klass ? return_nested_in (klass, nested) : NULL;
7823 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7824 guint32 assembly_idx;
7826 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7828 mono_assembly_load_reference (image, assembly_idx - 1);
7829 g_assert (image->references [assembly_idx - 1]);
7830 if (image->references [assembly_idx - 1] == (gpointer)-1)
7832 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7834 return klass ? return_nested_in (klass, nested) : NULL;
7837 g_assert_not_reached ();
7841 token = MONO_TOKEN_TYPE_DEF | token;
7843 klass = mono_class_get_checked (image, token, error);
7845 return return_nested_in (klass, nested);
7850 * mono_class_from_name_checked:
7851 * \param image The MonoImage where the type is looked up in
7852 * \param name_space the type namespace
7853 * \param name the type short name.
7855 * Obtains a MonoClass with a given namespace and a given name which
7856 * is located in the given MonoImage.
7858 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7859 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7862 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7865 GHashTable *visited_images;
7867 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7869 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7871 g_hash_table_destroy (visited_images);
7877 * mono_class_from_name:
7878 * \param image The \c MonoImage where the type is looked up in
7879 * \param name_space the type namespace
7880 * \param name the type short name.
7882 * Obtains a \c MonoClass with a given namespace and a given name which
7883 * is located in the given \c MonoImage.
7885 * To reference nested classes, use the "/" character as a separator.
7886 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7887 * inside \c Foo, like this: "class Foo { class Bar {} }".
7890 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7895 klass = mono_class_from_name_checked (image, name_space, name, &error);
7896 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7902 * mono_class_load_from_name:
7903 * \param image The MonoImage where the type is looked up in
7904 * \param name_space the type namespace
7905 * \param name the type short name.
7907 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7908 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7909 * If they are missing. Thing of System.Object or System.String.
7912 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7917 klass = mono_class_from_name_checked (image, name_space, name, &error);
7919 g_error ("Runtime critical type %s.%s not found", name_space, name);
7920 if (!mono_error_ok (&error))
7921 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7926 * mono_class_try_load_from_name:
7927 * \param image The MonoImage where the type is looked up in
7928 * \param name_space the type namespace
7929 * \param name the type short name.
7931 * This function tries to load a type, returning the class was found or NULL otherwise.
7932 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7934 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7935 * a type that we would otherwise assume to be available but was not due some error.
7939 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7944 klass = mono_class_from_name_checked (image, name_space, name, &error);
7945 if (!mono_error_ok (&error))
7946 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7952 * mono_class_is_subclass_of:
7953 * \param klass class to probe if it is a subclass of another one
7954 * \param klassc the class we suspect is the base class
7955 * \param check_interfaces whether we should perform interface checks
7957 * This method determines whether \p klass is a subclass of \p klassc.
7959 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7960 * this method return TRUE if the \p klass implements the interface or
7961 * if \p klass is an interface, if one of its base classes is \p klass.
7963 * If \p check_interfaces is false, then if \p klass is not an interface,
7964 * it returns TRUE if the \p klass is a subclass of \p klassc.
7966 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7971 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7972 gboolean check_interfaces)
7974 /* FIXME test for interfaces with variant generic arguments */
7975 mono_class_init (klass);
7976 mono_class_init (klassc);
7978 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7979 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7981 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7984 for (i = 0; i < klass->interface_count; i ++) {
7985 MonoClass *ic = klass->interfaces [i];
7990 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7995 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7998 if (klassc == mono_defaults.object_class)
8005 mono_type_is_generic_argument (MonoType *type)
8007 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8011 mono_class_has_variant_generic_params (MonoClass *klass)
8014 MonoGenericContainer *container;
8016 if (!mono_class_is_ginst (klass))
8019 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8021 for (i = 0; i < container->type_argc; ++i)
8022 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8029 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8031 if (target == candidate)
8034 if (check_for_reference_conv &&
8035 mono_type_is_generic_argument (&target->byval_arg) &&
8036 mono_type_is_generic_argument (&candidate->byval_arg)) {
8037 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8038 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8040 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8043 if (!mono_class_is_assignable_from (target, candidate))
8049 * @container the generic container from the GTD
8050 * @klass: the class to be assigned to
8051 * @oklass: the source class
8053 * Both @klass and @oklass must be instances of the same generic interface.
8055 * Returns: TRUE if @klass can be assigned to a @klass variable
8058 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8061 MonoType **klass_argv, **oklass_argv;
8062 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8063 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8065 if (klass == oklass)
8068 /*Viable candidates are instances of the same generic interface*/
8069 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8072 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8073 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8075 for (j = 0; j < container->type_argc; ++j) {
8076 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8077 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8079 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8083 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8084 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8086 if (param1_class != param2_class) {
8087 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8088 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8090 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8091 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8101 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8103 MonoGenericParam *gparam, *ogparam;
8104 MonoGenericParamInfo *tinfo, *cinfo;
8105 MonoClass **candidate_class;
8106 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8109 if (target == candidate)
8111 if (target->byval_arg.type != candidate->byval_arg.type)
8114 gparam = target->byval_arg.data.generic_param;
8115 ogparam = candidate->byval_arg.data.generic_param;
8116 tinfo = mono_generic_param_info (gparam);
8117 cinfo = mono_generic_param_info (ogparam);
8119 class_constraint_satisfied = FALSE;
8120 valuetype_constraint_satisfied = FALSE;
8122 /*candidate must have a super set of target's special constraints*/
8123 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8124 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8126 if (cinfo->constraints) {
8127 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8128 MonoClass *cc = *candidate_class;
8130 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8131 class_constraint_satisfied = TRUE;
8132 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8133 valuetype_constraint_satisfied = TRUE;
8136 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8137 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8139 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8141 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8143 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8144 valuetype_constraint_satisfied)) {
8149 /*candidate type constraints must be a superset of target's*/
8150 if (tinfo->constraints) {
8151 MonoClass **target_class;
8152 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8153 MonoClass *tc = *target_class;
8156 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8157 * check it's constraints since it satisfy the constraint by itself.
8159 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8162 if (!cinfo->constraints)
8165 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8166 MonoClass *cc = *candidate_class;
8168 if (mono_class_is_assignable_from (tc, cc))
8172 * This happens when we have the following:
8174 * Bar<K> where K : IFace
8175 * Foo<T, U> where T : U where U : IFace
8177 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8180 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8181 if (mono_gparam_is_assignable_from (target, cc))
8185 if (!*candidate_class)
8190 /*candidate itself must have a constraint that satisfy target*/
8191 if (cinfo->constraints) {
8192 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8193 MonoClass *cc = *candidate_class;
8194 if (mono_class_is_assignable_from (target, cc))
8202 * mono_class_is_assignable_from:
8203 * \param klass the class to be assigned to
8204 * \param oklass the source class
8206 * \returns TRUE if an instance of class \p oklass can be assigned to an
8207 * instance of class \p klass
8210 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8213 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8215 mono_class_init (klass);
8217 if (!oklass->inited)
8218 mono_class_init (oklass);
8220 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8223 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8224 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8226 return mono_gparam_is_assignable_from (klass, oklass);
8229 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
8230 * has a constraint which is a class type:
8233 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
8235 * In this case, Foo is assignable from T1.
8237 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8238 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8239 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8243 for (i = 0; constraints [i]; ++i) {
8244 if (mono_class_is_assignable_from (klass, constraints [i]))
8249 return mono_class_has_parent (oklass, klass);
8252 if (MONO_CLASS_IS_INTERFACE (klass)) {
8254 /* interface_offsets might not be set for dynamic classes */
8255 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8257 * oklass might be a generic type parameter but they have
8258 * interface_offsets set.
8260 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8261 if (!is_ok (&error)) {
8262 mono_error_cleanup (&error);
8267 if (!oklass->interface_bitmap)
8268 /* Happens with generic instances of not-yet created dynamic types */
8270 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8273 if (klass->is_array_special_interface && oklass->rank == 1) {
8274 //XXX we could offset this by having the cast target computed at JIT time
8275 //XXX we could go even further and emit a wrapper that would do the extra type check
8276 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8277 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8279 // 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
8280 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8281 if (iface_klass->valuetype)
8282 iface_klass = iface_klass->cast_class;
8284 //array covariant casts only operates on scalar to scalar
8285 //This is so int[] can't be casted to IComparable<int>[]
8286 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8290 if (mono_class_has_variant_generic_params (klass)) {
8292 mono_class_setup_interfaces (oklass, &error);
8293 if (!mono_error_ok (&error)) {
8294 mono_error_cleanup (&error);
8298 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8299 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8300 MonoClass *iface = oklass->interfaces_packed [i];
8302 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8307 } else if (klass->delegate) {
8308 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8310 }else if (klass->rank) {
8311 MonoClass *eclass, *eoclass;
8313 if (oklass->rank != klass->rank)
8316 /* vectors vs. one dimensional arrays */
8317 if (oklass->byval_arg.type != klass->byval_arg.type)
8320 eclass = klass->cast_class;
8321 eoclass = oklass->cast_class;
8324 * a is b does not imply a[] is b[] when a is a valuetype, and
8325 * b is a reference type.
8328 if (eoclass->valuetype) {
8329 if ((eclass == mono_defaults.enum_class) ||
8330 (eclass == mono_defaults.enum_class->parent) ||
8331 (eclass == mono_defaults.object_class))
8335 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8336 } else if (mono_class_is_nullable (klass)) {
8337 if (mono_class_is_nullable (oklass))
8338 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8340 return mono_class_is_assignable_from (klass->cast_class, oklass);
8341 } else if (klass == mono_defaults.object_class)
8344 return mono_class_has_parent (oklass, klass);
8347 /*Check if @oklass is variant compatible with @klass.*/
8349 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8352 MonoType **klass_argv, **oklass_argv;
8353 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8354 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8356 /*Viable candidates are instances of the same generic interface*/
8357 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8360 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8361 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8363 for (j = 0; j < container->type_argc; ++j) {
8364 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8365 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8367 if (param1_class->valuetype != param2_class->valuetype)
8371 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8372 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8374 if (param1_class != param2_class) {
8375 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8376 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8378 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8379 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8387 /*Check if @candidate implements the interface @target*/
8389 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8393 gboolean is_variant = mono_class_has_variant_generic_params (target);
8395 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8396 if (mono_class_is_variant_compatible_slow (target, candidate))
8401 if (candidate == target)
8404 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8405 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8406 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8408 if (tb && tb->interfaces) {
8409 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8410 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8411 MonoClass *iface_class;
8413 /* we can't realize the type here since it can do pretty much anything. */
8416 iface_class = mono_class_from_mono_type (iface->type);
8417 if (iface_class == target)
8419 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8421 if (mono_class_implement_interface_slow (target, iface_class))
8426 /*setup_interfaces don't mono_class_init anything*/
8427 /*FIXME this doesn't handle primitive type arrays.
8428 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8429 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8431 mono_class_setup_interfaces (candidate, &error);
8432 if (!mono_error_ok (&error)) {
8433 mono_error_cleanup (&error);
8437 for (i = 0; i < candidate->interface_count; ++i) {
8438 if (candidate->interfaces [i] == target)
8441 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8444 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8448 candidate = candidate->parent;
8449 } while (candidate);
8455 * Check if @oklass can be assigned to @klass.
8456 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8459 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8461 if (candidate == target)
8463 if (target == mono_defaults.object_class)
8466 if (mono_class_has_parent (candidate, target))
8469 /*If target is not an interface there is no need to check them.*/
8470 if (MONO_CLASS_IS_INTERFACE (target))
8471 return mono_class_implement_interface_slow (target, candidate);
8473 if (target->delegate && mono_class_has_variant_generic_params (target))
8474 return mono_class_is_variant_compatible (target, candidate, FALSE);
8477 MonoClass *eclass, *eoclass;
8479 if (target->rank != candidate->rank)
8482 /* vectors vs. one dimensional arrays */
8483 if (target->byval_arg.type != candidate->byval_arg.type)
8486 eclass = target->cast_class;
8487 eoclass = candidate->cast_class;
8490 * a is b does not imply a[] is b[] when a is a valuetype, and
8491 * b is a reference type.
8494 if (eoclass->valuetype) {
8495 if ((eclass == mono_defaults.enum_class) ||
8496 (eclass == mono_defaults.enum_class->parent) ||
8497 (eclass == mono_defaults.object_class))
8501 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8503 /*FIXME properly handle nullables */
8504 /*FIXME properly handle (M)VAR */
8509 * mono_class_get_cctor:
8510 * \param klass A MonoClass pointer
8512 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8515 mono_class_get_cctor (MonoClass *klass)
8517 MonoCachedClassInfo cached_info;
8519 if (image_is_dynamic (klass->image)) {
8521 * has_cctor is not set for these classes because mono_class_init () is
8524 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8527 mono_class_init (klass);
8529 if (!klass->has_cctor)
8532 if (mono_class_is_ginst (klass) && !klass->methods)
8533 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8535 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8537 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8538 if (!mono_error_ok (&error))
8539 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8543 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8547 * mono_class_get_finalizer:
8548 * \param klass: The MonoClass pointer
8550 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8553 mono_class_get_finalizer (MonoClass *klass)
8555 MonoCachedClassInfo cached_info;
8558 mono_class_init (klass);
8559 if (!mono_class_has_finalizer (klass))
8562 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8564 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8565 if (!mono_error_ok (&error))
8566 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8569 mono_class_setup_vtable (klass);
8570 return klass->vtable [finalize_slot];
8575 * mono_class_needs_cctor_run:
8576 * \param klass the MonoClass pointer
8577 * \param caller a MonoMethod describing the caller
8579 * Determines whenever the class has a static constructor and whenever it
8580 * needs to be called when executing CALLER.
8583 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8587 method = mono_class_get_cctor (klass);
8589 return (method == caller) ? FALSE : TRUE;
8595 * mono_class_array_element_size:
8598 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8601 mono_class_array_element_size (MonoClass *klass)
8603 MonoType *type = &klass->byval_arg;
8606 switch (type->type) {
8609 case MONO_TYPE_BOOLEAN:
8613 case MONO_TYPE_CHAR:
8622 case MONO_TYPE_CLASS:
8623 case MONO_TYPE_STRING:
8624 case MONO_TYPE_OBJECT:
8625 case MONO_TYPE_SZARRAY:
8626 case MONO_TYPE_ARRAY:
8627 return sizeof (gpointer);
8632 case MONO_TYPE_VALUETYPE:
8633 if (type->data.klass->enumtype) {
8634 type = mono_class_enum_basetype (type->data.klass);
8635 klass = klass->element_class;
8638 return mono_class_instance_size (klass) - sizeof (MonoObject);
8639 case MONO_TYPE_GENERICINST:
8640 type = &type->data.generic_class->container_class->byval_arg;
8643 case MONO_TYPE_MVAR: {
8646 return mono_type_size (type, &align);
8648 case MONO_TYPE_VOID:
8652 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8658 * mono_array_element_size:
8659 * \param ac pointer to a \c MonoArrayClass
8661 * \returns The size of single array element.
8663 * LOCKING: Acquires the loader lock.
8666 mono_array_element_size (MonoClass *ac)
8668 g_assert (ac->rank);
8669 if (G_UNLIKELY (!ac->size_inited)) {
8670 mono_class_setup_fields (ac);
8672 return ac->sizes.element_size;
8679 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8680 MonoGenericContext *context)
8683 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8684 g_assert (mono_error_ok (&error));
8689 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8690 MonoGenericContext *context, MonoError *error)
8694 if (image_is_dynamic (image)) {
8695 MonoClass *tmp_handle_class;
8696 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8698 mono_error_assert_ok (error);
8699 g_assert (tmp_handle_class);
8701 *handle_class = tmp_handle_class;
8703 if (tmp_handle_class == mono_defaults.typehandle_class)
8704 return &((MonoClass*)obj)->byval_arg;
8709 switch (token & 0xff000000) {
8710 case MONO_TOKEN_TYPE_DEF:
8711 case MONO_TOKEN_TYPE_REF:
8712 case MONO_TOKEN_TYPE_SPEC: {
8715 *handle_class = mono_defaults.typehandle_class;
8716 type = mono_type_get_checked (image, token, context, error);
8720 mono_class_init (mono_class_from_mono_type (type));
8721 /* We return a MonoType* as handle */
8724 case MONO_TOKEN_FIELD_DEF: {
8726 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8728 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8732 *handle_class = mono_defaults.fieldhandle_class;
8733 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8737 mono_class_init (klass);
8738 return mono_class_get_field (klass, token);
8740 case MONO_TOKEN_METHOD_DEF:
8741 case MONO_TOKEN_METHOD_SPEC: {
8743 meth = mono_get_method_checked (image, token, NULL, context, error);
8745 *handle_class = mono_defaults.methodhandle_class;
8751 case MONO_TOKEN_MEMBER_REF: {
8752 guint32 cols [MONO_MEMBERREF_SIZE];
8754 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8755 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8756 mono_metadata_decode_blob_size (sig, &sig);
8757 if (*sig == 0x6) { /* it's a field */
8759 MonoClassField *field;
8760 field = mono_field_from_token_checked (image, token, &klass, context, error);
8762 *handle_class = mono_defaults.fieldhandle_class;
8766 meth = mono_get_method_checked (image, token, NULL, context, error);
8768 *handle_class = mono_defaults.methodhandle_class;
8773 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8779 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8781 MonoClass *handle_class;
8783 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8787 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8789 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8792 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8795 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8797 get_cached_class_info = func;
8801 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8803 if (!get_cached_class_info)
8806 return get_cached_class_info (klass, res);
8810 mono_install_get_class_from_name (MonoGetClassFromName func)
8812 get_class_from_name = func;
8816 * mono_class_get_image:
8818 * Use this method to get the \c MonoImage* where this class came from.
8820 * \returns The image where this class is defined.
8823 mono_class_get_image (MonoClass *klass)
8825 return klass->image;
8829 * mono_class_get_element_class:
8830 * \param klass the \c MonoClass to act on
8832 * Use this function to get the element class of an array.
8834 * \returns The element class of an array.
8837 mono_class_get_element_class (MonoClass *klass)
8839 return klass->element_class;
8843 * mono_class_is_valuetype:
8844 * \param klass the \c MonoClass to act on
8846 * Use this method to determine if the provided \c MonoClass* represents a value type,
8847 * or a reference type.
8849 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8852 mono_class_is_valuetype (MonoClass *klass)
8854 return klass->valuetype;
8858 * mono_class_is_enum:
8859 * \param klass the \c MonoClass to act on
8861 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8863 * \returns TRUE if the \c MonoClass represents an enumeration.
8866 mono_class_is_enum (MonoClass *klass)
8868 return klass->enumtype;
8872 * mono_class_enum_basetype:
8873 * \param klass the \c MonoClass to act on
8875 * Use this function to get the underlying type for an enumeration value.
8877 * \returns The underlying type representation for an enumeration.
8880 mono_class_enum_basetype (MonoClass *klass)
8882 if (klass->element_class == klass)
8883 /* SRE or broken types */
8886 return &klass->element_class->byval_arg;
8890 * mono_class_get_parent
8891 * \param klass the \c MonoClass to act on
8893 * \returns The parent class for this class.
8896 mono_class_get_parent (MonoClass *klass)
8898 return klass->parent;
8902 * mono_class_get_nesting_type:
8903 * \param klass the \c MonoClass to act on
8905 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8907 * If the return is NULL, this indicates that this class is not nested.
8909 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8912 mono_class_get_nesting_type (MonoClass *klass)
8914 return klass->nested_in;
8918 * mono_class_get_rank:
8919 * \param klass the MonoClass to act on
8921 * \returns The rank for the array (the number of dimensions).
8924 mono_class_get_rank (MonoClass *klass)
8930 * mono_class_get_name
8931 * \param klass the \c MonoClass to act on
8933 * \returns The name of the class.
8936 mono_class_get_name (MonoClass *klass)
8942 * mono_class_get_namespace:
8943 * \param klass the \c MonoClass to act on
8945 * \returns The namespace of the class.
8948 mono_class_get_namespace (MonoClass *klass)
8950 return klass->name_space;
8954 * mono_class_get_type:
8955 * \param klass the \c MonoClass to act on
8957 * This method returns the internal \c MonoType representation for the class.
8959 * \returns The \c MonoType from the class.
8962 mono_class_get_type (MonoClass *klass)
8964 return &klass->byval_arg;
8968 * mono_class_get_type_token:
8969 * \param klass the \c MonoClass to act on
8971 * This method returns type token for the class.
8973 * \returns The type token for the class.
8976 mono_class_get_type_token (MonoClass *klass)
8978 return klass->type_token;
8982 * mono_class_get_byref_type:
8983 * \param klass the \c MonoClass to act on
8988 mono_class_get_byref_type (MonoClass *klass)
8990 return &klass->this_arg;
8994 * mono_class_num_fields:
8995 * \param klass the \c MonoClass to act on
8997 * \returns The number of static and instance fields in the class.
9000 mono_class_num_fields (MonoClass *klass)
9002 return mono_class_get_field_count (klass);
9006 * mono_class_num_methods:
9007 * \param klass the \c MonoClass to act on
9009 * \returns The number of methods in the class.
9012 mono_class_num_methods (MonoClass *klass)
9014 return mono_class_get_method_count (klass);
9018 * mono_class_num_properties
9019 * \param klass the \c MonoClass to act on
9021 * \returns The number of properties in the class.
9024 mono_class_num_properties (MonoClass *klass)
9026 mono_class_setup_properties (klass);
9028 return mono_class_get_property_info (klass)->count;
9032 * mono_class_num_events:
9033 * \param klass the \c MonoClass to act on
9035 * \returns The number of events in the class.
9038 mono_class_num_events (MonoClass *klass)
9040 mono_class_setup_events (klass);
9042 return mono_class_get_event_info (klass)->count;
9046 * mono_class_get_fields:
9047 * \param klass the \c MonoClass to act on
9049 * This routine is an iterator routine for retrieving the fields in a class.
9051 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9052 * iterate over all of the elements. When no more values are
9053 * available, the return value is NULL.
9055 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9058 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9060 MonoClassField* field;
9064 mono_class_setup_fields (klass);
9065 if (mono_class_has_failure (klass))
9067 /* start from the first */
9068 if (mono_class_get_field_count (klass)) {
9069 *iter = &klass->fields [0];
9070 return &klass->fields [0];
9076 field = (MonoClassField *)*iter;
9078 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9086 * mono_class_get_methods:
9087 * \param klass the \c MonoClass to act on
9089 * This routine is an iterator routine for retrieving the fields in a class.
9091 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9092 * iterate over all of the elements. When no more values are
9093 * available, the return value is NULL.
9095 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9098 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9100 MonoMethod** method;
9104 mono_class_setup_methods (klass);
9107 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9108 * FIXME we should better report this error to the caller
9110 if (!klass->methods)
9112 /* start from the first */
9113 if (mono_class_get_method_count (klass)) {
9114 *iter = &klass->methods [0];
9115 return klass->methods [0];
9121 method = (MonoMethod **)*iter;
9123 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9131 * mono_class_get_virtual_methods:
9133 * Iterate over the virtual methods of KLASS.
9135 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9138 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9140 gboolean static_iter = FALSE;
9146 * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
9147 * and the upper bits contain an index. Otherwise, the iterator is a pointer into
9150 if ((gsize)(*iter) & 1)
9152 /* Use the static metadata only if klass->methods is not yet initialized */
9153 if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
9157 MonoMethod** methodptr;
9160 mono_class_setup_methods (klass);
9162 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9163 * FIXME we should better report this error to the caller
9165 if (!klass->methods)
9167 /* start from the first */
9168 methodptr = &klass->methods [0];
9170 methodptr = (MonoMethod **)*iter;
9174 g_assert ((guint64)(*iter) > 0x100);
9175 int mcount = mono_class_get_method_count (klass);
9176 while (methodptr < &klass->methods [mcount]) {
9177 if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9181 if (methodptr < &klass->methods [mcount]) {
9188 /* Search directly in metadata to avoid calling setup_methods () */
9189 MonoMethod *res = NULL;
9195 start_index = GPOINTER_TO_UINT (*iter) >> 1;
9198 int first_idx = mono_class_get_first_method_idx (klass);
9199 int mcount = mono_class_get_method_count (klass);
9200 for (i = start_index; i < mcount; ++i) {
9203 /* first_idx points into the methodptr table */
9204 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9206 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9212 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9213 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9215 /* Add 1 here so the if (*iter) check fails */
9216 *iter = GUINT_TO_POINTER (((i + 1) << 1) | 1);
9225 * mono_class_get_properties:
9226 * \param klass the \c MonoClass to act on
9228 * This routine is an iterator routine for retrieving the properties in a class.
9230 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9231 * iterate over all of the elements. When no more values are
9232 * available, the return value is NULL.
9234 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9237 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9239 MonoProperty* property;
9243 mono_class_setup_properties (klass);
9244 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9245 /* start from the first */
9247 *iter = &info->properties [0];
9248 return (MonoProperty *)*iter;
9254 property = (MonoProperty *)*iter;
9256 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9257 if (property < &info->properties [info->count]) {
9259 return (MonoProperty *)*iter;
9265 * mono_class_get_events:
9266 * \param klass the \c MonoClass to act on
9268 * This routine is an iterator routine for retrieving the properties in a class.
9270 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9271 * iterate over all of the elements. When no more values are
9272 * available, the return value is NULL.
9274 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9277 mono_class_get_events (MonoClass* klass, gpointer *iter)
9283 mono_class_setup_events (klass);
9284 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9285 /* start from the first */
9287 *iter = &info->events [0];
9288 return (MonoEvent *)*iter;
9294 event = (MonoEvent *)*iter;
9296 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9297 if (event < &info->events [info->count]) {
9299 return (MonoEvent *)*iter;
9305 * mono_class_get_interfaces
9306 * \param klass the \c MonoClass to act on
9308 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9310 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9311 * iterate over all of the elements. When no more values are
9312 * available, the return value is NULL.
9314 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9317 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9325 mono_class_init (klass);
9326 if (!klass->interfaces_inited) {
9327 mono_class_setup_interfaces (klass, &error);
9328 if (!mono_error_ok (&error)) {
9329 mono_error_cleanup (&error);
9333 /* start from the first */
9334 if (klass->interface_count) {
9335 *iter = &klass->interfaces [0];
9336 return klass->interfaces [0];
9342 iface = (MonoClass **)*iter;
9344 if (iface < &klass->interfaces [klass->interface_count]) {
9352 setup_nested_types (MonoClass *klass)
9355 GList *classes, *nested_classes, *l;
9358 if (klass->nested_classes_inited)
9361 if (!klass->type_token) {
9362 mono_loader_lock ();
9363 klass->nested_classes_inited = TRUE;
9364 mono_loader_unlock ();
9368 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9372 guint32 cols [MONO_NESTED_CLASS_SIZE];
9373 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9374 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9375 if (!mono_error_ok (&error)) {
9376 /*FIXME don't swallow the error message*/
9377 mono_error_cleanup (&error);
9379 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9383 classes = g_list_prepend (classes, nclass);
9385 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9388 nested_classes = NULL;
9389 for (l = classes; l; l = l->next)
9390 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9391 g_list_free (classes);
9393 mono_loader_lock ();
9394 if (!klass->nested_classes_inited) {
9395 mono_class_set_nested_classes_property (klass, nested_classes);
9396 mono_memory_barrier ();
9397 klass->nested_classes_inited = TRUE;
9399 mono_loader_unlock ();
9403 * mono_class_get_nested_types
9404 * \param klass the \c MonoClass to act on
9406 * This routine is an iterator routine for retrieving the nested types of a class.
9407 * This works only if \p klass is non-generic, or a generic type definition.
9409 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9410 * iterate over all of the elements. When no more values are
9411 * available, the return value is NULL.
9413 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9416 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9422 if (!klass->nested_classes_inited)
9423 setup_nested_types (klass);
9426 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9427 /* start from the first */
9428 if (nested_classes) {
9429 *iter = nested_classes;
9430 return (MonoClass *)nested_classes->data;
9432 /* no nested types */
9436 item = (GList *)*iter;
9440 return (MonoClass *)item->data;
9447 * mono_class_is_delegate
9448 * \param klass the \c MonoClass to act on
9450 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9453 mono_class_is_delegate (MonoClass *klass)
9455 return klass->delegate;
9459 * mono_class_implements_interface
9460 * \param klass The MonoClass to act on
9461 * \param interface The interface to check if \p klass implements.
9463 * \returns TRUE if \p klass implements \p interface.
9466 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9468 return mono_class_is_assignable_from (iface, klass);
9472 * mono_field_get_name:
9473 * \param field the \c MonoClassField to act on
9475 * \returns The name of the field.
9478 mono_field_get_name (MonoClassField *field)
9484 * mono_field_get_type:
9485 * \param field the \c MonoClassField to act on
9486 * \returns \c MonoType of the field.
9489 mono_field_get_type (MonoClassField *field)
9492 MonoType *type = mono_field_get_type_checked (field, &error);
9493 if (!mono_error_ok (&error)) {
9494 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9495 mono_error_cleanup (&error);
9502 * mono_field_get_type_checked:
9503 * \param field the \c MonoClassField to act on
9504 * \param error used to return any error found while retrieving \p field type
9506 * \returns \c MonoType of the field.
9509 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9513 mono_field_resolve_type (field, error);
9518 * mono_field_get_parent:
9519 * \param field the \c MonoClassField to act on
9521 * \returns \c MonoClass where the field was defined.
9524 mono_field_get_parent (MonoClassField *field)
9526 return field->parent;
9530 * mono_field_get_flags;
9531 * \param field the \c MonoClassField to act on
9533 * The metadata flags for a field are encoded using the
9534 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9536 * \returns The flags for the field.
9539 mono_field_get_flags (MonoClassField *field)
9542 return mono_field_resolve_flags (field);
9543 return field->type->attrs;
9547 * mono_field_get_offset:
9548 * \param field the \c MonoClassField to act on
9550 * \returns The field offset.
9553 mono_field_get_offset (MonoClassField *field)
9555 return field->offset;
9559 mono_field_get_rva (MonoClassField *field)
9563 MonoClass *klass = field->parent;
9564 MonoFieldDefaultValue *def_values;
9566 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9568 def_values = mono_class_get_field_def_values (klass);
9570 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9572 mono_class_set_field_def_values (klass, def_values);
9575 field_index = mono_field_get_index (field);
9577 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9578 int first_field_idx = mono_class_get_first_field_idx (klass);
9579 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9581 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9582 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9585 return def_values [field_index].data;
9589 * mono_field_get_data:
9590 * \param field the \c MonoClassField to act on
9592 * \returns A pointer to the metadata constant value or to the field
9593 * data if it has an RVA flag.
9596 mono_field_get_data (MonoClassField *field)
9598 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9599 MonoTypeEnum def_type;
9601 return mono_class_get_field_default_value (field, &def_type);
9602 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9603 return mono_field_get_rva (field);
9610 * mono_property_get_name:
9611 * \param prop the \c MonoProperty to act on
9612 * \returns The name of the property
9615 mono_property_get_name (MonoProperty *prop)
9621 * mono_property_get_set_method
9622 * \param prop the \c MonoProperty to act on.
9623 * \returns The setter method of the property, a \c MonoMethod.
9626 mono_property_get_set_method (MonoProperty *prop)
9632 * mono_property_get_get_method
9633 * \param prop the MonoProperty to act on.
9634 * \returns The getter method of the property (A \c MonoMethod)
9637 mono_property_get_get_method (MonoProperty *prop)
9643 * mono_property_get_parent:
9644 * \param prop the \c MonoProperty to act on.
9645 * \returns The \c MonoClass where the property was defined.
9648 mono_property_get_parent (MonoProperty *prop)
9650 return prop->parent;
9654 * mono_property_get_flags:
9655 * \param prop the \c MonoProperty to act on.
9657 * The metadata flags for a property are encoded using the
9658 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9660 * \returns The flags for the property.
9663 mono_property_get_flags (MonoProperty *prop)
9669 * mono_event_get_name:
9670 * \param event the MonoEvent to act on
9671 * \returns The name of the event.
9674 mono_event_get_name (MonoEvent *event)
9680 * mono_event_get_add_method:
9681 * \param event The \c MonoEvent to act on.
9682 * \returns The \c add method for the event, a \c MonoMethod.
9685 mono_event_get_add_method (MonoEvent *event)
9691 * mono_event_get_remove_method:
9692 * \param event The \c MonoEvent to act on.
9693 * \returns The \c remove method for the event, a \c MonoMethod.
9696 mono_event_get_remove_method (MonoEvent *event)
9698 return event->remove;
9702 * mono_event_get_raise_method:
9703 * \param event The \c MonoEvent to act on.
9704 * \returns The \c raise method for the event, a \c MonoMethod.
9707 mono_event_get_raise_method (MonoEvent *event)
9709 return event->raise;
9713 * mono_event_get_parent:
9714 * \param event the MonoEvent to act on.
9715 * \returns The \c MonoClass where the event is defined.
9718 mono_event_get_parent (MonoEvent *event)
9720 return event->parent;
9724 * mono_event_get_flags
9725 * \param event the \c MonoEvent to act on.
9727 * The metadata flags for an event are encoded using the
9728 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9730 * \returns The flags for the event.
9733 mono_event_get_flags (MonoEvent *event)
9735 return event->attrs;
9739 * mono_class_get_method_from_name:
9740 * \param klass where to look for the method
9741 * \param name name of the method
9742 * \param param_count number of parameters. -1 for any number.
9744 * Obtains a \c MonoMethod with a given name and number of parameters.
9745 * It only works if there are no multiple signatures for any given method name.
9748 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9750 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9754 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9756 MonoMethod *res = NULL;
9759 /* Search directly in the metadata to avoid calling setup_methods () */
9760 int first_idx = mono_class_get_first_method_idx (klass);
9761 int mcount = mono_class_get_method_count (klass);
9762 for (i = 0; i < mcount; ++i) {
9764 guint32 cols [MONO_METHOD_SIZE];
9766 MonoMethodSignature *sig;
9768 /* first_idx points into the methodptr table */
9769 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9771 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9772 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9774 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9777 if (param_count == -1) {
9781 sig = mono_method_signature_checked (method, &error);
9783 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9786 if (sig->param_count == param_count) {
9797 * mono_class_get_method_from_name_flags:
9798 * \param klass where to look for the method
9799 * \param name_space name of the method
9800 * \param param_count number of parameters. -1 for any number.
9801 * \param flags flags which must be set in the method
9803 * Obtains a \c MonoMethod with a given name and number of parameters.
9804 * It only works if there are no multiple signatures for any given method name.
9807 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9809 MonoMethod *res = NULL;
9812 mono_class_init (klass);
9814 if (mono_class_is_ginst (klass) && !klass->methods) {
9815 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9818 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9819 if (!mono_error_ok (&error))
9820 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9825 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9826 mono_class_setup_methods (klass);
9828 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9829 See mono/tests/array_load_exception.il
9830 FIXME we should better report this error to the caller
9832 if (!klass->methods)
9834 int mcount = mono_class_get_method_count (klass);
9835 for (i = 0; i < mcount; ++i) {
9836 MonoMethod *method = klass->methods [i];
9838 if (method->name[0] == name [0] &&
9839 !strcmp (name, method->name) &&
9840 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9841 ((method->flags & flags) == flags)) {
9848 res = find_method_in_metadata (klass, name, param_count, flags);
9855 * mono_class_set_failure:
9856 * \param klass class in which the failure was detected
9857 * \param ex_type the kind of exception/error to be thrown (later)
9858 * \param ex_data exception data (specific to each type of exception/error)
9860 * Keep a detected failure informations in the class for later processing.
9861 * Note that only the first failure is kept.
9863 * LOCKING: Acquires the loader lock.
9866 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9868 g_assert (boxed_error != NULL);
9870 if (mono_class_has_failure (klass))
9873 mono_loader_lock ();
9874 klass->has_failure = 1;
9875 mono_class_set_exception_data (klass, boxed_error);
9876 mono_loader_unlock ();
9882 mono_class_has_failure (const MonoClass *klass)
9884 g_assert (klass != NULL);
9885 return klass->has_failure != 0;
9890 * mono_class_set_type_load_failure:
9891 * \param klass class in which the failure was detected
9892 * \param fmt \c printf -style error message string.
9894 * Collect detected failure informaion in the class for later processing.
9895 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9896 * Note that only the first failure is kept.
9898 * LOCKING: Acquires the loader lock.
9900 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9903 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9905 MonoError prepare_error;
9908 if (mono_class_has_failure (klass))
9911 error_init (&prepare_error);
9913 va_start (args, fmt);
9914 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9917 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9918 mono_error_cleanup (&prepare_error);
9919 return mono_class_set_failure (klass, box);
9923 * mono_classes_init:
9925 * Initialize the resources used by this module.
9926 * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
9928 MONO_NO_SANITIZE_THREAD
9930 mono_classes_init (void)
9932 mono_os_mutex_init (&classes_mutex);
9934 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9935 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9937 mono_counters_register ("MonoClassDef count",
9938 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9939 mono_counters_register ("MonoClassGtd count",
9940 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9941 mono_counters_register ("MonoClassGenericInst count",
9942 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9943 mono_counters_register ("MonoClassGenericParam count",
9944 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9945 mono_counters_register ("MonoClassArray count",
9946 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9947 mono_counters_register ("MonoClassPointer count",
9948 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9949 mono_counters_register ("Inflated methods size",
9950 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9951 mono_counters_register ("Inflated classes size",
9952 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9953 mono_counters_register ("MonoClass size",
9954 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9958 * mono_classes_cleanup:
9960 * Free the resources used by this module.
9963 mono_classes_cleanup (void)
9965 mono_native_tls_free (setup_fields_tls_id);
9966 mono_native_tls_free (init_pending_tls_id);
9968 if (global_interface_bitset)
9969 mono_bitset_free (global_interface_bitset);
9970 global_interface_bitset = NULL;
9971 mono_os_mutex_destroy (&classes_mutex);
9975 * mono_class_get_exception_for_failure:
9976 * \param klass class in which the failure was detected
9978 * \returns a constructed MonoException than the caller can then throw
9979 * using mono_raise_exception - or NULL if no failure is present (or
9980 * doesn't result in an exception).
9983 mono_class_get_exception_for_failure (MonoClass *klass)
9985 if (!mono_class_has_failure (klass))
9987 MonoError unboxed_error;
9988 error_init (&unboxed_error);
9989 mono_error_set_for_class_failure (&unboxed_error, klass);
9990 return mono_error_convert_to_exception (&unboxed_error);
9994 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9996 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9997 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9999 if (outer_klass == inner_klass)
10001 inner_klass = inner_klass->nested_in;
10002 } while (inner_klass);
10007 mono_class_get_generic_type_definition (MonoClass *klass)
10009 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10010 return gklass ? gklass->container_class : klass;
10014 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10016 * Generic instantiations are ignored for all super types of @klass.
10018 * Visibility checks ignoring generic instantiations.
10021 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10024 klass = mono_class_get_generic_type_definition (klass);
10025 parent = mono_class_get_generic_type_definition (parent);
10026 mono_class_setup_supertypes (klass);
10028 for (i = 0; i < klass->idepth; ++i) {
10029 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10035 * Subtype can only access parent members with family protection if the site object
10036 * is subclass of Subtype. For example:
10037 * class A { protected int x; }
10039 * void valid_access () {
10043 * void invalid_access () {
10050 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10052 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10055 if (context_klass == NULL)
10057 /*if access_klass is not member_klass context_klass must be type compat*/
10058 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10064 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10067 if (accessing == accessed)
10069 if (!accessed || !accessing)
10072 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10073 * anywhere so untrusted friends are not safe to access platform's code internals */
10074 if (mono_security_core_clr_enabled ()) {
10075 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10079 mono_assembly_load_friends (accessed);
10080 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10081 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10082 /* Be conservative with checks */
10083 if (!friend_->name)
10085 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10087 if (friend_->public_key_token [0]) {
10088 if (!accessing->aname.public_key_token [0])
10090 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10099 * If klass is a generic type or if it is derived from a generic type, return the
10100 * MonoClass of the generic definition
10101 * Returns NULL if not found
10104 get_generic_definition_class (MonoClass *klass)
10107 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10108 if (gklass && gklass->container_class)
10109 return gklass->container_class;
10110 klass = klass->parent;
10116 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10119 for (i = 0; i < ginst->type_argc; ++i) {
10120 MonoType *type = ginst->type_argv[i];
10121 switch (type->type) {
10122 case MONO_TYPE_SZARRAY:
10123 if (!can_access_type (access_klass, type->data.klass))
10126 case MONO_TYPE_ARRAY:
10127 if (!can_access_type (access_klass, type->data.array->eklass))
10130 case MONO_TYPE_PTR:
10131 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10134 case MONO_TYPE_CLASS:
10135 case MONO_TYPE_VALUETYPE:
10136 case MONO_TYPE_GENERICINST:
10137 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10147 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10151 if (access_klass == member_klass)
10154 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10157 if (access_klass->element_class && !access_klass->enumtype)
10158 access_klass = access_klass->element_class;
10160 if (member_klass->element_class && !member_klass->enumtype)
10161 member_klass = member_klass->element_class;
10163 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10165 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10168 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10171 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10174 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10177 /*Non nested type with nested visibility. We just fail it.*/
10178 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10181 switch (access_level) {
10182 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10183 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10185 case TYPE_ATTRIBUTE_PUBLIC:
10188 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10191 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10192 return is_nesting_type (member_klass, access_klass);
10194 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10195 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10197 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10198 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10200 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10201 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10202 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10204 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10205 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10206 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10211 /* FIXME: check visibility of type, too */
10213 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10215 MonoClass *member_generic_def;
10216 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10219 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10220 if (((access_gklass && access_gklass->container_class) ||
10221 mono_class_is_gtd (access_klass)) &&
10222 (member_generic_def = get_generic_definition_class (member_klass))) {
10223 MonoClass *access_container;
10225 if (mono_class_is_gtd (access_klass))
10226 access_container = access_klass;
10228 access_container = access_gklass->container_class;
10230 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10234 /* Partition I 8.5.3.2 */
10235 /* the access level values are the same for fields and methods */
10236 switch (access_level) {
10237 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10238 /* same compilation unit */
10239 return access_klass->image == member_klass->image;
10240 case FIELD_ATTRIBUTE_PRIVATE:
10241 return access_klass == member_klass;
10242 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10243 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10244 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10247 case FIELD_ATTRIBUTE_ASSEMBLY:
10248 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10249 case FIELD_ATTRIBUTE_FAMILY:
10250 if (is_valid_family_access (access_klass, member_klass, context_klass))
10253 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10254 if (is_valid_family_access (access_klass, member_klass, context_klass))
10256 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10257 case FIELD_ATTRIBUTE_PUBLIC:
10264 * mono_method_can_access_field:
10265 * \param method Method that will attempt to access the field
10266 * \param field the field to access
10268 * Used to determine if a method is allowed to access the specified field.
10270 * \returns TRUE if the given \p method is allowed to access the \p field while following
10271 * the accessibility rules of the CLI.
10274 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10276 /* FIXME: check all overlapping fields */
10277 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10279 MonoClass *nested = method->klass->nested_in;
10281 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10284 nested = nested->nested_in;
10291 * mono_method_can_access_method:
10292 * \param method Method that will attempt to access the other method
10293 * \param called the method that we want to probe for accessibility.
10295 * Used to determine if the \p method is allowed to access the specified \p called method.
10297 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10298 * the accessibility rules of the CLI.
10301 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10303 method = mono_method_get_method_definition (method);
10304 called = mono_method_get_method_definition (called);
10305 return mono_method_can_access_method_full (method, called, NULL);
10309 * mono_method_can_access_method_full:
10310 * @method: The caller method
10311 * @called: The called method
10312 * @context_klass: The static type on stack of the owner @called object used
10314 * This function must be used with instance calls, as they have more strict family accessibility.
10315 * It can be used with static methods, but context_klass should be NULL.
10317 * Returns: TRUE if caller have proper visibility and acessibility to @called
10320 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10322 /* Wrappers are except from access checks */
10323 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10326 MonoClass *access_class = method->klass;
10327 MonoClass *member_class = called->klass;
10328 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10330 MonoClass *nested = access_class->nested_in;
10332 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10335 nested = nested->nested_in;
10342 can = can_access_type (access_class, member_class);
10344 MonoClass *nested = access_class->nested_in;
10346 can = can_access_type (nested, member_class);
10349 nested = nested->nested_in;
10356 if (called->is_inflated) {
10357 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10358 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10367 * mono_method_can_access_field_full:
10368 * @method: The caller method
10369 * @field: The accessed field
10370 * @context_klass: The static type on stack of the owner @field object used
10372 * This function must be used with instance fields, as they have more strict family accessibility.
10373 * It can be used with static fields, but context_klass should be NULL.
10375 * Returns: TRUE if caller have proper visibility and acessibility to @field
10378 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10380 MonoClass *access_class = method->klass;
10381 MonoClass *member_class = field->parent;
10382 /* FIXME: check all overlapping fields */
10383 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10385 MonoClass *nested = access_class->nested_in;
10387 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10390 nested = nested->nested_in;
10397 can = can_access_type (access_class, member_class);
10399 MonoClass *nested = access_class->nested_in;
10401 can = can_access_type (nested, member_class);
10404 nested = nested->nested_in;
10414 * mono_class_can_access_class:
10415 * @source_class: The source class
10416 * @target_class: The accessed class
10418 * This function returns is @target_class is visible to @source_class
10420 * Returns: TRUE if source have proper visibility and acessibility to target
10423 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10425 return can_access_type (source_class, target_class);
10429 * mono_type_is_valid_enum_basetype:
10430 * \param type The MonoType to check
10431 * \returns TRUE if the type can be used as the basetype of an enum
10433 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10434 switch (type->type) {
10437 case MONO_TYPE_BOOLEAN:
10440 case MONO_TYPE_CHAR:
10454 * mono_class_is_valid_enum:
10455 * \param klass An enum class to be validated
10457 * This method verify the required properties an enum should have.
10459 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10460 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10461 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10463 * \returns TRUE if the informed enum class is valid
10466 mono_class_is_valid_enum (MonoClass *klass)
10468 MonoClassField * field;
10469 gpointer iter = NULL;
10470 gboolean found_base_field = FALSE;
10472 g_assert (klass->enumtype);
10473 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10474 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10478 if (!mono_class_is_auto_layout (klass))
10481 while ((field = mono_class_get_fields (klass, &iter))) {
10482 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10483 if (found_base_field)
10485 found_base_field = TRUE;
10486 if (!mono_type_is_valid_enum_basetype (field->type))
10491 if (!found_base_field)
10494 if (mono_class_get_method_count (klass) > 0)
10501 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10503 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10507 * mono_class_setup_interface_id:
10509 * Initializes MonoClass::interface_id if required.
10511 * LOCKING: Acquires the loader lock.
10514 mono_class_setup_interface_id (MonoClass *klass)
10516 mono_loader_lock ();
10517 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10518 klass->interface_id = mono_get_unique_iid (klass);
10519 mono_loader_unlock ();
10523 * mono_class_setup_interfaces:
10525 * Initialize klass->interfaces/interfaces_count.
10526 * LOCKING: Acquires the loader lock.
10527 * This function can fail the type.
10530 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10532 int i, interface_count;
10533 MonoClass **interfaces;
10535 error_init (error);
10537 if (klass->interfaces_inited)
10540 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10541 MonoType *args [1];
10543 /* generic IList, ICollection, IEnumerable */
10544 interface_count = 2;
10545 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10547 args [0] = &klass->element_class->byval_arg;
10548 interfaces [0] = mono_class_bind_generic_parameters (
10549 mono_defaults.generic_ilist_class, 1, args, FALSE);
10550 interfaces [1] = mono_class_bind_generic_parameters (
10551 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10552 } else if (mono_class_is_ginst (klass)) {
10553 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10555 mono_class_setup_interfaces (gklass, error);
10556 if (!mono_error_ok (error)) {
10557 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10561 interface_count = gklass->interface_count;
10562 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10563 for (i = 0; i < interface_count; i++) {
10564 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10565 if (!mono_error_ok (error)) {
10566 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10571 interface_count = 0;
10575 mono_loader_lock ();
10576 if (!klass->interfaces_inited) {
10577 klass->interface_count = interface_count;
10578 klass->interfaces = interfaces;
10580 mono_memory_barrier ();
10582 klass->interfaces_inited = TRUE;
10584 mono_loader_unlock ();
10588 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10590 MonoClass *klass = field->parent;
10591 MonoImage *image = klass->image;
10592 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10594 int field_idx = field - klass->fields;
10596 error_init (error);
10599 MonoClassField *gfield = >d->fields [field_idx];
10600 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10601 if (!mono_error_ok (error)) {
10602 char *full_name = mono_type_get_full_name (gtd);
10603 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));
10604 g_free (full_name);
10607 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10608 if (!mono_error_ok (error)) {
10609 char *full_name = mono_type_get_full_name (klass);
10610 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));
10611 g_free (full_name);
10615 guint32 cols [MONO_FIELD_SIZE];
10616 MonoGenericContainer *container = NULL;
10617 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10619 /*FIXME, in theory we do not lazy load SRE fields*/
10620 g_assert (!image_is_dynamic (image));
10622 if (mono_class_is_gtd (klass)) {
10623 container = mono_class_get_generic_container (klass);
10625 container = mono_class_get_generic_container (gtd);
10626 g_assert (container);
10629 /* first_field_idx and idx points into the fieldptr table */
10630 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10632 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10633 char *full_name = mono_type_get_full_name (klass);
10634 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10635 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10636 g_free (full_name);
10640 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10642 mono_metadata_decode_value (sig, &sig);
10643 /* FIELD signature == 0x06 */
10644 g_assert (*sig == 0x06);
10646 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10648 char *full_name = mono_type_get_full_name (klass);
10649 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));
10650 g_free (full_name);
10653 mono_memory_barrier ();
10654 field->type = ftype;
10658 mono_field_resolve_flags (MonoClassField *field)
10660 MonoClass *klass = field->parent;
10661 MonoImage *image = klass->image;
10662 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10663 int field_idx = field - klass->fields;
10666 MonoClassField *gfield = >d->fields [field_idx];
10667 return mono_field_get_flags (gfield);
10669 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10671 /*FIXME, in theory we do not lazy load SRE fields*/
10672 g_assert (!image_is_dynamic (image));
10674 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10679 * mono_class_get_fields_lazy:
10680 * \param klass the MonoClass to act on
10682 * This routine is an iterator routine for retrieving the fields in a class.
10683 * Only minimal information about fields are loaded. Accessors must be used
10684 * for all MonoClassField returned.
10686 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10687 * iterate over all of the elements. When no more values are
10688 * available, the return value is NULL.
10690 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10693 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10695 MonoClassField* field;
10699 mono_class_setup_basic_field_info (klass);
10700 if (!klass->fields)
10702 /* start from the first */
10703 if (mono_class_get_field_count (klass)) {
10704 *iter = &klass->fields [0];
10705 return (MonoClassField *)*iter;
10711 field = (MonoClassField *)*iter;
10713 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10715 return (MonoClassField *)*iter;
10721 mono_class_full_name (MonoClass *klass)
10723 return mono_type_full_name (&klass->byval_arg);
10726 /* Declare all shared lazy type lookup functions */
10727 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10730 * mono_method_get_base_method:
10731 * \param method a method
10732 * \param definition if true, get the definition
10733 * \param error set on failure
10735 * Given a virtual method associated with a subclass, return the corresponding
10736 * method from an ancestor. If \p definition is FALSE, returns the method in the
10737 * superclass of the given method. If \p definition is TRUE, return the method
10738 * in the ancestor class where it was first declared. The type arguments will
10739 * be inflated in the ancestor classes. If the method is not associated with a
10740 * class, or isn't virtual, returns the method itself. On failure returns NULL
10741 * and sets \p error.
10744 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10746 MonoClass *klass, *parent;
10747 MonoGenericContext *generic_inst = NULL;
10748 MonoMethod *result = NULL;
10751 if (method->klass == NULL)
10754 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10755 MONO_CLASS_IS_INTERFACE (method->klass) ||
10756 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10759 slot = mono_method_get_vtable_slot (method);
10763 klass = method->klass;
10764 if (mono_class_is_ginst (klass)) {
10765 generic_inst = mono_class_get_context (klass);
10766 klass = mono_class_get_generic_class (klass)->container_class;
10771 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10772 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10773 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10774 or klass is the generic container class and generic_inst is the instantiation.
10776 when we go to the parent, if the parent is an open constructed type, we need to
10777 replace the type parameters by the definitions from the generic_inst, and then take it
10778 apart again into the klass and the generic_inst.
10780 For cases like this:
10781 class C<T> : B<T, int> {
10782 public override void Foo () { ... }
10784 class B<U,V> : A<HashMap<U,V>> {
10785 public override void Foo () { ... }
10788 public virtual void Foo () { ... }
10791 if at each iteration the parent isn't open, we can skip inflating it. if at some
10792 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10795 MonoGenericContext *parent_inst = NULL;
10796 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10797 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10798 return_val_if_nok (error, NULL);
10800 if (mono_class_is_ginst (parent)) {
10801 parent_inst = mono_class_get_context (parent);
10802 parent = mono_class_get_generic_class (parent)->container_class;
10805 mono_class_setup_vtable (parent);
10806 if (parent->vtable_size <= slot)
10809 generic_inst = parent_inst;
10812 klass = klass->parent;
10815 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10816 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10817 return_val_if_nok (error, NULL);
10819 generic_inst = NULL;
10821 if (mono_class_is_ginst (klass)) {
10822 generic_inst = mono_class_get_context (klass);
10823 klass = mono_class_get_generic_class (klass)->container_class;
10828 if (generic_inst) {
10829 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10830 return_val_if_nok (error, NULL);
10833 if (klass == method->klass)
10836 /*This is possible if definition == FALSE.
10837 * Do it here to be really sure we don't read invalid memory.
10839 if (slot >= klass->vtable_size)
10842 mono_class_setup_vtable (klass);
10844 result = klass->vtable [slot];
10845 if (result == NULL) {
10846 /* It is an abstract method */
10847 gboolean found = FALSE;
10848 gpointer iter = NULL;
10849 while ((result = mono_class_get_methods (klass, &iter))) {
10850 if (result->slot == slot) {
10855 /* found might be FALSE if we looked in an abstract class
10856 * that doesn't override an abstract method of its
10858 * abstract class Base {
10859 * public abstract void Foo ();
10861 * abstract class Derived : Base { }
10862 * class Child : Derived {
10863 * public override void Foo () { }
10866 * if m was Child.Foo and we ask for the base method,
10867 * then we get here with klass == Derived and found == FALSE
10869 /* but it shouldn't be the case that if we're looking
10870 * for the definition and didn't find a result; the
10871 * loop above should've taken us as far as we could
10873 g_assert (!(definition && !found));
10878 g_assert (result != NULL);