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 3 vtable layouts, with and without the stelemref method and enum element type
4959 * The first slot if for array with.
4961 static int szarray_vtable_size[3] = { 0 };
4965 if (MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg))
4967 else if (klass->element_class->enumtype)
4973 if (!szarray_vtable_size [slot]) {
4974 mono_class_setup_vtable (klass);
4975 szarray_vtable_size [slot] = klass->vtable_size;
4976 vtable_size = klass->vtable_size;
4978 vtable_size = szarray_vtable_size[slot];
4980 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4981 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4983 /* Generic instance case */
4984 ghcimpl = gklass->ghcimpl;
4985 has_cctor = gklass->has_cctor;
4987 mono_class_setup_vtable (gklass);
4988 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4991 vtable_size = gklass->vtable_size;
4995 /* ghcimpl is not currently used
4997 if (klass->parent) {
4998 MonoMethod *cmethod = klass->vtable [ghc_slot];
4999 if (cmethod->is_inflated)
5000 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5001 if (cmethod == default_ghc) {
5007 /* C# doesn't allow interfaces to have cctors */
5008 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5009 MonoMethod *cmethod = NULL;
5011 if (mono_class_is_ginst (klass)) {
5012 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5014 /* Generic instance case */
5015 ghcimpl = gklass->ghcimpl;
5016 has_cctor = gklass->has_cctor;
5017 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5018 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5019 /* The find_method function ignores the 'flags' argument */
5020 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5023 mono_class_setup_methods (klass);
5024 if (mono_class_has_failure (klass))
5027 int mcount = mono_class_get_method_count (klass);
5028 for (i = 0; i < mcount; ++i) {
5029 MonoMethod *method = klass->methods [i];
5030 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5031 (strcmp (".cctor", method->name) == 0)) {
5041 array_method_count = 3 + (klass->rank > 1? 2: 1);
5043 if (klass->interface_count) {
5044 int count_generic = generic_array_methods (klass);
5045 array_method_count += klass->interface_count * count_generic;
5049 if (klass->parent) {
5050 if (!klass->parent->vtable_size)
5051 mono_class_setup_vtable (klass->parent);
5052 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5054 g_assert (klass->parent->vtable_size);
5055 first_iface_slot = klass->parent->vtable_size;
5056 if (mono_class_need_stelemref_method (klass))
5061 * Do the actual changes to @klass inside the loader lock
5063 mono_loader_lock ();
5066 if (klass->inited || mono_class_has_failure (klass)) {
5067 mono_loader_unlock ();
5068 /* Somebody might have gotten in before us */
5069 return !mono_class_has_failure (klass);
5072 UnlockedIncrement (&mono_stats.initialized_class_count);
5074 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5075 UnlockedIncrement (&mono_stats.generic_class_count);
5077 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5078 klass->nested_classes_inited = TRUE;
5079 klass->ghcimpl = ghcimpl;
5080 klass->has_cctor = has_cctor;
5082 klass->vtable_size = vtable_size;
5083 if (has_cached_info) {
5084 klass->has_finalize = cached_info.has_finalize;
5085 klass->has_finalize_inited = TRUE;
5088 mono_class_set_method_count (klass, array_method_count);
5090 mono_loader_unlock ();
5093 setup_interface_offsets (klass, first_iface_slot, TRUE);
5095 if (mono_security_core_clr_enabled ())
5096 mono_security_core_clr_check_inheritance (klass);
5098 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5099 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5104 init_list = mono_native_tls_get_value (init_pending_tls_id);
5105 init_list = g_slist_remove (init_list, klass);
5106 mono_native_tls_set_value (init_pending_tls_id, init_list);
5108 leave_no_init_pending:
5110 mono_loader_unlock ();
5112 /* Leave this for last */
5113 mono_loader_lock ();
5115 mono_loader_unlock ();
5117 return !mono_class_has_failure (klass);
5121 * mono_class_has_finalizer:
5123 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5127 mono_class_has_finalizer (MonoClass *klass)
5129 gboolean has_finalize = FALSE;
5131 if (klass->has_finalize_inited)
5132 return klass->has_finalize;
5134 /* Interfaces and valuetypes are not supposed to have finalizers */
5135 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5136 MonoMethod *cmethod = NULL;
5138 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5139 } else if (mono_class_is_ginst (klass)) {
5140 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5142 has_finalize = mono_class_has_finalizer (gklass);
5143 } else if (klass->parent && klass->parent->has_finalize) {
5144 has_finalize = TRUE;
5146 if (klass->parent) {
5148 * Can't search in metadata for a method named Finalize, because that
5149 * ignores overrides.
5151 mono_class_setup_vtable (klass);
5152 if (mono_class_has_failure (klass))
5155 cmethod = klass->vtable [finalize_slot];
5159 g_assert (klass->vtable_size > finalize_slot);
5161 if (klass->parent) {
5162 if (cmethod->is_inflated)
5163 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5164 if (cmethod != default_finalize)
5165 has_finalize = TRUE;
5171 mono_loader_lock ();
5172 if (!klass->has_finalize_inited) {
5173 klass->has_finalize = has_finalize ? 1 : 0;
5175 mono_memory_barrier ();
5176 klass->has_finalize_inited = TRUE;
5178 mono_loader_unlock ();
5180 return klass->has_finalize;
5184 mono_is_corlib_image (MonoImage *image)
5186 return image == mono_defaults.corlib;
5190 * LOCKING: this assumes the loader lock is held
5193 mono_class_setup_mono_type (MonoClass *klass)
5195 const char *name = klass->name;
5196 const char *nspace = klass->name_space;
5197 gboolean is_corlib = mono_is_corlib_image (klass->image);
5199 klass->this_arg.byref = 1;
5200 klass->this_arg.data.klass = klass;
5201 klass->this_arg.type = MONO_TYPE_CLASS;
5202 klass->byval_arg.data.klass = klass;
5203 klass->byval_arg.type = MONO_TYPE_CLASS;
5205 if (is_corlib && !strcmp (nspace, "System")) {
5206 if (!strcmp (name, "ValueType")) {
5208 * do not set the valuetype bit for System.ValueType.
5209 * klass->valuetype = 1;
5211 klass->blittable = TRUE;
5212 } else if (!strcmp (name, "Enum")) {
5214 * do not set the valuetype bit for System.Enum.
5215 * klass->valuetype = 1;
5217 klass->valuetype = 0;
5218 klass->enumtype = 0;
5219 } else if (!strcmp (name, "Object")) {
5220 klass->byval_arg.type = MONO_TYPE_OBJECT;
5221 klass->this_arg.type = MONO_TYPE_OBJECT;
5222 } else if (!strcmp (name, "String")) {
5223 klass->byval_arg.type = MONO_TYPE_STRING;
5224 klass->this_arg.type = MONO_TYPE_STRING;
5225 } else if (!strcmp (name, "TypedReference")) {
5226 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5227 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5231 if (klass->valuetype) {
5232 int t = MONO_TYPE_VALUETYPE;
5234 if (is_corlib && !strcmp (nspace, "System")) {
5237 if (!strcmp (name, "Boolean")) {
5238 t = MONO_TYPE_BOOLEAN;
5239 } else if (!strcmp(name, "Byte")) {
5241 klass->blittable = TRUE;
5245 if (!strcmp (name, "Char")) {
5250 if (!strcmp (name, "Double")) {
5252 klass->blittable = TRUE;
5256 if (!strcmp (name, "Int32")) {
5258 klass->blittable = TRUE;
5259 } else if (!strcmp(name, "Int16")) {
5261 klass->blittable = TRUE;
5262 } else if (!strcmp(name, "Int64")) {
5264 klass->blittable = TRUE;
5265 } else if (!strcmp(name, "IntPtr")) {
5267 klass->blittable = TRUE;
5271 if (!strcmp (name, "Single")) {
5273 klass->blittable = TRUE;
5274 } else if (!strcmp(name, "SByte")) {
5276 klass->blittable = TRUE;
5280 if (!strcmp (name, "UInt32")) {
5282 klass->blittable = TRUE;
5283 } else if (!strcmp(name, "UInt16")) {
5285 klass->blittable = TRUE;
5286 } else if (!strcmp(name, "UInt64")) {
5288 klass->blittable = TRUE;
5289 } else if (!strcmp(name, "UIntPtr")) {
5291 klass->blittable = TRUE;
5295 if (!strcmp (name, "TypedReference")) {
5296 t = MONO_TYPE_TYPEDBYREF;
5297 klass->blittable = TRUE;
5301 if (!strcmp (name, "Void")) {
5309 klass->byval_arg.type = (MonoTypeEnum)t;
5310 klass->this_arg.type = (MonoTypeEnum)t;
5313 if (MONO_CLASS_IS_INTERFACE (klass)) {
5314 klass->interface_id = mono_get_unique_iid (klass);
5316 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5317 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5318 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5319 * MS returns diferrent types based on which instance is called. For example:
5320 * object obj = new byte[10][];
5321 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5322 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5325 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5326 klass->is_array_special_interface = 1;
5333 * COM initialization is delayed until needed.
5334 * However when a [ComImport] attribute is present on a type it will trigger
5335 * the initialization. This is not a problem unless the BCL being executed
5336 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5339 init_com_from_comimport (MonoClass *klass)
5341 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5342 if (mono_security_core_clr_enabled ()) {
5343 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5344 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5345 /* but it can not be made available for application (i.e. user code) since all COM calls
5346 * are considered native calls. In this case we fail with a TypeLoadException (just like
5347 * Silverlight 2 does */
5348 mono_class_set_type_load_failure (klass, "");
5353 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5355 #endif /*DISABLE_COM*/
5358 * LOCKING: this assumes the loader lock is held
5361 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5363 gboolean system_namespace;
5364 gboolean is_corlib = mono_is_corlib_image (klass->image);
5366 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5368 /* if root of the hierarchy */
5369 if (system_namespace && !strcmp (klass->name, "Object")) {
5370 klass->parent = NULL;
5371 klass->instance_size = sizeof (MonoObject);
5374 if (!strcmp (klass->name, "<Module>")) {
5375 klass->parent = NULL;
5376 klass->instance_size = 0;
5380 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5381 /* Imported COM Objects always derive from __ComObject. */
5383 if (MONO_CLASS_IS_IMPORT (klass)) {
5384 init_com_from_comimport (klass);
5385 if (parent == mono_defaults.object_class)
5386 parent = mono_class_get_com_object_class ();
5390 /* set the parent to something useful and safe, but mark the type as broken */
5391 parent = mono_defaults.object_class;
5392 mono_class_set_type_load_failure (klass, "");
5396 klass->parent = parent;
5398 if (mono_class_is_ginst (parent) && !parent->name) {
5400 * If the parent is a generic instance, we may get
5401 * called before it is fully initialized, especially
5402 * before it has its name.
5407 #ifndef DISABLE_REMOTING
5408 klass->marshalbyref = parent->marshalbyref;
5409 klass->contextbound = parent->contextbound;
5412 klass->delegate = parent->delegate;
5414 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5415 mono_class_set_is_com_object (klass);
5417 if (system_namespace) {
5418 #ifndef DISABLE_REMOTING
5419 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5420 klass->marshalbyref = 1;
5422 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5423 klass->contextbound = 1;
5425 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5426 klass->delegate = 1;
5429 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5430 (strcmp (klass->parent->name_space, "System") == 0)))
5431 klass->valuetype = 1;
5432 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5433 klass->valuetype = klass->enumtype = 1;
5435 /*klass->enumtype = klass->parent->enumtype; */
5437 /* initialize com types if COM interfaces are present */
5439 if (MONO_CLASS_IS_IMPORT (klass))
5440 init_com_from_comimport (klass);
5442 klass->parent = NULL;
5448 * mono_class_setup_supertypes:
5451 * Build the data structure needed to make fast type checks work.
5452 * This currently sets two fields in @class:
5453 * - idepth: distance between @class and System.Object in the type
5455 * - supertypes: array of classes: each element has a class in the hierarchy
5456 * starting from @class up to System.Object
5458 * LOCKING: Acquires the loader lock.
5461 mono_class_setup_supertypes (MonoClass *klass)
5464 MonoClass **supertypes;
5466 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5470 if (klass->parent && !klass->parent->supertypes)
5471 mono_class_setup_supertypes (klass->parent);
5473 idepth = klass->parent->idepth + 1;
5477 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5478 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5480 if (klass->parent) {
5481 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5484 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5485 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5487 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5490 mono_memory_barrier ();
5492 mono_loader_lock ();
5493 klass->idepth = idepth;
5494 /* Needed so idepth is visible before supertypes is set */
5495 mono_memory_barrier ();
5496 klass->supertypes = supertypes;
5497 mono_loader_unlock ();
5501 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5503 return mono_class_get_generic_class (gclass)->container_class == user_data;
5507 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5509 MonoClass *gtd = (MonoClass*)user_data;
5510 /* Only try to fix generic instances of @gtd */
5511 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5514 /* Check if the generic instance has no parent. */
5515 if (gtd->parent && !gclass->parent)
5516 mono_generic_class_setup_parent (gclass, gtd);
5522 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5524 mono_class_set_type_load_failure (klass, "%s", msg);
5525 mono_error_set_type_load_class (error, klass, "%s", msg);
5529 * mono_class_create_from_typedef:
5530 * \param image: image where the token is valid
5531 * \param type_token: typedef token
5532 * \param error: used to return any error found while creating the type
5534 * Create the MonoClass* representing the specified type token.
5535 * \p type_token must be a TypeDef token.
5537 * FIXME: don't return NULL on failure, just let the caller figure it out.
5540 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5542 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5543 MonoClass *klass, *parent = NULL;
5544 guint32 cols [MONO_TYPEDEF_SIZE];
5545 guint32 cols_next [MONO_TYPEDEF_SIZE];
5546 guint tidx = mono_metadata_token_index (type_token);
5547 MonoGenericContext *context = NULL;
5548 const char *name, *nspace;
5550 MonoClass **interfaces;
5551 guint32 field_last, method_last;
5552 guint32 nesting_tokeen;
5556 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5557 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5561 mono_loader_lock ();
5563 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5564 mono_loader_unlock ();
5568 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5570 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5571 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5573 if (mono_metadata_has_generic_params (image, type_token)) {
5574 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5575 klass->class_kind = MONO_CLASS_GTD;
5576 UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
5579 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5580 klass->class_kind = MONO_CLASS_DEF;
5581 UnlockedAdd (&classes_size, sizeof (MonoClassDef));
5586 klass->name_space = nspace;
5588 MONO_PROFILER_RAISE (class_loading, (klass));
5590 klass->image = image;
5591 klass->type_token = type_token;
5592 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5594 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5597 * Check whether we're a generic type definition.
5599 if (mono_class_is_gtd (klass)) {
5600 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5601 generic_container->owner.klass = klass;
5602 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5603 context = &generic_container->context;
5604 mono_class_set_generic_container (klass, generic_container);
5605 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5606 canonical_inst->type = MONO_TYPE_GENERICINST;
5607 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5608 enable_gclass_recording ();
5611 if (cols [MONO_TYPEDEF_EXTENDS]) {
5613 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5615 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5616 /*WARNING: this must satisfy mono_metadata_type_hash*/
5617 klass->this_arg.byref = 1;
5618 klass->this_arg.data.klass = klass;
5619 klass->this_arg.type = MONO_TYPE_CLASS;
5620 klass->byval_arg.data.klass = klass;
5621 klass->byval_arg.type = MONO_TYPE_CLASS;
5623 parent = mono_class_get_checked (image, parent_token, error);
5624 if (parent && context) /* Always inflate */
5625 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5627 if (parent == NULL) {
5628 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5629 goto parent_failure;
5632 for (tmp = parent; tmp; tmp = tmp->parent) {
5634 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5635 goto parent_failure;
5637 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5638 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5639 goto parent_failure;
5644 mono_class_setup_parent (klass, parent);
5646 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5647 mono_class_setup_mono_type (klass);
5649 if (mono_class_is_gtd (klass))
5650 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5653 * This might access klass->byval_arg for recursion generated by generic constraints,
5654 * so it has to come after setup_mono_type ().
5656 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5657 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5658 if (!mono_error_ok (error)) {
5659 /*FIXME implement a mono_class_set_failure_from_mono_error */
5660 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5661 mono_loader_unlock ();
5662 MONO_PROFILER_RAISE (class_failed, (klass));
5667 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5671 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5675 klass->cast_class = klass->element_class = klass;
5676 if (mono_is_corlib_image (klass->image)) {
5677 switch (klass->byval_arg.type) {
5679 if (mono_defaults.byte_class)
5680 klass->cast_class = mono_defaults.byte_class;
5683 if (mono_defaults.sbyte_class)
5684 mono_defaults.sbyte_class = klass;
5687 if (mono_defaults.uint16_class)
5688 mono_defaults.uint16_class = klass;
5691 if (mono_defaults.int16_class)
5692 klass->cast_class = mono_defaults.int16_class;
5695 if (mono_defaults.uint32_class)
5696 mono_defaults.uint32_class = klass;
5699 if (mono_defaults.int32_class)
5700 klass->cast_class = mono_defaults.int32_class;
5703 if (mono_defaults.uint64_class)
5704 mono_defaults.uint64_class = klass;
5707 if (mono_defaults.int64_class)
5708 klass->cast_class = mono_defaults.int64_class;
5713 if (!klass->enumtype) {
5714 if (!mono_metadata_interfaces_from_typedef_full (
5715 image, type_token, &interfaces, &icount, FALSE, context, error)){
5717 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5718 mono_loader_unlock ();
5719 MONO_PROFILER_RAISE (class_failed, (klass));
5723 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5724 g_assert(icount <= 65535);
5726 klass->interfaces = interfaces;
5727 klass->interface_count = icount;
5728 klass->interfaces_inited = 1;
5731 /*g_print ("Load class %s\n", name);*/
5734 * Compute the field and method lists
5736 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5737 mono_class_set_first_field_idx (klass, first_field_idx);
5738 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5739 mono_class_set_first_method_idx (klass, first_method_idx);
5741 if (tt->rows > tidx){
5742 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5743 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5744 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5746 field_last = image->tables [MONO_TABLE_FIELD].rows;
5747 method_last = image->tables [MONO_TABLE_METHOD].rows;
5750 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5751 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5752 mono_class_set_field_count (klass, field_last - first_field_idx);
5753 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5754 mono_class_set_method_count (klass, method_last - first_method_idx);
5756 /* reserve space to store vector pointer in arrays */
5757 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5758 klass->instance_size += 2 * sizeof (gpointer);
5759 g_assert (mono_class_get_field_count (klass) == 0);
5762 if (klass->enumtype) {
5763 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5764 if (!enum_basetype) {
5765 /*set it to a default value as the whole runtime can't handle this to be null*/
5766 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5767 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5768 mono_loader_unlock ();
5769 MONO_PROFILER_RAISE (class_failed, (klass));
5772 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5776 * If we're a generic type definition, load the constraints.
5777 * We must do this after the class has been constructed to make certain recursive scenarios
5780 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5781 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5782 mono_loader_unlock ();
5783 MONO_PROFILER_RAISE (class_failed, (klass));
5787 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5788 if (!strncmp (name, "Vector", 6))
5789 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");
5790 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5791 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5792 klass->simd_type = 1;
5795 mono_loader_unlock ();
5797 MONO_PROFILER_RAISE (class_loaded, (klass));
5802 if (mono_class_is_gtd (klass))
5803 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5805 mono_class_setup_mono_type (klass);
5806 mono_loader_unlock ();
5807 MONO_PROFILER_RAISE (class_failed, (klass));
5811 /** Is klass a Nullable<T> ginst? */
5813 mono_class_is_nullable (MonoClass *klass)
5815 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5816 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5820 /** if klass is T? return T */
5822 mono_class_get_nullable_param (MonoClass *klass)
5824 g_assert (mono_class_is_nullable (klass));
5825 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5829 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5833 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5835 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5836 if (!mono_error_ok (&error)) {
5837 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5838 klass->parent = mono_defaults.object_class;
5839 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5840 mono_error_cleanup (&error);
5843 mono_loader_lock ();
5845 mono_class_setup_parent (klass, klass->parent);
5847 if (klass->enumtype) {
5848 klass->cast_class = gtd->cast_class;
5849 klass->element_class = gtd->element_class;
5851 mono_loader_unlock ();
5855 mono_type_is_primitive (MonoType *type)
5857 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5858 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5862 * Create the `MonoClass' for an instantiation of a generic type.
5863 * We only do this if we actually need it.
5866 mono_generic_class_get_class (MonoGenericClass *gclass)
5868 MonoClass *klass, *gklass;
5870 if (gclass->cached_class)
5871 return gclass->cached_class;
5873 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5875 gklass = gclass->container_class;
5877 if (gklass->nested_in) {
5878 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5879 klass->nested_in = gklass->nested_in;
5882 klass->name = gklass->name;
5883 klass->name_space = gklass->name_space;
5885 klass->image = gklass->image;
5886 klass->type_token = gklass->type_token;
5888 klass->class_kind = MONO_CLASS_GINST;
5890 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5892 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5893 klass->this_arg.type = klass->byval_arg.type;
5894 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5895 klass->this_arg.byref = TRUE;
5896 klass->enumtype = gklass->enumtype;
5897 klass->valuetype = gklass->valuetype;
5900 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5901 g_assert (gclass->context.class_inst);
5902 g_assert (gclass->context.class_inst->type_argc > 0);
5903 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5904 klass->simd_type = 1;
5906 klass->is_array_special_interface = gklass->is_array_special_interface;
5908 klass->cast_class = klass->element_class = klass;
5910 if (gclass->is_dynamic) {
5912 * 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.
5913 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5914 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5916 if (!gklass->wastypebuilder)
5919 if (klass->enumtype) {
5921 * For enums, gklass->fields might not been set, but instance_size etc. is
5922 * already set in mono_reflection_create_internal_class (). For non-enums,
5923 * these will be computed normally in mono_class_layout_fields ().
5925 klass->instance_size = gklass->instance_size;
5926 klass->sizes.class_size = gklass->sizes.class_size;
5927 klass->size_inited = 1;
5931 mono_loader_lock ();
5933 if (gclass->cached_class) {
5934 mono_loader_unlock ();
5935 return gclass->cached_class;
5938 if (record_gclass_instantiation > 0)
5939 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5941 if (mono_class_is_nullable (klass))
5942 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5944 MONO_PROFILER_RAISE (class_loading, (klass));
5946 mono_generic_class_setup_parent (klass, gklass);
5948 if (gclass->is_dynamic)
5949 mono_class_setup_supertypes (klass);
5951 mono_memory_barrier ();
5952 gclass->cached_class = klass;
5954 MONO_PROFILER_RAISE (class_loaded, (klass));
5956 ++class_ginst_count;
5957 inflated_classes_size += sizeof (MonoClassGenericInst);
5959 mono_loader_unlock ();
5965 get_image_for_container (MonoGenericContainer *container)
5968 if (container->is_anonymous) {
5969 result = container->owner.image;
5972 if (container->is_method) {
5973 MonoMethod *method = container->owner.method;
5974 g_assert_checked (method);
5975 klass = method->klass;
5977 klass = container->owner.klass;
5979 g_assert_checked (klass);
5980 result = klass->image;
5987 get_image_for_generic_param (MonoGenericParam *param)
5989 MonoGenericContainer *container = mono_generic_param_owner (param);
5990 g_assert_checked (container);
5991 return get_image_for_container (container);
5994 // Make a string in the designated image consisting of a single integer.
5995 #define INT_STRING_SIZE 16
5997 make_generic_name_string (MonoImage *image, int num)
5999 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6000 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6004 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6005 // pinfo is derived from param by the caller for us.
6007 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6009 MonoClass *klass, **ptr;
6011 MonoGenericContainer *container = mono_generic_param_owner (param);
6012 g_assert_checked (container);
6014 MonoImage *image = get_image_for_container (container);
6015 gboolean is_mvar = container->is_method;
6016 gboolean is_anonymous = container->is_anonymous;
6018 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6019 klass->class_kind = MONO_CLASS_GPARAM;
6020 UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
6021 UnlockedIncrement (&class_gparam_count);
6024 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6026 int n = mono_generic_param_num (param);
6027 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6031 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6032 } else if (is_mvar) {
6033 MonoMethod *omethod = container->owner.method;
6034 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6036 MonoClass *oklass = container->owner.klass;
6037 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6040 MONO_PROFILER_RAISE (class_loading, (klass));
6042 // Count non-NULL items in pinfo->constraints
6045 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6049 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6050 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6052 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6053 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6055 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6058 if (count - pos > 0) {
6059 klass->interface_count = count - pos;
6060 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6061 klass->interfaces_inited = TRUE;
6062 for (i = pos; i < count; i++)
6063 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6066 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6068 klass->inited = TRUE;
6069 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6070 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6072 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6073 klass->this_arg.type = klass->byval_arg.type;
6074 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6075 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6076 klass->this_arg.byref = TRUE;
6078 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6079 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6081 /*Init these fields to sane values*/
6082 klass->min_align = 1;
6084 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6085 * constrained to, the JIT depends on this.
6087 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6088 mono_memory_barrier ();
6089 klass->size_inited = 1;
6091 mono_class_setup_supertypes (klass);
6093 if (count - pos > 0) {
6094 mono_class_setup_vtable (klass->parent);
6095 if (mono_class_has_failure (klass->parent))
6096 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6098 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6104 #define FAST_CACHE_SIZE 16
6107 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6108 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6109 * we cache the MonoClasses.
6110 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6111 * LOCKING: Takes the image lock depending on @take_lock.
6114 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6116 int n = mono_generic_param_num (param);
6117 MonoImage *image = get_image_for_generic_param (param);
6118 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6119 MonoClass *klass = NULL;
6124 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6125 // For high numbers or constraints we have to use pointer hashes.
6126 if (param->gshared_constraint) {
6127 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6130 mono_image_lock (image);
6131 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6133 mono_image_unlock (image);
6138 if (n < FAST_CACHE_SIZE) {
6140 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6142 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6144 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6147 mono_image_lock (image);
6148 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6150 mono_image_unlock (image);
6157 * LOCKING: Image lock (param->image) must be held
6160 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6162 int n = mono_generic_param_num (param);
6163 MonoImage *image = get_image_for_generic_param (param);
6164 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6168 if (param->gshared_constraint) {
6169 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6171 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6172 mono_memory_barrier ();
6174 image->mvar_cache_constrained = ht;
6176 image->var_cache_constrained = ht;
6178 g_hash_table_insert (ht, param, klass);
6179 } else if (n < FAST_CACHE_SIZE) {
6181 /* Requires locking to avoid droping an already published class */
6182 if (!image->mvar_cache_fast)
6183 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6184 image->mvar_cache_fast [n] = klass;
6186 if (!image->var_cache_fast)
6187 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6188 image->var_cache_fast [n] = klass;
6191 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6193 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6195 ht = g_hash_table_new (NULL, NULL);
6196 mono_memory_barrier ();
6198 image->mvar_cache_slow = ht;
6200 image->var_cache_slow = ht;
6203 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6208 * LOCKING: Acquires the image lock (@image).
6211 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6213 MonoImage *image = get_image_for_generic_param (param);
6214 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6215 MonoClass *klass, *klass2;
6217 // If a klass already exists for this object and is cached, return it.
6218 if (pinfo) // Non-anonymous
6219 klass = pinfo->pklass;
6221 klass = get_anon_gparam_class (param, TRUE);
6226 // Create a new klass
6227 klass = make_generic_param_class (param, pinfo);
6229 // Now we need to cache the klass we created.
6230 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6231 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6232 // and allow our newly-created klass object to just leak.
6233 mono_memory_barrier ();
6235 mono_image_lock (image);
6237 // Here "klass2" refers to the klass potentially created by the other thread.
6238 if (pinfo) // Repeat check from above
6239 klass2 = pinfo->pklass;
6241 klass2 = get_anon_gparam_class (param, FALSE);
6248 pinfo->pklass = klass;
6250 set_anon_gparam_class (param, klass);
6252 mono_image_unlock (image);
6254 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6256 MONO_PROFILER_RAISE (class_failed, (klass2));
6258 MONO_PROFILER_RAISE (class_loaded, (klass));
6264 * mono_class_from_generic_parameter:
6265 * \param param Parameter to find/construct a class for.
6266 * \param arg2 Is ignored.
6267 * \param arg3 Is ignored.
6270 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6272 return mono_class_from_generic_parameter_internal (param);
6276 * mono_ptr_class_get:
6279 mono_ptr_class_get (MonoType *type)
6282 MonoClass *el_class;
6286 el_class = mono_class_from_mono_type (type);
6287 image = el_class->image;
6289 mono_image_lock (image);
6290 if (image->ptr_cache) {
6291 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6292 mono_image_unlock (image);
6296 mono_image_unlock (image);
6298 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6300 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6301 ++class_pointer_count;
6303 result->parent = NULL; /* no parent for PTR types */
6304 result->name_space = el_class->name_space;
6305 name = g_strdup_printf ("%s*", el_class->name);
6306 result->name = mono_image_strdup (image, name);
6307 result->class_kind = MONO_CLASS_POINTER;
6310 MONO_PROFILER_RAISE (class_loading, (result));
6312 result->image = el_class->image;
6313 result->inited = TRUE;
6314 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6315 result->cast_class = result->element_class = el_class;
6316 result->blittable = TRUE;
6318 result->byval_arg.type = MONO_TYPE_PTR;
6319 result->this_arg.type = result->byval_arg.type;
6320 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6321 result->this_arg.byref = TRUE;
6323 mono_class_setup_supertypes (result);
6325 mono_image_lock (image);
6326 if (image->ptr_cache) {
6328 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6329 mono_image_unlock (image);
6330 MONO_PROFILER_RAISE (class_failed, (result));
6334 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6336 g_hash_table_insert (image->ptr_cache, el_class, result);
6337 mono_image_unlock (image);
6339 MONO_PROFILER_RAISE (class_loaded, (result));
6345 mono_fnptr_class_get (MonoMethodSignature *sig)
6347 MonoClass *result, *cached;
6348 static GHashTable *ptr_hash = NULL;
6350 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6352 mono_loader_lock ();
6354 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6355 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6356 mono_loader_unlock ();
6360 result = g_new0 (MonoClass, 1);
6362 result->parent = NULL; /* no parent for PTR types */
6363 result->name_space = "System";
6364 result->name = "MonoFNPtrFakeClass";
6365 result->class_kind = MONO_CLASS_POINTER;
6367 result->image = mono_defaults.corlib; /* need to fix... */
6368 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6369 result->cast_class = result->element_class = result;
6370 result->byval_arg.type = MONO_TYPE_FNPTR;
6371 result->this_arg.type = result->byval_arg.type;
6372 result->this_arg.data.method = result->byval_arg.data.method = sig;
6373 result->this_arg.byref = TRUE;
6374 result->blittable = TRUE;
6375 result->inited = TRUE;
6377 mono_class_setup_supertypes (result);
6379 mono_loader_lock ();
6381 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6384 mono_loader_unlock ();
6388 MONO_PROFILER_RAISE (class_loading, (result));
6390 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6391 ++class_pointer_count;
6393 g_hash_table_insert (ptr_hash, sig, result);
6395 mono_loader_unlock ();
6397 MONO_PROFILER_RAISE (class_loaded, (result));
6403 * mono_class_from_mono_type:
6404 * \param type describes the type to return
6405 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6408 mono_class_from_mono_type (MonoType *type)
6410 switch (type->type) {
6411 case MONO_TYPE_OBJECT:
6412 return type->data.klass? type->data.klass: mono_defaults.object_class;
6413 case MONO_TYPE_VOID:
6414 return type->data.klass? type->data.klass: mono_defaults.void_class;
6415 case MONO_TYPE_BOOLEAN:
6416 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6417 case MONO_TYPE_CHAR:
6418 return type->data.klass? type->data.klass: mono_defaults.char_class;
6420 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6422 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6424 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6426 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6428 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6430 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6432 return type->data.klass? type->data.klass: mono_defaults.int_class;
6434 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6436 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6438 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6440 return type->data.klass? type->data.klass: mono_defaults.single_class;
6442 return type->data.klass? type->data.klass: mono_defaults.double_class;
6443 case MONO_TYPE_STRING:
6444 return type->data.klass? type->data.klass: mono_defaults.string_class;
6445 case MONO_TYPE_TYPEDBYREF:
6446 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6447 case MONO_TYPE_ARRAY:
6448 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6450 return mono_ptr_class_get (type->data.type);
6451 case MONO_TYPE_FNPTR:
6452 return mono_fnptr_class_get (type->data.method);
6453 case MONO_TYPE_SZARRAY:
6454 return mono_array_class_get (type->data.klass, 1);
6455 case MONO_TYPE_CLASS:
6456 case MONO_TYPE_VALUETYPE:
6457 return type->data.klass;
6458 case MONO_TYPE_GENERICINST:
6459 return mono_generic_class_get_class (type->data.generic_class);
6460 case MONO_TYPE_MVAR:
6462 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6464 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6465 g_assert_not_reached ();
6468 // Yes, this returns NULL, even if it is documented as not doing so, but there
6469 // is no way for the code to make it this far, due to the assert above.
6474 * mono_type_retrieve_from_typespec
6475 * \param image context where the image is created
6476 * \param type_spec typespec token
6477 * \param context the generic context used to evaluate generic instantiations in
6480 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6482 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6484 *did_inflate = FALSE;
6489 if (context && (context->class_inst || context->method_inst)) {
6490 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6492 if (!mono_error_ok (error)) {
6498 *did_inflate = TRUE;
6505 * mono_class_create_from_typespec
6506 * \param image context where the image is created
6507 * \param type_spec typespec token
6508 * \param context the generic context used to evaluate generic instantiations in
6511 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6514 gboolean inflated = FALSE;
6515 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6516 return_val_if_nok (error, NULL);
6517 ret = mono_class_from_mono_type (t);
6519 mono_metadata_free_type (t);
6524 * mono_bounded_array_class_get:
6525 * \param element_class element class
6526 * \param rank the dimension of the array class
6527 * \param bounded whenever the array has non-zero bounds
6528 * \returns A class object describing the array with element type \p element_type and
6529 * dimension \p rank.
6532 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6535 MonoClass *klass, *cached, *k;
6536 MonoClass *parent = NULL;
6537 GSList *list, *rootlist = NULL;
6541 g_assert (rank <= 255);
6544 /* bounded only matters for one-dimensional arrays */
6547 image = eclass->image;
6551 if (rank == 1 && !bounded) {
6553 * This case is very frequent not just during compilation because of calls
6554 * from mono_class_from_mono_type (), mono_array_new (),
6555 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6557 mono_os_mutex_lock (&image->szarray_cache_lock);
6558 if (!image->szarray_cache)
6559 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6560 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6561 mono_os_mutex_unlock (&image->szarray_cache_lock);
6563 mono_loader_lock ();
6564 if (!image->array_cache)
6565 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6566 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6567 for (list = rootlist; list; list = list->next) {
6568 k = (MonoClass *)list->data;
6569 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6574 mono_loader_unlock ();
6579 parent = mono_defaults.array_class;
6580 if (!parent->inited)
6581 mono_class_init (parent);
6583 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6585 klass->image = image;
6586 klass->name_space = eclass->name_space;
6587 klass->class_kind = MONO_CLASS_ARRAY;
6589 nsize = strlen (eclass->name);
6590 name = (char *)g_malloc (nsize + 2 + rank + 1);
6591 memcpy (name, eclass->name, nsize);
6594 memset (name + nsize + 1, ',', rank - 1);
6596 name [nsize + rank] = '*';
6597 name [nsize + rank + bounded] = ']';
6598 name [nsize + rank + bounded + 1] = 0;
6599 klass->name = mono_image_strdup (image, name);
6602 klass->type_token = 0;
6603 klass->parent = parent;
6604 klass->instance_size = mono_class_instance_size (klass->parent);
6606 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6607 /*Arrays of those two types are invalid.*/
6608 MonoError prepared_error;
6609 error_init (&prepared_error);
6610 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6611 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6612 mono_error_cleanup (&prepared_error);
6613 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6614 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6615 if (!ref_info_handle || eclass->wastypebuilder) {
6616 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6617 g_assert (ref_info_handle && !eclass->wastypebuilder);
6619 /* element_size -1 is ok as this is not an instantitable type*/
6620 klass->sizes.element_size = -1;
6622 klass->sizes.element_size = -1;
6624 mono_class_setup_supertypes (klass);
6626 if (mono_class_is_ginst (eclass))
6627 mono_class_init (eclass);
6628 if (!eclass->size_inited)
6629 mono_class_setup_fields (eclass);
6630 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6631 /*FIXME we fail the array type, but we have to let other fields be set.*/
6633 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6637 if (eclass->enumtype)
6638 klass->cast_class = eclass->element_class;
6640 klass->cast_class = eclass;
6642 switch (klass->cast_class->byval_arg.type) {
6644 klass->cast_class = mono_defaults.byte_class;
6647 klass->cast_class = mono_defaults.int16_class;
6650 #if SIZEOF_VOID_P == 4
6654 klass->cast_class = mono_defaults.int32_class;
6657 #if SIZEOF_VOID_P == 8
6661 klass->cast_class = mono_defaults.int64_class;
6667 klass->element_class = eclass;
6669 if ((rank > 1) || bounded) {
6670 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6671 klass->byval_arg.type = MONO_TYPE_ARRAY;
6672 klass->byval_arg.data.array = at;
6673 at->eklass = eclass;
6675 /* FIXME: complete.... */
6677 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6678 klass->byval_arg.data.klass = eclass;
6680 klass->this_arg = klass->byval_arg;
6681 klass->this_arg.byref = 1;
6684 MonoError prepared_error;
6685 error_init (&prepared_error);
6686 name = mono_type_get_full_name (klass);
6687 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6688 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6689 mono_error_cleanup (&prepared_error);
6693 mono_loader_lock ();
6695 /* Check cache again */
6697 if (rank == 1 && !bounded) {
6698 mono_os_mutex_lock (&image->szarray_cache_lock);
6699 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6700 mono_os_mutex_unlock (&image->szarray_cache_lock);
6702 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6703 for (list = rootlist; list; list = list->next) {
6704 k = (MonoClass *)list->data;
6705 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6712 mono_loader_unlock ();
6716 MONO_PROFILER_RAISE (class_loading, (klass));
6718 UnlockedAdd (&classes_size, sizeof (MonoClassArray));
6719 ++class_array_count;
6721 if (rank == 1 && !bounded) {
6722 mono_os_mutex_lock (&image->szarray_cache_lock);
6723 g_hash_table_insert (image->szarray_cache, eclass, klass);
6724 mono_os_mutex_unlock (&image->szarray_cache_lock);
6726 list = g_slist_append (rootlist, klass);
6727 g_hash_table_insert (image->array_cache, eclass, list);
6730 mono_loader_unlock ();
6732 MONO_PROFILER_RAISE (class_loaded, (klass));
6738 * mono_array_class_get:
6739 * \param element_class element class
6740 * \param rank the dimension of the array class
6741 * \returns A class object describing the array with element type \p element_type and
6742 * dimension \p rank.
6745 mono_array_class_get (MonoClass *eclass, guint32 rank)
6747 return mono_bounded_array_class_get (eclass, rank, FALSE);
6751 * mono_class_instance_size:
6752 * \param klass a class
6754 * Use to get the size of a class in bytes.
6756 * \returns The size of an object instance
6759 mono_class_instance_size (MonoClass *klass)
6761 if (!klass->size_inited)
6762 mono_class_init (klass);
6764 return klass->instance_size;
6768 * mono_class_min_align:
6769 * \param klass a class
6771 * Use to get the computed minimum alignment requirements for the specified class.
6773 * Returns: minimum alignment requirements
6776 mono_class_min_align (MonoClass *klass)
6778 if (!klass->size_inited)
6779 mono_class_init (klass);
6781 return klass->min_align;
6785 * mono_class_value_size:
6786 * \param klass a class
6788 * This function is used for value types, and return the
6789 * space and the alignment to store that kind of value object.
6791 * \returns the size of a value of kind \p klass
6794 mono_class_value_size (MonoClass *klass, guint32 *align)
6798 /* fixme: check disable, because we still have external revereces to
6799 * mscorlib and Dummy Objects
6801 /*g_assert (klass->valuetype);*/
6803 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6806 *align = klass->min_align;
6812 * mono_class_data_size:
6813 * \param klass a class
6815 * \returns The size of the static class data
6818 mono_class_data_size (MonoClass *klass)
6821 mono_class_init (klass);
6822 /* This can happen with dynamically created types */
6823 if (!klass->fields_inited)
6824 mono_class_setup_fields (klass);
6826 /* in arrays, sizes.class_size is unioned with element_size
6827 * and arrays have no static fields
6831 return klass->sizes.class_size;
6835 * Auxiliary routine to mono_class_get_field
6837 * Takes a field index instead of a field token.
6839 static MonoClassField *
6840 mono_class_get_field_idx (MonoClass *klass, int idx)
6842 mono_class_setup_fields (klass);
6843 if (mono_class_has_failure (klass))
6847 int first_field_idx = mono_class_get_first_field_idx (klass);
6848 int fcount = mono_class_get_field_count (klass);
6849 if (klass->image->uncompressed_metadata) {
6851 * first_field_idx points to the FieldPtr table, while idx points into the
6852 * Field table, so we have to do a search.
6854 /*FIXME this is broken for types with multiple fields with the same name.*/
6855 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6858 for (i = 0; i < fcount; ++i)
6859 if (mono_field_get_name (&klass->fields [i]) == name)
6860 return &klass->fields [i];
6861 g_assert_not_reached ();
6864 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6865 return &klass->fields [idx - first_field_idx];
6869 klass = klass->parent;
6875 * mono_class_get_field:
6876 * \param class the class to lookup the field.
6877 * \param field_token the field token
6879 * \returns A \c MonoClassField representing the type and offset of
6880 * the field, or a NULL value if the field does not belong to this
6884 mono_class_get_field (MonoClass *klass, guint32 field_token)
6886 int idx = mono_metadata_token_index (field_token);
6888 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6890 return mono_class_get_field_idx (klass, idx - 1);
6894 * mono_class_get_field_from_name:
6895 * \param klass the class to lookup the field.
6896 * \param name the field name
6898 * Search the class \p klass and its parents for a field with the name \p name.
6900 * \returns The \c MonoClassField pointer of the named field or NULL
6903 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6905 return mono_class_get_field_from_name_full (klass, name, NULL);
6909 * mono_class_get_field_from_name_full:
6910 * \param klass the class to lookup the field.
6911 * \param name the field name
6912 * \param type the type of the fields. This optional.
6914 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6916 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6917 * of its generic type definition.
6919 * \returns The MonoClassField pointer of the named field or NULL
6922 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6926 mono_class_setup_fields (klass);
6927 if (mono_class_has_failure (klass))
6931 int fcount = mono_class_get_field_count (klass);
6932 for (i = 0; i < fcount; ++i) {
6933 MonoClassField *field = &klass->fields [i];
6935 if (strcmp (name, mono_field_get_name (field)) != 0)
6939 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6940 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6945 klass = klass->parent;
6951 * mono_class_get_field_token:
6952 * \param field the field we need the token of
6954 * Get the token of a field. Note that the tokesn is only valid for the image
6955 * the field was loaded from. Don't use this function for fields in dynamic types.
6957 * \returns The token representing the field in the image it was loaded from.
6960 mono_class_get_field_token (MonoClassField *field)
6962 MonoClass *klass = field->parent;
6965 mono_class_setup_fields (klass);
6970 int first_field_idx = mono_class_get_first_field_idx (klass);
6971 int fcount = mono_class_get_field_count (klass);
6972 for (i = 0; i < fcount; ++i) {
6973 if (&klass->fields [i] == field) {
6974 int idx = first_field_idx + i + 1;
6976 if (klass->image->uncompressed_metadata)
6977 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6978 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6981 klass = klass->parent;
6984 g_assert_not_reached ();
6989 mono_field_get_index (MonoClassField *field)
6991 int index = field - field->parent->fields;
6992 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6998 * mono_class_get_field_default_value:
7000 * Return the default value of the field as a pointer into the metadata blob.
7003 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7006 guint32 constant_cols [MONO_CONSTANT_SIZE];
7008 MonoClass *klass = field->parent;
7009 MonoFieldDefaultValue *def_values;
7011 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7013 def_values = mono_class_get_field_def_values (klass);
7015 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7017 mono_class_set_field_def_values (klass, def_values);
7020 field_index = mono_field_get_index (field);
7022 if (!def_values [field_index].data) {
7023 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7027 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7029 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7030 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7031 mono_memory_barrier ();
7032 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7035 *def_type = def_values [field_index].def_type;
7036 return def_values [field_index].data;
7040 mono_property_get_index (MonoProperty *prop)
7042 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7043 int index = prop - info->properties;
7045 g_assert (index >= 0 && index < info->count);
7051 * mono_class_get_property_default_value:
7053 * Return the default value of the field as a pointer into the metadata blob.
7056 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7059 guint32 constant_cols [MONO_CONSTANT_SIZE];
7060 MonoClass *klass = property->parent;
7062 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7064 * We don't cache here because it is not used by C# so it's quite rare, but
7065 * we still do the lookup in klass->ext because that is where the data
7066 * is stored for dynamic assemblies.
7069 if (image_is_dynamic (klass->image)) {
7070 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7071 int prop_index = mono_property_get_index (property);
7072 if (info->def_values && info->def_values [prop_index].data) {
7073 *def_type = info->def_values [prop_index].def_type;
7074 return info->def_values [prop_index].data;
7078 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7082 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7083 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7084 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7088 * mono_class_get_event_token:
7091 mono_class_get_event_token (MonoEvent *event)
7093 MonoClass *klass = event->parent;
7097 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7099 for (i = 0; i < info->count; ++i) {
7100 if (&info->events [i] == event)
7101 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7104 klass = klass->parent;
7107 g_assert_not_reached ();
7112 * mono_class_get_property_from_name:
7113 * \param klass a class
7114 * \param name name of the property to lookup in the specified class
7116 * Use this method to lookup a property in a class
7117 * \returns the \c MonoProperty with the given name, or NULL if the property
7118 * does not exist on the \p klass.
7121 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7125 gpointer iter = NULL;
7126 while ((p = mono_class_get_properties (klass, &iter))) {
7127 if (! strcmp (name, p->name))
7130 klass = klass->parent;
7136 * mono_class_get_property_token:
7137 * \param prop MonoProperty to query
7139 * \returns The ECMA token for the specified property.
7142 mono_class_get_property_token (MonoProperty *prop)
7144 MonoClass *klass = prop->parent;
7148 gpointer iter = NULL;
7149 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7150 while ((p = mono_class_get_properties (klass, &iter))) {
7151 if (&info->properties [i] == prop)
7152 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7156 klass = klass->parent;
7159 g_assert_not_reached ();
7164 * mono_class_name_from_token:
7167 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7169 const char *name, *nspace;
7170 if (image_is_dynamic (image))
7171 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7173 switch (type_token & 0xff000000){
7174 case MONO_TOKEN_TYPE_DEF: {
7175 guint32 cols [MONO_TYPEDEF_SIZE];
7176 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7177 guint tidx = mono_metadata_token_index (type_token);
7179 if (tidx > tt->rows)
7180 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7182 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7183 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7184 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7185 if (strlen (nspace) == 0)
7186 return g_strdup_printf ("%s", name);
7188 return g_strdup_printf ("%s.%s", nspace, name);
7191 case MONO_TOKEN_TYPE_REF: {
7193 guint32 cols [MONO_TYPEREF_SIZE];
7194 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7195 guint tidx = mono_metadata_token_index (type_token);
7198 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7200 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7201 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7202 mono_error_cleanup (&error);
7206 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7207 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7208 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7209 if (strlen (nspace) == 0)
7210 return g_strdup_printf ("%s", name);
7212 return g_strdup_printf ("%s.%s", nspace, name);
7215 case MONO_TOKEN_TYPE_SPEC:
7216 return g_strdup_printf ("Typespec 0x%08x", type_token);
7218 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7223 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7225 if (image_is_dynamic (image))
7226 return g_strdup_printf ("DynamicAssembly %s", image->name);
7228 switch (type_token & 0xff000000){
7229 case MONO_TOKEN_TYPE_DEF:
7230 if (image->assembly)
7231 return mono_stringify_assembly_name (&image->assembly->aname);
7232 else if (image->assembly_name)
7233 return g_strdup (image->assembly_name);
7234 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7235 case MONO_TOKEN_TYPE_REF: {
7237 MonoAssemblyName aname;
7238 guint32 cols [MONO_TYPEREF_SIZE];
7239 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7240 guint32 idx = mono_metadata_token_index (type_token);
7243 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7245 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7246 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7247 mono_error_cleanup (&error);
7250 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7252 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7253 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7254 case MONO_RESOLUTION_SCOPE_MODULE:
7256 return g_strdup ("");
7257 case MONO_RESOLUTION_SCOPE_MODULEREF:
7259 return g_strdup ("");
7260 case MONO_RESOLUTION_SCOPE_TYPEREF:
7262 return g_strdup ("");
7263 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7264 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7265 return mono_stringify_assembly_name (&aname);
7267 g_assert_not_reached ();
7271 case MONO_TOKEN_TYPE_SPEC:
7273 return g_strdup ("");
7275 g_assert_not_reached ();
7282 * mono_class_get_full:
7283 * \param image the image where the class resides
7284 * \param type_token the token for the class
7285 * \param context the generic context used to evaluate generic instantiations in
7286 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7287 * \returns The \c MonoClass that represents \p type_token in \p image
7290 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7294 klass = mono_class_get_checked (image, type_token, &error);
7296 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7297 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7299 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7305 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7310 klass = mono_class_get_checked (image, type_token, error);
7312 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7313 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7318 * mono_class_get_checked:
7319 * \param image the image where the class resides
7320 * \param type_token the token for the class
7321 * \param error error object to return any error
7323 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7326 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7328 MonoClass *klass = NULL;
7332 if (image_is_dynamic (image)) {
7333 int table = mono_metadata_token_table (type_token);
7335 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7336 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7339 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7343 switch (type_token & 0xff000000){
7344 case MONO_TOKEN_TYPE_DEF:
7345 klass = mono_class_create_from_typedef (image, type_token, error);
7347 case MONO_TOKEN_TYPE_REF:
7348 klass = mono_class_from_typeref_checked (image, type_token, error);
7350 case MONO_TOKEN_TYPE_SPEC:
7351 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7354 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7358 /* Generic case, should be avoided for when a better error is possible. */
7359 if (!klass && mono_error_ok (error)) {
7360 char *name = mono_class_name_from_token (image, type_token);
7361 char *assembly = mono_assembly_name_from_token (image, type_token);
7362 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7370 * mono_type_get_checked:
7371 * \param image the image where the type resides
7372 * \param type_token the token for the type
7373 * \param context the generic context used to evaluate generic instantiations in
7374 * \param error Error handling context
7376 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7378 * \returns The MonoType that represents \p type_token in \p image
7381 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7383 MonoType *type = NULL;
7384 gboolean inflated = FALSE;
7388 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7389 if (image_is_dynamic (image)) {
7390 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7391 return_val_if_nok (error, NULL);
7392 return mono_class_get_type (klass);
7395 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7396 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7403 return mono_class_get_type (klass);
7406 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7413 MonoType *tmp = type;
7414 type = mono_class_get_type (mono_class_from_mono_type (type));
7415 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7416 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7417 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7419 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7421 if (type->type != tmp->type)
7424 mono_metadata_free_type (tmp);
7431 * \param image image where the class token will be looked up.
7432 * \param type_token a type token from the image
7433 * \returns the \c MonoClass with the given \p type_token on the \p image
7436 mono_class_get (MonoImage *image, guint32 type_token)
7438 return mono_class_get_full (image, type_token, NULL);
7442 * mono_image_init_name_cache:
7444 * Initializes the class name cache stored in image->name_cache.
7446 * LOCKING: Acquires the corresponding image lock.
7449 mono_image_init_name_cache (MonoImage *image)
7451 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7452 guint32 cols [MONO_TYPEDEF_SIZE];
7455 guint32 i, visib, nspace_index;
7456 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7458 if (image->name_cache)
7461 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7463 if (image_is_dynamic (image)) {
7464 mono_image_lock (image);
7465 if (image->name_cache) {
7466 /* Somebody initialized it before us */
7467 g_hash_table_destroy (the_name_cache);
7469 mono_atomic_store_release (&image->name_cache, the_name_cache);
7471 mono_image_unlock (image);
7475 /* Temporary hash table to avoid lookups in the nspace_table */
7476 name_cache2 = g_hash_table_new (NULL, NULL);
7478 for (i = 1; i <= t->rows; ++i) {
7479 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7480 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7482 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7483 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7485 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7487 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7488 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7490 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7491 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7492 if (!nspace_table) {
7493 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7494 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7495 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7498 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7501 /* Load type names from EXPORTEDTYPES table */
7503 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7504 guint32 cols [MONO_EXP_TYPE_SIZE];
7507 for (i = 0; i < t->rows; ++i) {
7508 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7510 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7511 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7515 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7516 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7518 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7519 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7520 if (!nspace_table) {
7521 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7522 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7523 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7526 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7530 g_hash_table_destroy (name_cache2);
7532 mono_image_lock (image);
7533 if (image->name_cache) {
7534 /* Somebody initialized it before us */
7535 g_hash_table_destroy (the_name_cache);
7537 mono_atomic_store_release (&image->name_cache, the_name_cache);
7539 mono_image_unlock (image);
7542 /*FIXME Only dynamic assemblies should allow this operation.*/
7544 * mono_image_add_to_name_cache:
7547 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7548 const char *name, guint32 index)
7550 GHashTable *nspace_table;
7551 GHashTable *name_cache;
7554 mono_image_init_name_cache (image);
7555 mono_image_lock (image);
7557 name_cache = image->name_cache;
7558 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7559 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7560 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7563 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7564 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7566 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7568 mono_image_unlock (image);
7577 find_nocase (gpointer key, gpointer value, gpointer user_data)
7579 char *name = (char*)key;
7580 FindUserData *data = (FindUserData*)user_data;
7582 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7583 data->value = value;
7587 * mono_class_from_name_case:
7588 * \param image The MonoImage where the type is looked up in
7589 * \param name_space the type namespace
7590 * \param name the type short name.
7591 * \deprecated use the mono_class_from_name_case_checked variant instead.
7593 * Obtains a \c MonoClass with a given namespace and a given name which
7594 * is located in the given \c MonoImage. The namespace and name
7595 * lookups are case insensitive.
7598 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7601 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7602 mono_error_cleanup (&error);
7608 * mono_class_from_name_case_checked:
7609 * \param image The MonoImage where the type is looked up in
7610 * \param name_space the type namespace
7611 * \param name the type short name.
7614 * Obtains a MonoClass with a given namespace and a given name which
7615 * is located in the given MonoImage. The namespace and name
7616 * lookups are case insensitive.
7618 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7619 * was not found. The \p error object will contain information about the problem
7623 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7625 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7626 guint32 cols [MONO_TYPEDEF_SIZE];
7633 if (image_is_dynamic (image)) {
7635 FindUserData user_data;
7637 mono_image_init_name_cache (image);
7638 mono_image_lock (image);
7640 user_data.key = name_space;
7641 user_data.value = NULL;
7642 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7644 if (user_data.value) {
7645 GHashTable *nspace_table = (GHashTable*)user_data.value;
7647 user_data.key = name;
7648 user_data.value = NULL;
7650 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7652 if (user_data.value)
7653 token = GPOINTER_TO_UINT (user_data.value);
7656 mono_image_unlock (image);
7659 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7665 /* add a cache if needed */
7666 for (i = 1; i <= t->rows; ++i) {
7667 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7668 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7670 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7671 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7673 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7675 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7676 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7677 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7678 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7684 return_nested_in (MonoClass *klass, char *nested)
7687 char *s = strchr (nested, '/');
7688 gpointer iter = NULL;
7695 while ((found = mono_class_get_nested_types (klass, &iter))) {
7696 if (strcmp (found->name, nested) == 0) {
7698 return return_nested_in (found, s);
7706 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7708 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7709 MonoImage *file_image;
7716 * The EXPORTEDTYPES table only contains public types, so have to search the
7718 * Note: image->modules contains the contents of the MODULEREF table, while
7719 * the real module list is in the FILE table.
7721 for (i = 0; i < file_table->rows; i++) {
7722 guint32 cols [MONO_FILE_SIZE];
7723 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7724 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7727 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7729 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7730 if (klass || !is_ok (error))
7739 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7741 GHashTable *nspace_table;
7742 MonoImage *loaded_image;
7751 // Checking visited images avoids stack overflows when cyclic references exist.
7752 if (g_hash_table_lookup (visited_images, image))
7755 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7757 if ((nested = strchr (name, '/'))) {
7758 int pos = nested - name;
7759 int len = strlen (name);
7762 memcpy (buf, name, len + 1);
7764 nested = buf + pos + 1;
7768 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7769 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7770 gboolean res = get_class_from_name (image, name_space, name, &klass);
7773 klass = search_modules (image, name_space, name, error);
7778 return klass ? return_nested_in (klass, nested) : NULL;
7784 mono_image_init_name_cache (image);
7785 mono_image_lock (image);
7787 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7790 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7792 mono_image_unlock (image);
7794 if (!token && image_is_dynamic (image) && image->modules) {
7795 /* Search modules as well */
7796 for (i = 0; i < image->module_count; ++i) {
7797 MonoImage *module = image->modules [i];
7799 klass = mono_class_from_name_checked (module, name_space, name, error);
7800 if (klass || !is_ok (error))
7806 klass = search_modules (image, name_space, name, error);
7807 if (klass || !is_ok (error))
7812 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7813 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7814 guint32 cols [MONO_EXP_TYPE_SIZE];
7817 idx = mono_metadata_token_index (token);
7819 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7821 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7822 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7823 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7826 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7828 return klass ? return_nested_in (klass, nested) : NULL;
7830 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7831 guint32 assembly_idx;
7833 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7835 mono_assembly_load_reference (image, assembly_idx - 1);
7836 g_assert (image->references [assembly_idx - 1]);
7837 if (image->references [assembly_idx - 1] == (gpointer)-1)
7839 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7841 return klass ? return_nested_in (klass, nested) : NULL;
7844 g_assert_not_reached ();
7848 token = MONO_TOKEN_TYPE_DEF | token;
7850 klass = mono_class_get_checked (image, token, error);
7852 return return_nested_in (klass, nested);
7857 * mono_class_from_name_checked:
7858 * \param image The MonoImage where the type is looked up in
7859 * \param name_space the type namespace
7860 * \param name the type short name.
7862 * Obtains a MonoClass with a given namespace and a given name which
7863 * is located in the given MonoImage.
7865 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7866 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7869 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7872 GHashTable *visited_images;
7874 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7876 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7878 g_hash_table_destroy (visited_images);
7884 * mono_class_from_name:
7885 * \param image The \c MonoImage where the type is looked up in
7886 * \param name_space the type namespace
7887 * \param name the type short name.
7889 * Obtains a \c MonoClass with a given namespace and a given name which
7890 * is located in the given \c MonoImage.
7892 * To reference nested classes, use the "/" character as a separator.
7893 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7894 * inside \c Foo, like this: "class Foo { class Bar {} }".
7897 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7902 klass = mono_class_from_name_checked (image, name_space, name, &error);
7903 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7909 * mono_class_load_from_name:
7910 * \param image The MonoImage where the type is looked up in
7911 * \param name_space the type namespace
7912 * \param name the type short name.
7914 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7915 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7916 * If they are missing. Thing of System.Object or System.String.
7919 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7924 klass = mono_class_from_name_checked (image, name_space, name, &error);
7926 g_error ("Runtime critical type %s.%s not found", name_space, name);
7927 if (!mono_error_ok (&error))
7928 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7933 * mono_class_try_load_from_name:
7934 * \param image The MonoImage where the type is looked up in
7935 * \param name_space the type namespace
7936 * \param name the type short name.
7938 * This function tries to load a type, returning the class was found or NULL otherwise.
7939 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7941 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7942 * a type that we would otherwise assume to be available but was not due some error.
7946 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7951 klass = mono_class_from_name_checked (image, name_space, name, &error);
7952 if (!mono_error_ok (&error))
7953 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7959 * mono_class_is_subclass_of:
7960 * \param klass class to probe if it is a subclass of another one
7961 * \param klassc the class we suspect is the base class
7962 * \param check_interfaces whether we should perform interface checks
7964 * This method determines whether \p klass is a subclass of \p klassc.
7966 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7967 * this method return TRUE if the \p klass implements the interface or
7968 * if \p klass is an interface, if one of its base classes is \p klass.
7970 * If \p check_interfaces is false, then if \p klass is not an interface,
7971 * it returns TRUE if the \p klass is a subclass of \p klassc.
7973 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7978 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7979 gboolean check_interfaces)
7981 /* FIXME test for interfaces with variant generic arguments */
7982 mono_class_init (klass);
7983 mono_class_init (klassc);
7985 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7986 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7988 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7991 for (i = 0; i < klass->interface_count; i ++) {
7992 MonoClass *ic = klass->interfaces [i];
7997 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8002 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8005 if (klassc == mono_defaults.object_class)
8012 mono_type_is_generic_argument (MonoType *type)
8014 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8018 mono_class_has_variant_generic_params (MonoClass *klass)
8021 MonoGenericContainer *container;
8023 if (!mono_class_is_ginst (klass))
8026 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8028 for (i = 0; i < container->type_argc; ++i)
8029 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8036 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8038 if (target == candidate)
8041 if (check_for_reference_conv &&
8042 mono_type_is_generic_argument (&target->byval_arg) &&
8043 mono_type_is_generic_argument (&candidate->byval_arg)) {
8044 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8045 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8047 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8050 if (!mono_class_is_assignable_from (target, candidate))
8056 * @container the generic container from the GTD
8057 * @klass: the class to be assigned to
8058 * @oklass: the source class
8060 * Both @klass and @oklass must be instances of the same generic interface.
8062 * Returns: TRUE if @klass can be assigned to a @klass variable
8065 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8068 MonoType **klass_argv, **oklass_argv;
8069 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8070 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8072 if (klass == oklass)
8075 /*Viable candidates are instances of the same generic interface*/
8076 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8079 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8080 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8082 for (j = 0; j < container->type_argc; ++j) {
8083 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8084 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8086 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8090 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8091 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8093 if (param1_class != param2_class) {
8094 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8095 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8097 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8098 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8108 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8110 MonoGenericParam *gparam, *ogparam;
8111 MonoGenericParamInfo *tinfo, *cinfo;
8112 MonoClass **candidate_class;
8113 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8116 if (target == candidate)
8118 if (target->byval_arg.type != candidate->byval_arg.type)
8121 gparam = target->byval_arg.data.generic_param;
8122 ogparam = candidate->byval_arg.data.generic_param;
8123 tinfo = mono_generic_param_info (gparam);
8124 cinfo = mono_generic_param_info (ogparam);
8126 class_constraint_satisfied = FALSE;
8127 valuetype_constraint_satisfied = FALSE;
8129 /*candidate must have a super set of target's special constraints*/
8130 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8131 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8133 if (cinfo->constraints) {
8134 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8135 MonoClass *cc = *candidate_class;
8137 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8138 class_constraint_satisfied = TRUE;
8139 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8140 valuetype_constraint_satisfied = TRUE;
8143 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8144 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8146 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8148 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8150 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8151 valuetype_constraint_satisfied)) {
8156 /*candidate type constraints must be a superset of target's*/
8157 if (tinfo->constraints) {
8158 MonoClass **target_class;
8159 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8160 MonoClass *tc = *target_class;
8163 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8164 * check it's constraints since it satisfy the constraint by itself.
8166 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8169 if (!cinfo->constraints)
8172 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8173 MonoClass *cc = *candidate_class;
8175 if (mono_class_is_assignable_from (tc, cc))
8179 * This happens when we have the following:
8181 * Bar<K> where K : IFace
8182 * Foo<T, U> where T : U where U : IFace
8184 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8187 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8188 if (mono_gparam_is_assignable_from (target, cc))
8192 if (!*candidate_class)
8197 /*candidate itself must have a constraint that satisfy target*/
8198 if (cinfo->constraints) {
8199 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8200 MonoClass *cc = *candidate_class;
8201 if (mono_class_is_assignable_from (target, cc))
8209 * mono_class_is_assignable_from:
8210 * \param klass the class to be assigned to
8211 * \param oklass the source class
8213 * \returns TRUE if an instance of class \p oklass can be assigned to an
8214 * instance of class \p klass
8217 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8220 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8222 mono_class_init (klass);
8224 if (!oklass->inited)
8225 mono_class_init (oklass);
8227 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8230 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8231 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8233 return mono_gparam_is_assignable_from (klass, oklass);
8236 /* This can happen if oklass is a tyvar that has a constraint which is another tyvar which in turn
8237 * has a constraint which is a class type:
8240 * class G<T1, T2> where T1 : T2 where T2 : Foo { }
8242 * In this case, Foo is assignable from T1.
8244 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8245 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8246 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8250 for (i = 0; constraints [i]; ++i) {
8251 if (mono_class_is_assignable_from (klass, constraints [i]))
8256 return mono_class_has_parent (oklass, klass);
8259 if (MONO_CLASS_IS_INTERFACE (klass)) {
8261 /* interface_offsets might not be set for dynamic classes */
8262 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8264 * oklass might be a generic type parameter but they have
8265 * interface_offsets set.
8267 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8268 if (!is_ok (&error)) {
8269 mono_error_cleanup (&error);
8274 if (!oklass->interface_bitmap)
8275 /* Happens with generic instances of not-yet created dynamic types */
8277 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8280 if (klass->is_array_special_interface && oklass->rank == 1) {
8281 //XXX we could offset this by having the cast target computed at JIT time
8282 //XXX we could go even further and emit a wrapper that would do the extra type check
8283 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8284 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8286 // 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
8287 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8288 if (iface_klass->valuetype)
8289 iface_klass = iface_klass->cast_class;
8291 //array covariant casts only operates on scalar to scalar
8292 //This is so int[] can't be casted to IComparable<int>[]
8293 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8297 if (mono_class_has_variant_generic_params (klass)) {
8299 mono_class_setup_interfaces (oklass, &error);
8300 if (!mono_error_ok (&error)) {
8301 mono_error_cleanup (&error);
8305 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8306 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8307 MonoClass *iface = oklass->interfaces_packed [i];
8309 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8314 } else if (klass->delegate) {
8315 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8317 }else if (klass->rank) {
8318 MonoClass *eclass, *eoclass;
8320 if (oklass->rank != klass->rank)
8323 /* vectors vs. one dimensional arrays */
8324 if (oklass->byval_arg.type != klass->byval_arg.type)
8327 eclass = klass->cast_class;
8328 eoclass = oklass->cast_class;
8331 * a is b does not imply a[] is b[] when a is a valuetype, and
8332 * b is a reference type.
8335 if (eoclass->valuetype) {
8336 if ((eclass == mono_defaults.enum_class) ||
8337 (eclass == mono_defaults.enum_class->parent) ||
8338 (eclass == mono_defaults.object_class))
8342 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8343 } else if (mono_class_is_nullable (klass)) {
8344 if (mono_class_is_nullable (oklass))
8345 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8347 return mono_class_is_assignable_from (klass->cast_class, oklass);
8348 } else if (klass == mono_defaults.object_class)
8351 return mono_class_has_parent (oklass, klass);
8354 /*Check if @oklass is variant compatible with @klass.*/
8356 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8359 MonoType **klass_argv, **oklass_argv;
8360 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8361 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8363 /*Viable candidates are instances of the same generic interface*/
8364 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8367 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8368 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8370 for (j = 0; j < container->type_argc; ++j) {
8371 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8372 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8374 if (param1_class->valuetype != param2_class->valuetype)
8378 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8379 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8381 if (param1_class != param2_class) {
8382 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8383 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8385 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8386 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8394 /*Check if @candidate implements the interface @target*/
8396 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8400 gboolean is_variant = mono_class_has_variant_generic_params (target);
8402 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8403 if (mono_class_is_variant_compatible_slow (target, candidate))
8408 if (candidate == target)
8411 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8412 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8413 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8415 if (tb && tb->interfaces) {
8416 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8417 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8418 MonoClass *iface_class;
8420 /* we can't realize the type here since it can do pretty much anything. */
8423 iface_class = mono_class_from_mono_type (iface->type);
8424 if (iface_class == target)
8426 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8428 if (mono_class_implement_interface_slow (target, iface_class))
8433 /*setup_interfaces don't mono_class_init anything*/
8434 /*FIXME this doesn't handle primitive type arrays.
8435 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8436 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8438 mono_class_setup_interfaces (candidate, &error);
8439 if (!mono_error_ok (&error)) {
8440 mono_error_cleanup (&error);
8444 for (i = 0; i < candidate->interface_count; ++i) {
8445 if (candidate->interfaces [i] == target)
8448 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8451 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8455 candidate = candidate->parent;
8456 } while (candidate);
8462 * Check if @oklass can be assigned to @klass.
8463 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8466 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8468 if (candidate == target)
8470 if (target == mono_defaults.object_class)
8473 if (mono_class_has_parent (candidate, target))
8476 /*If target is not an interface there is no need to check them.*/
8477 if (MONO_CLASS_IS_INTERFACE (target))
8478 return mono_class_implement_interface_slow (target, candidate);
8480 if (target->delegate && mono_class_has_variant_generic_params (target))
8481 return mono_class_is_variant_compatible (target, candidate, FALSE);
8484 MonoClass *eclass, *eoclass;
8486 if (target->rank != candidate->rank)
8489 /* vectors vs. one dimensional arrays */
8490 if (target->byval_arg.type != candidate->byval_arg.type)
8493 eclass = target->cast_class;
8494 eoclass = candidate->cast_class;
8497 * a is b does not imply a[] is b[] when a is a valuetype, and
8498 * b is a reference type.
8501 if (eoclass->valuetype) {
8502 if ((eclass == mono_defaults.enum_class) ||
8503 (eclass == mono_defaults.enum_class->parent) ||
8504 (eclass == mono_defaults.object_class))
8508 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8510 /*FIXME properly handle nullables */
8511 /*FIXME properly handle (M)VAR */
8516 * mono_class_get_cctor:
8517 * \param klass A MonoClass pointer
8519 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8522 mono_class_get_cctor (MonoClass *klass)
8524 MonoCachedClassInfo cached_info;
8526 if (image_is_dynamic (klass->image)) {
8528 * has_cctor is not set for these classes because mono_class_init () is
8531 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8534 mono_class_init (klass);
8536 if (!klass->has_cctor)
8539 if (mono_class_is_ginst (klass) && !klass->methods)
8540 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8542 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8544 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8545 if (!mono_error_ok (&error))
8546 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8550 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8554 * mono_class_get_finalizer:
8555 * \param klass: The MonoClass pointer
8557 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8560 mono_class_get_finalizer (MonoClass *klass)
8562 MonoCachedClassInfo cached_info;
8565 mono_class_init (klass);
8566 if (!mono_class_has_finalizer (klass))
8569 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8571 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8572 if (!mono_error_ok (&error))
8573 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8576 mono_class_setup_vtable (klass);
8577 return klass->vtable [finalize_slot];
8582 * mono_class_needs_cctor_run:
8583 * \param klass the MonoClass pointer
8584 * \param caller a MonoMethod describing the caller
8586 * Determines whenever the class has a static constructor and whenever it
8587 * needs to be called when executing CALLER.
8590 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8594 method = mono_class_get_cctor (klass);
8596 return (method == caller) ? FALSE : TRUE;
8602 * mono_class_array_element_size:
8605 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8608 mono_class_array_element_size (MonoClass *klass)
8610 MonoType *type = &klass->byval_arg;
8613 switch (type->type) {
8616 case MONO_TYPE_BOOLEAN:
8620 case MONO_TYPE_CHAR:
8629 case MONO_TYPE_CLASS:
8630 case MONO_TYPE_STRING:
8631 case MONO_TYPE_OBJECT:
8632 case MONO_TYPE_SZARRAY:
8633 case MONO_TYPE_ARRAY:
8634 return sizeof (gpointer);
8639 case MONO_TYPE_VALUETYPE:
8640 if (type->data.klass->enumtype) {
8641 type = mono_class_enum_basetype (type->data.klass);
8642 klass = klass->element_class;
8645 return mono_class_instance_size (klass) - sizeof (MonoObject);
8646 case MONO_TYPE_GENERICINST:
8647 type = &type->data.generic_class->container_class->byval_arg;
8650 case MONO_TYPE_MVAR: {
8653 return mono_type_size (type, &align);
8655 case MONO_TYPE_VOID:
8659 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8665 * mono_array_element_size:
8666 * \param ac pointer to a \c MonoArrayClass
8668 * \returns The size of single array element.
8670 * LOCKING: Acquires the loader lock.
8673 mono_array_element_size (MonoClass *ac)
8675 g_assert (ac->rank);
8676 if (G_UNLIKELY (!ac->size_inited)) {
8677 mono_class_setup_fields (ac);
8679 return ac->sizes.element_size;
8686 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8687 MonoGenericContext *context)
8690 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8691 g_assert (mono_error_ok (&error));
8696 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8697 MonoGenericContext *context, MonoError *error)
8701 if (image_is_dynamic (image)) {
8702 MonoClass *tmp_handle_class;
8703 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8705 mono_error_assert_ok (error);
8706 g_assert (tmp_handle_class);
8708 *handle_class = tmp_handle_class;
8710 if (tmp_handle_class == mono_defaults.typehandle_class)
8711 return &((MonoClass*)obj)->byval_arg;
8716 switch (token & 0xff000000) {
8717 case MONO_TOKEN_TYPE_DEF:
8718 case MONO_TOKEN_TYPE_REF:
8719 case MONO_TOKEN_TYPE_SPEC: {
8722 *handle_class = mono_defaults.typehandle_class;
8723 type = mono_type_get_checked (image, token, context, error);
8727 mono_class_init (mono_class_from_mono_type (type));
8728 /* We return a MonoType* as handle */
8731 case MONO_TOKEN_FIELD_DEF: {
8733 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8735 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8739 *handle_class = mono_defaults.fieldhandle_class;
8740 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8744 mono_class_init (klass);
8745 return mono_class_get_field (klass, token);
8747 case MONO_TOKEN_METHOD_DEF:
8748 case MONO_TOKEN_METHOD_SPEC: {
8750 meth = mono_get_method_checked (image, token, NULL, context, error);
8752 *handle_class = mono_defaults.methodhandle_class;
8758 case MONO_TOKEN_MEMBER_REF: {
8759 guint32 cols [MONO_MEMBERREF_SIZE];
8761 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8762 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8763 mono_metadata_decode_blob_size (sig, &sig);
8764 if (*sig == 0x6) { /* it's a field */
8766 MonoClassField *field;
8767 field = mono_field_from_token_checked (image, token, &klass, context, error);
8769 *handle_class = mono_defaults.fieldhandle_class;
8773 meth = mono_get_method_checked (image, token, NULL, context, error);
8775 *handle_class = mono_defaults.methodhandle_class;
8780 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8786 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8788 MonoClass *handle_class;
8790 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8794 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8796 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8799 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8802 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8804 get_cached_class_info = func;
8808 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8810 if (!get_cached_class_info)
8813 return get_cached_class_info (klass, res);
8817 mono_install_get_class_from_name (MonoGetClassFromName func)
8819 get_class_from_name = func;
8823 * mono_class_get_image:
8825 * Use this method to get the \c MonoImage* where this class came from.
8827 * \returns The image where this class is defined.
8830 mono_class_get_image (MonoClass *klass)
8832 return klass->image;
8836 * mono_class_get_element_class:
8837 * \param klass the \c MonoClass to act on
8839 * Use this function to get the element class of an array.
8841 * \returns The element class of an array.
8844 mono_class_get_element_class (MonoClass *klass)
8846 return klass->element_class;
8850 * mono_class_is_valuetype:
8851 * \param klass the \c MonoClass to act on
8853 * Use this method to determine if the provided \c MonoClass* represents a value type,
8854 * or a reference type.
8856 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8859 mono_class_is_valuetype (MonoClass *klass)
8861 return klass->valuetype;
8865 * mono_class_is_enum:
8866 * \param klass the \c MonoClass to act on
8868 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8870 * \returns TRUE if the \c MonoClass represents an enumeration.
8873 mono_class_is_enum (MonoClass *klass)
8875 return klass->enumtype;
8879 * mono_class_enum_basetype:
8880 * \param klass the \c MonoClass to act on
8882 * Use this function to get the underlying type for an enumeration value.
8884 * \returns The underlying type representation for an enumeration.
8887 mono_class_enum_basetype (MonoClass *klass)
8889 if (klass->element_class == klass)
8890 /* SRE or broken types */
8893 return &klass->element_class->byval_arg;
8897 * mono_class_get_parent
8898 * \param klass the \c MonoClass to act on
8900 * \returns The parent class for this class.
8903 mono_class_get_parent (MonoClass *klass)
8905 return klass->parent;
8909 * mono_class_get_nesting_type:
8910 * \param klass the \c MonoClass to act on
8912 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8914 * If the return is NULL, this indicates that this class is not nested.
8916 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8919 mono_class_get_nesting_type (MonoClass *klass)
8921 return klass->nested_in;
8925 * mono_class_get_rank:
8926 * \param klass the MonoClass to act on
8928 * \returns The rank for the array (the number of dimensions).
8931 mono_class_get_rank (MonoClass *klass)
8937 * mono_class_get_name
8938 * \param klass the \c MonoClass to act on
8940 * \returns The name of the class.
8943 mono_class_get_name (MonoClass *klass)
8949 * mono_class_get_namespace:
8950 * \param klass the \c MonoClass to act on
8952 * \returns The namespace of the class.
8955 mono_class_get_namespace (MonoClass *klass)
8957 return klass->name_space;
8961 * mono_class_get_type:
8962 * \param klass the \c MonoClass to act on
8964 * This method returns the internal \c MonoType representation for the class.
8966 * \returns The \c MonoType from the class.
8969 mono_class_get_type (MonoClass *klass)
8971 return &klass->byval_arg;
8975 * mono_class_get_type_token:
8976 * \param klass the \c MonoClass to act on
8978 * This method returns type token for the class.
8980 * \returns The type token for the class.
8983 mono_class_get_type_token (MonoClass *klass)
8985 return klass->type_token;
8989 * mono_class_get_byref_type:
8990 * \param klass the \c MonoClass to act on
8995 mono_class_get_byref_type (MonoClass *klass)
8997 return &klass->this_arg;
9001 * mono_class_num_fields:
9002 * \param klass the \c MonoClass to act on
9004 * \returns The number of static and instance fields in the class.
9007 mono_class_num_fields (MonoClass *klass)
9009 return mono_class_get_field_count (klass);
9013 * mono_class_num_methods:
9014 * \param klass the \c MonoClass to act on
9016 * \returns The number of methods in the class.
9019 mono_class_num_methods (MonoClass *klass)
9021 return mono_class_get_method_count (klass);
9025 * mono_class_num_properties
9026 * \param klass the \c MonoClass to act on
9028 * \returns The number of properties in the class.
9031 mono_class_num_properties (MonoClass *klass)
9033 mono_class_setup_properties (klass);
9035 return mono_class_get_property_info (klass)->count;
9039 * mono_class_num_events:
9040 * \param klass the \c MonoClass to act on
9042 * \returns The number of events in the class.
9045 mono_class_num_events (MonoClass *klass)
9047 mono_class_setup_events (klass);
9049 return mono_class_get_event_info (klass)->count;
9053 * mono_class_get_fields:
9054 * \param klass the \c MonoClass to act on
9056 * This routine is an iterator routine for retrieving the fields in a class.
9058 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9059 * iterate over all of the elements. When no more values are
9060 * available, the return value is NULL.
9062 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9065 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9067 MonoClassField* field;
9071 mono_class_setup_fields (klass);
9072 if (mono_class_has_failure (klass))
9074 /* start from the first */
9075 if (mono_class_get_field_count (klass)) {
9076 *iter = &klass->fields [0];
9077 return &klass->fields [0];
9083 field = (MonoClassField *)*iter;
9085 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9093 * mono_class_get_methods:
9094 * \param klass the \c MonoClass to act on
9096 * This routine is an iterator routine for retrieving the fields in a class.
9098 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9099 * iterate over all of the elements. When no more values are
9100 * available, the return value is NULL.
9102 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9105 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9107 MonoMethod** method;
9111 mono_class_setup_methods (klass);
9114 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9115 * FIXME we should better report this error to the caller
9117 if (!klass->methods)
9119 /* start from the first */
9120 if (mono_class_get_method_count (klass)) {
9121 *iter = &klass->methods [0];
9122 return klass->methods [0];
9128 method = (MonoMethod **)*iter;
9130 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9138 * mono_class_get_virtual_methods:
9140 * Iterate over the virtual methods of KLASS.
9142 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9145 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9147 gboolean static_iter = FALSE;
9153 * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
9154 * and the upper bits contain an index. Otherwise, the iterator is a pointer into
9157 if ((gsize)(*iter) & 1)
9159 /* Use the static metadata only if klass->methods is not yet initialized */
9160 if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
9164 MonoMethod** methodptr;
9167 mono_class_setup_methods (klass);
9169 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9170 * FIXME we should better report this error to the caller
9172 if (!klass->methods)
9174 /* start from the first */
9175 methodptr = &klass->methods [0];
9177 methodptr = (MonoMethod **)*iter;
9181 g_assert ((guint64)(*iter) > 0x100);
9182 int mcount = mono_class_get_method_count (klass);
9183 while (methodptr < &klass->methods [mcount]) {
9184 if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9188 if (methodptr < &klass->methods [mcount]) {
9195 /* Search directly in metadata to avoid calling setup_methods () */
9196 MonoMethod *res = NULL;
9202 start_index = GPOINTER_TO_UINT (*iter) >> 1;
9205 int first_idx = mono_class_get_first_method_idx (klass);
9206 int mcount = mono_class_get_method_count (klass);
9207 for (i = start_index; i < mcount; ++i) {
9210 /* first_idx points into the methodptr table */
9211 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9213 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9219 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9220 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9222 /* Add 1 here so the if (*iter) check fails */
9223 *iter = GUINT_TO_POINTER (((i + 1) << 1) | 1);
9232 * mono_class_get_properties:
9233 * \param klass the \c MonoClass to act on
9235 * This routine is an iterator routine for retrieving the properties in a class.
9237 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9238 * iterate over all of the elements. When no more values are
9239 * available, the return value is NULL.
9241 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9244 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9246 MonoProperty* property;
9250 mono_class_setup_properties (klass);
9251 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9252 /* start from the first */
9254 *iter = &info->properties [0];
9255 return (MonoProperty *)*iter;
9261 property = (MonoProperty *)*iter;
9263 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9264 if (property < &info->properties [info->count]) {
9266 return (MonoProperty *)*iter;
9272 * mono_class_get_events:
9273 * \param klass the \c MonoClass to act on
9275 * This routine is an iterator routine for retrieving the properties in a class.
9277 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9278 * iterate over all of the elements. When no more values are
9279 * available, the return value is NULL.
9281 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9284 mono_class_get_events (MonoClass* klass, gpointer *iter)
9290 mono_class_setup_events (klass);
9291 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9292 /* start from the first */
9294 *iter = &info->events [0];
9295 return (MonoEvent *)*iter;
9301 event = (MonoEvent *)*iter;
9303 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9304 if (event < &info->events [info->count]) {
9306 return (MonoEvent *)*iter;
9312 * mono_class_get_interfaces
9313 * \param klass the \c MonoClass to act on
9315 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9317 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9318 * iterate over all of the elements. When no more values are
9319 * available, the return value is NULL.
9321 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9324 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9332 mono_class_init (klass);
9333 if (!klass->interfaces_inited) {
9334 mono_class_setup_interfaces (klass, &error);
9335 if (!mono_error_ok (&error)) {
9336 mono_error_cleanup (&error);
9340 /* start from the first */
9341 if (klass->interface_count) {
9342 *iter = &klass->interfaces [0];
9343 return klass->interfaces [0];
9349 iface = (MonoClass **)*iter;
9351 if (iface < &klass->interfaces [klass->interface_count]) {
9359 setup_nested_types (MonoClass *klass)
9362 GList *classes, *nested_classes, *l;
9365 if (klass->nested_classes_inited)
9368 if (!klass->type_token) {
9369 mono_loader_lock ();
9370 klass->nested_classes_inited = TRUE;
9371 mono_loader_unlock ();
9375 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9379 guint32 cols [MONO_NESTED_CLASS_SIZE];
9380 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9381 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9382 if (!mono_error_ok (&error)) {
9383 /*FIXME don't swallow the error message*/
9384 mono_error_cleanup (&error);
9386 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9390 classes = g_list_prepend (classes, nclass);
9392 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9395 nested_classes = NULL;
9396 for (l = classes; l; l = l->next)
9397 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9398 g_list_free (classes);
9400 mono_loader_lock ();
9401 if (!klass->nested_classes_inited) {
9402 mono_class_set_nested_classes_property (klass, nested_classes);
9403 mono_memory_barrier ();
9404 klass->nested_classes_inited = TRUE;
9406 mono_loader_unlock ();
9410 * mono_class_get_nested_types
9411 * \param klass the \c MonoClass to act on
9413 * This routine is an iterator routine for retrieving the nested types of a class.
9414 * This works only if \p klass is non-generic, or a generic type definition.
9416 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9417 * iterate over all of the elements. When no more values are
9418 * available, the return value is NULL.
9420 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9423 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9429 if (!klass->nested_classes_inited)
9430 setup_nested_types (klass);
9433 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9434 /* start from the first */
9435 if (nested_classes) {
9436 *iter = nested_classes;
9437 return (MonoClass *)nested_classes->data;
9439 /* no nested types */
9443 item = (GList *)*iter;
9447 return (MonoClass *)item->data;
9454 * mono_class_is_delegate
9455 * \param klass the \c MonoClass to act on
9457 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9460 mono_class_is_delegate (MonoClass *klass)
9462 return klass->delegate;
9466 * mono_class_implements_interface
9467 * \param klass The MonoClass to act on
9468 * \param interface The interface to check if \p klass implements.
9470 * \returns TRUE if \p klass implements \p interface.
9473 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9475 return mono_class_is_assignable_from (iface, klass);
9479 * mono_field_get_name:
9480 * \param field the \c MonoClassField to act on
9482 * \returns The name of the field.
9485 mono_field_get_name (MonoClassField *field)
9491 * mono_field_get_type:
9492 * \param field the \c MonoClassField to act on
9493 * \returns \c MonoType of the field.
9496 mono_field_get_type (MonoClassField *field)
9499 MonoType *type = mono_field_get_type_checked (field, &error);
9500 if (!mono_error_ok (&error)) {
9501 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9502 mono_error_cleanup (&error);
9509 * mono_field_get_type_checked:
9510 * \param field the \c MonoClassField to act on
9511 * \param error used to return any error found while retrieving \p field type
9513 * \returns \c MonoType of the field.
9516 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9520 mono_field_resolve_type (field, error);
9525 * mono_field_get_parent:
9526 * \param field the \c MonoClassField to act on
9528 * \returns \c MonoClass where the field was defined.
9531 mono_field_get_parent (MonoClassField *field)
9533 return field->parent;
9537 * mono_field_get_flags;
9538 * \param field the \c MonoClassField to act on
9540 * The metadata flags for a field are encoded using the
9541 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9543 * \returns The flags for the field.
9546 mono_field_get_flags (MonoClassField *field)
9549 return mono_field_resolve_flags (field);
9550 return field->type->attrs;
9554 * mono_field_get_offset:
9555 * \param field the \c MonoClassField to act on
9557 * \returns The field offset.
9560 mono_field_get_offset (MonoClassField *field)
9562 return field->offset;
9566 mono_field_get_rva (MonoClassField *field)
9570 MonoClass *klass = field->parent;
9571 MonoFieldDefaultValue *def_values;
9573 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9575 def_values = mono_class_get_field_def_values (klass);
9577 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9579 mono_class_set_field_def_values (klass, def_values);
9582 field_index = mono_field_get_index (field);
9584 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9585 int first_field_idx = mono_class_get_first_field_idx (klass);
9586 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9588 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9589 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9592 return def_values [field_index].data;
9596 * mono_field_get_data:
9597 * \param field the \c MonoClassField to act on
9599 * \returns A pointer to the metadata constant value or to the field
9600 * data if it has an RVA flag.
9603 mono_field_get_data (MonoClassField *field)
9605 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9606 MonoTypeEnum def_type;
9608 return mono_class_get_field_default_value (field, &def_type);
9609 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9610 return mono_field_get_rva (field);
9617 * mono_property_get_name:
9618 * \param prop the \c MonoProperty to act on
9619 * \returns The name of the property
9622 mono_property_get_name (MonoProperty *prop)
9628 * mono_property_get_set_method
9629 * \param prop the \c MonoProperty to act on.
9630 * \returns The setter method of the property, a \c MonoMethod.
9633 mono_property_get_set_method (MonoProperty *prop)
9639 * mono_property_get_get_method
9640 * \param prop the MonoProperty to act on.
9641 * \returns The getter method of the property (A \c MonoMethod)
9644 mono_property_get_get_method (MonoProperty *prop)
9650 * mono_property_get_parent:
9651 * \param prop the \c MonoProperty to act on.
9652 * \returns The \c MonoClass where the property was defined.
9655 mono_property_get_parent (MonoProperty *prop)
9657 return prop->parent;
9661 * mono_property_get_flags:
9662 * \param prop the \c MonoProperty to act on.
9664 * The metadata flags for a property are encoded using the
9665 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9667 * \returns The flags for the property.
9670 mono_property_get_flags (MonoProperty *prop)
9676 * mono_event_get_name:
9677 * \param event the MonoEvent to act on
9678 * \returns The name of the event.
9681 mono_event_get_name (MonoEvent *event)
9687 * mono_event_get_add_method:
9688 * \param event The \c MonoEvent to act on.
9689 * \returns The \c add method for the event, a \c MonoMethod.
9692 mono_event_get_add_method (MonoEvent *event)
9698 * mono_event_get_remove_method:
9699 * \param event The \c MonoEvent to act on.
9700 * \returns The \c remove method for the event, a \c MonoMethod.
9703 mono_event_get_remove_method (MonoEvent *event)
9705 return event->remove;
9709 * mono_event_get_raise_method:
9710 * \param event The \c MonoEvent to act on.
9711 * \returns The \c raise method for the event, a \c MonoMethod.
9714 mono_event_get_raise_method (MonoEvent *event)
9716 return event->raise;
9720 * mono_event_get_parent:
9721 * \param event the MonoEvent to act on.
9722 * \returns The \c MonoClass where the event is defined.
9725 mono_event_get_parent (MonoEvent *event)
9727 return event->parent;
9731 * mono_event_get_flags
9732 * \param event the \c MonoEvent to act on.
9734 * The metadata flags for an event are encoded using the
9735 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9737 * \returns The flags for the event.
9740 mono_event_get_flags (MonoEvent *event)
9742 return event->attrs;
9746 * mono_class_get_method_from_name:
9747 * \param klass where to look for the method
9748 * \param name name of the method
9749 * \param param_count number of parameters. -1 for any number.
9751 * Obtains a \c MonoMethod with a given name and number of parameters.
9752 * It only works if there are no multiple signatures for any given method name.
9755 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9757 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9761 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9763 MonoMethod *res = NULL;
9766 /* Search directly in the metadata to avoid calling setup_methods () */
9767 int first_idx = mono_class_get_first_method_idx (klass);
9768 int mcount = mono_class_get_method_count (klass);
9769 for (i = 0; i < mcount; ++i) {
9771 guint32 cols [MONO_METHOD_SIZE];
9773 MonoMethodSignature *sig;
9775 /* first_idx points into the methodptr table */
9776 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9778 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9779 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9781 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9784 if (param_count == -1) {
9788 sig = mono_method_signature_checked (method, &error);
9790 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9793 if (sig->param_count == param_count) {
9804 * mono_class_get_method_from_name_flags:
9805 * \param klass where to look for the method
9806 * \param name_space name of the method
9807 * \param param_count number of parameters. -1 for any number.
9808 * \param flags flags which must be set in the method
9810 * Obtains a \c MonoMethod with a given name and number of parameters.
9811 * It only works if there are no multiple signatures for any given method name.
9814 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9816 MonoMethod *res = NULL;
9819 mono_class_init (klass);
9821 if (mono_class_is_ginst (klass) && !klass->methods) {
9822 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9825 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9826 if (!mono_error_ok (&error))
9827 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9832 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9833 mono_class_setup_methods (klass);
9835 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9836 See mono/tests/array_load_exception.il
9837 FIXME we should better report this error to the caller
9839 if (!klass->methods)
9841 int mcount = mono_class_get_method_count (klass);
9842 for (i = 0; i < mcount; ++i) {
9843 MonoMethod *method = klass->methods [i];
9845 if (method->name[0] == name [0] &&
9846 !strcmp (name, method->name) &&
9847 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9848 ((method->flags & flags) == flags)) {
9855 res = find_method_in_metadata (klass, name, param_count, flags);
9862 * mono_class_set_failure:
9863 * \param klass class in which the failure was detected
9864 * \param ex_type the kind of exception/error to be thrown (later)
9865 * \param ex_data exception data (specific to each type of exception/error)
9867 * Keep a detected failure informations in the class for later processing.
9868 * Note that only the first failure is kept.
9870 * LOCKING: Acquires the loader lock.
9873 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9875 g_assert (boxed_error != NULL);
9877 if (mono_class_has_failure (klass))
9880 mono_loader_lock ();
9881 klass->has_failure = 1;
9882 mono_class_set_exception_data (klass, boxed_error);
9883 mono_loader_unlock ();
9889 mono_class_has_failure (const MonoClass *klass)
9891 g_assert (klass != NULL);
9892 return klass->has_failure != 0;
9897 * mono_class_set_type_load_failure:
9898 * \param klass class in which the failure was detected
9899 * \param fmt \c printf -style error message string.
9901 * Collect detected failure informaion in the class for later processing.
9902 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9903 * Note that only the first failure is kept.
9905 * LOCKING: Acquires the loader lock.
9907 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9910 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9912 MonoError prepare_error;
9915 if (mono_class_has_failure (klass))
9918 error_init (&prepare_error);
9920 va_start (args, fmt);
9921 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9924 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9925 mono_error_cleanup (&prepare_error);
9926 return mono_class_set_failure (klass, box);
9930 * mono_classes_init:
9932 * Initialize the resources used by this module.
9933 * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
9935 MONO_NO_SANITIZE_THREAD
9937 mono_classes_init (void)
9939 mono_os_mutex_init (&classes_mutex);
9941 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9942 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9944 mono_counters_register ("MonoClassDef count",
9945 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9946 mono_counters_register ("MonoClassGtd count",
9947 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9948 mono_counters_register ("MonoClassGenericInst count",
9949 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9950 mono_counters_register ("MonoClassGenericParam count",
9951 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9952 mono_counters_register ("MonoClassArray count",
9953 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9954 mono_counters_register ("MonoClassPointer count",
9955 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9956 mono_counters_register ("Inflated methods size",
9957 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9958 mono_counters_register ("Inflated classes size",
9959 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9960 mono_counters_register ("MonoClass size",
9961 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9965 * mono_classes_cleanup:
9967 * Free the resources used by this module.
9970 mono_classes_cleanup (void)
9972 mono_native_tls_free (setup_fields_tls_id);
9973 mono_native_tls_free (init_pending_tls_id);
9975 if (global_interface_bitset)
9976 mono_bitset_free (global_interface_bitset);
9977 global_interface_bitset = NULL;
9978 mono_os_mutex_destroy (&classes_mutex);
9982 * mono_class_get_exception_for_failure:
9983 * \param klass class in which the failure was detected
9985 * \returns a constructed MonoException than the caller can then throw
9986 * using mono_raise_exception - or NULL if no failure is present (or
9987 * doesn't result in an exception).
9990 mono_class_get_exception_for_failure (MonoClass *klass)
9992 if (!mono_class_has_failure (klass))
9994 MonoError unboxed_error;
9995 error_init (&unboxed_error);
9996 mono_error_set_for_class_failure (&unboxed_error, klass);
9997 return mono_error_convert_to_exception (&unboxed_error);
10001 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10003 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10004 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10006 if (outer_klass == inner_klass)
10008 inner_klass = inner_klass->nested_in;
10009 } while (inner_klass);
10014 mono_class_get_generic_type_definition (MonoClass *klass)
10016 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10017 return gklass ? gklass->container_class : klass;
10021 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10023 * Generic instantiations are ignored for all super types of @klass.
10025 * Visibility checks ignoring generic instantiations.
10028 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10031 klass = mono_class_get_generic_type_definition (klass);
10032 parent = mono_class_get_generic_type_definition (parent);
10033 mono_class_setup_supertypes (klass);
10035 for (i = 0; i < klass->idepth; ++i) {
10036 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10042 * Subtype can only access parent members with family protection if the site object
10043 * is subclass of Subtype. For example:
10044 * class A { protected int x; }
10046 * void valid_access () {
10050 * void invalid_access () {
10057 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10059 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10062 if (context_klass == NULL)
10064 /*if access_klass is not member_klass context_klass must be type compat*/
10065 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10071 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10074 if (accessing == accessed)
10076 if (!accessed || !accessing)
10079 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10080 * anywhere so untrusted friends are not safe to access platform's code internals */
10081 if (mono_security_core_clr_enabled ()) {
10082 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10086 mono_assembly_load_friends (accessed);
10087 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10088 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10089 /* Be conservative with checks */
10090 if (!friend_->name)
10092 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10094 if (friend_->public_key_token [0]) {
10095 if (!accessing->aname.public_key_token [0])
10097 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10106 * If klass is a generic type or if it is derived from a generic type, return the
10107 * MonoClass of the generic definition
10108 * Returns NULL if not found
10111 get_generic_definition_class (MonoClass *klass)
10114 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10115 if (gklass && gklass->container_class)
10116 return gklass->container_class;
10117 klass = klass->parent;
10123 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10126 for (i = 0; i < ginst->type_argc; ++i) {
10127 MonoType *type = ginst->type_argv[i];
10128 switch (type->type) {
10129 case MONO_TYPE_SZARRAY:
10130 if (!can_access_type (access_klass, type->data.klass))
10133 case MONO_TYPE_ARRAY:
10134 if (!can_access_type (access_klass, type->data.array->eklass))
10137 case MONO_TYPE_PTR:
10138 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10141 case MONO_TYPE_CLASS:
10142 case MONO_TYPE_VALUETYPE:
10143 case MONO_TYPE_GENERICINST:
10144 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10154 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10158 if (access_klass == member_klass)
10161 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10164 if (access_klass->element_class && !access_klass->enumtype)
10165 access_klass = access_klass->element_class;
10167 if (member_klass->element_class && !member_klass->enumtype)
10168 member_klass = member_klass->element_class;
10170 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10172 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10175 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10178 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10181 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10184 /*Non nested type with nested visibility. We just fail it.*/
10185 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10188 switch (access_level) {
10189 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10190 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10192 case TYPE_ATTRIBUTE_PUBLIC:
10195 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10198 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10199 return is_nesting_type (member_klass, access_klass);
10201 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10202 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10204 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10205 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10207 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10208 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10209 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10211 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10212 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10213 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10218 /* FIXME: check visibility of type, too */
10220 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10222 MonoClass *member_generic_def;
10223 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10226 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10227 if (((access_gklass && access_gklass->container_class) ||
10228 mono_class_is_gtd (access_klass)) &&
10229 (member_generic_def = get_generic_definition_class (member_klass))) {
10230 MonoClass *access_container;
10232 if (mono_class_is_gtd (access_klass))
10233 access_container = access_klass;
10235 access_container = access_gklass->container_class;
10237 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10241 /* Partition I 8.5.3.2 */
10242 /* the access level values are the same for fields and methods */
10243 switch (access_level) {
10244 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10245 /* same compilation unit */
10246 return access_klass->image == member_klass->image;
10247 case FIELD_ATTRIBUTE_PRIVATE:
10248 return access_klass == member_klass;
10249 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10250 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10251 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10254 case FIELD_ATTRIBUTE_ASSEMBLY:
10255 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10256 case FIELD_ATTRIBUTE_FAMILY:
10257 if (is_valid_family_access (access_klass, member_klass, context_klass))
10260 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10261 if (is_valid_family_access (access_klass, member_klass, context_klass))
10263 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10264 case FIELD_ATTRIBUTE_PUBLIC:
10271 * mono_method_can_access_field:
10272 * \param method Method that will attempt to access the field
10273 * \param field the field to access
10275 * Used to determine if a method is allowed to access the specified field.
10277 * \returns TRUE if the given \p method is allowed to access the \p field while following
10278 * the accessibility rules of the CLI.
10281 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10283 /* FIXME: check all overlapping fields */
10284 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10286 MonoClass *nested = method->klass->nested_in;
10288 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10291 nested = nested->nested_in;
10298 * mono_method_can_access_method:
10299 * \param method Method that will attempt to access the other method
10300 * \param called the method that we want to probe for accessibility.
10302 * Used to determine if the \p method is allowed to access the specified \p called method.
10304 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10305 * the accessibility rules of the CLI.
10308 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10310 method = mono_method_get_method_definition (method);
10311 called = mono_method_get_method_definition (called);
10312 return mono_method_can_access_method_full (method, called, NULL);
10316 * mono_method_can_access_method_full:
10317 * @method: The caller method
10318 * @called: The called method
10319 * @context_klass: The static type on stack of the owner @called object used
10321 * This function must be used with instance calls, as they have more strict family accessibility.
10322 * It can be used with static methods, but context_klass should be NULL.
10324 * Returns: TRUE if caller have proper visibility and acessibility to @called
10327 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10329 /* Wrappers are except from access checks */
10330 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10333 MonoClass *access_class = method->klass;
10334 MonoClass *member_class = called->klass;
10335 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10337 MonoClass *nested = access_class->nested_in;
10339 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10342 nested = nested->nested_in;
10349 can = can_access_type (access_class, member_class);
10351 MonoClass *nested = access_class->nested_in;
10353 can = can_access_type (nested, member_class);
10356 nested = nested->nested_in;
10363 if (called->is_inflated) {
10364 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10365 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10374 * mono_method_can_access_field_full:
10375 * @method: The caller method
10376 * @field: The accessed field
10377 * @context_klass: The static type on stack of the owner @field object used
10379 * This function must be used with instance fields, as they have more strict family accessibility.
10380 * It can be used with static fields, but context_klass should be NULL.
10382 * Returns: TRUE if caller have proper visibility and acessibility to @field
10385 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10387 MonoClass *access_class = method->klass;
10388 MonoClass *member_class = field->parent;
10389 /* FIXME: check all overlapping fields */
10390 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10392 MonoClass *nested = access_class->nested_in;
10394 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10397 nested = nested->nested_in;
10404 can = can_access_type (access_class, member_class);
10406 MonoClass *nested = access_class->nested_in;
10408 can = can_access_type (nested, member_class);
10411 nested = nested->nested_in;
10421 * mono_class_can_access_class:
10422 * @source_class: The source class
10423 * @target_class: The accessed class
10425 * This function returns is @target_class is visible to @source_class
10427 * Returns: TRUE if source have proper visibility and acessibility to target
10430 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10432 return can_access_type (source_class, target_class);
10436 * mono_type_is_valid_enum_basetype:
10437 * \param type The MonoType to check
10438 * \returns TRUE if the type can be used as the basetype of an enum
10440 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10441 switch (type->type) {
10444 case MONO_TYPE_BOOLEAN:
10447 case MONO_TYPE_CHAR:
10461 * mono_class_is_valid_enum:
10462 * \param klass An enum class to be validated
10464 * This method verify the required properties an enum should have.
10466 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10467 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10468 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10470 * \returns TRUE if the informed enum class is valid
10473 mono_class_is_valid_enum (MonoClass *klass)
10475 MonoClassField * field;
10476 gpointer iter = NULL;
10477 gboolean found_base_field = FALSE;
10479 g_assert (klass->enumtype);
10480 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10481 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10485 if (!mono_class_is_auto_layout (klass))
10488 while ((field = mono_class_get_fields (klass, &iter))) {
10489 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10490 if (found_base_field)
10492 found_base_field = TRUE;
10493 if (!mono_type_is_valid_enum_basetype (field->type))
10498 if (!found_base_field)
10501 if (mono_class_get_method_count (klass) > 0)
10508 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10510 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10514 * mono_class_setup_interface_id:
10516 * Initializes MonoClass::interface_id if required.
10518 * LOCKING: Acquires the loader lock.
10521 mono_class_setup_interface_id (MonoClass *klass)
10523 mono_loader_lock ();
10524 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10525 klass->interface_id = mono_get_unique_iid (klass);
10526 mono_loader_unlock ();
10530 * mono_class_setup_interfaces:
10532 * Initialize klass->interfaces/interfaces_count.
10533 * LOCKING: Acquires the loader lock.
10534 * This function can fail the type.
10537 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10539 int i, interface_count;
10540 MonoClass **interfaces;
10542 error_init (error);
10544 if (klass->interfaces_inited)
10547 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10548 MonoType *args [1];
10550 /* IList and IReadOnlyList -> 2x if enum*/
10551 interface_count = klass->element_class->enumtype ? 4 : 2;
10552 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10554 args [0] = &klass->element_class->byval_arg;
10555 interfaces [0] = mono_class_bind_generic_parameters (
10556 mono_defaults.generic_ilist_class, 1, args, FALSE);
10557 interfaces [1] = mono_class_bind_generic_parameters (
10558 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10559 if (klass->element_class->enumtype) {
10560 args [0] = mono_class_enum_basetype (klass->element_class);
10561 interfaces [2] = mono_class_bind_generic_parameters (
10562 mono_defaults.generic_ilist_class, 1, args, FALSE);
10563 interfaces [3] = mono_class_bind_generic_parameters (
10564 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10566 } else if (mono_class_is_ginst (klass)) {
10567 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10569 mono_class_setup_interfaces (gklass, error);
10570 if (!mono_error_ok (error)) {
10571 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10575 interface_count = gklass->interface_count;
10576 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10577 for (i = 0; i < interface_count; i++) {
10578 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10579 if (!mono_error_ok (error)) {
10580 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10585 interface_count = 0;
10589 mono_loader_lock ();
10590 if (!klass->interfaces_inited) {
10591 klass->interface_count = interface_count;
10592 klass->interfaces = interfaces;
10594 mono_memory_barrier ();
10596 klass->interfaces_inited = TRUE;
10598 mono_loader_unlock ();
10602 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10604 MonoClass *klass = field->parent;
10605 MonoImage *image = klass->image;
10606 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10608 int field_idx = field - klass->fields;
10610 error_init (error);
10613 MonoClassField *gfield = >d->fields [field_idx];
10614 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10615 if (!mono_error_ok (error)) {
10616 char *full_name = mono_type_get_full_name (gtd);
10617 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));
10618 g_free (full_name);
10621 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10622 if (!mono_error_ok (error)) {
10623 char *full_name = mono_type_get_full_name (klass);
10624 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));
10625 g_free (full_name);
10629 guint32 cols [MONO_FIELD_SIZE];
10630 MonoGenericContainer *container = NULL;
10631 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10633 /*FIXME, in theory we do not lazy load SRE fields*/
10634 g_assert (!image_is_dynamic (image));
10636 if (mono_class_is_gtd (klass)) {
10637 container = mono_class_get_generic_container (klass);
10639 container = mono_class_get_generic_container (gtd);
10640 g_assert (container);
10643 /* first_field_idx and idx points into the fieldptr table */
10644 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10646 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10647 char *full_name = mono_type_get_full_name (klass);
10648 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10649 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10650 g_free (full_name);
10654 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10656 mono_metadata_decode_value (sig, &sig);
10657 /* FIELD signature == 0x06 */
10658 g_assert (*sig == 0x06);
10660 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10662 char *full_name = mono_type_get_full_name (klass);
10663 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));
10664 g_free (full_name);
10667 mono_memory_barrier ();
10668 field->type = ftype;
10672 mono_field_resolve_flags (MonoClassField *field)
10674 MonoClass *klass = field->parent;
10675 MonoImage *image = klass->image;
10676 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10677 int field_idx = field - klass->fields;
10680 MonoClassField *gfield = >d->fields [field_idx];
10681 return mono_field_get_flags (gfield);
10683 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10685 /*FIXME, in theory we do not lazy load SRE fields*/
10686 g_assert (!image_is_dynamic (image));
10688 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10693 * mono_class_get_fields_lazy:
10694 * \param klass the MonoClass to act on
10696 * This routine is an iterator routine for retrieving the fields in a class.
10697 * Only minimal information about fields are loaded. Accessors must be used
10698 * for all MonoClassField returned.
10700 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10701 * iterate over all of the elements. When no more values are
10702 * available, the return value is NULL.
10704 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10707 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10709 MonoClassField* field;
10713 mono_class_setup_basic_field_info (klass);
10714 if (!klass->fields)
10716 /* start from the first */
10717 if (mono_class_get_field_count (klass)) {
10718 *iter = &klass->fields [0];
10719 return (MonoClassField *)*iter;
10725 field = (MonoClassField *)*iter;
10727 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10729 return (MonoClassField *)*iter;
10735 mono_class_full_name (MonoClass *klass)
10737 return mono_type_full_name (&klass->byval_arg);
10740 /* Declare all shared lazy type lookup functions */
10741 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10744 * mono_method_get_base_method:
10745 * \param method a method
10746 * \param definition if true, get the definition
10747 * \param error set on failure
10749 * Given a virtual method associated with a subclass, return the corresponding
10750 * method from an ancestor. If \p definition is FALSE, returns the method in the
10751 * superclass of the given method. If \p definition is TRUE, return the method
10752 * in the ancestor class where it was first declared. The type arguments will
10753 * be inflated in the ancestor classes. If the method is not associated with a
10754 * class, or isn't virtual, returns the method itself. On failure returns NULL
10755 * and sets \p error.
10758 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10760 MonoClass *klass, *parent;
10761 MonoGenericContext *generic_inst = NULL;
10762 MonoMethod *result = NULL;
10765 if (method->klass == NULL)
10768 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10769 MONO_CLASS_IS_INTERFACE (method->klass) ||
10770 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10773 slot = mono_method_get_vtable_slot (method);
10777 klass = method->klass;
10778 if (mono_class_is_ginst (klass)) {
10779 generic_inst = mono_class_get_context (klass);
10780 klass = mono_class_get_generic_class (klass)->container_class;
10785 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10786 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10787 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10788 or klass is the generic container class and generic_inst is the instantiation.
10790 when we go to the parent, if the parent is an open constructed type, we need to
10791 replace the type parameters by the definitions from the generic_inst, and then take it
10792 apart again into the klass and the generic_inst.
10794 For cases like this:
10795 class C<T> : B<T, int> {
10796 public override void Foo () { ... }
10798 class B<U,V> : A<HashMap<U,V>> {
10799 public override void Foo () { ... }
10802 public virtual void Foo () { ... }
10805 if at each iteration the parent isn't open, we can skip inflating it. if at some
10806 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10809 MonoGenericContext *parent_inst = NULL;
10810 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10811 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10812 return_val_if_nok (error, NULL);
10814 if (mono_class_is_ginst (parent)) {
10815 parent_inst = mono_class_get_context (parent);
10816 parent = mono_class_get_generic_class (parent)->container_class;
10819 mono_class_setup_vtable (parent);
10820 if (parent->vtable_size <= slot)
10823 generic_inst = parent_inst;
10826 klass = klass->parent;
10829 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10830 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10831 return_val_if_nok (error, NULL);
10833 generic_inst = NULL;
10835 if (mono_class_is_ginst (klass)) {
10836 generic_inst = mono_class_get_context (klass);
10837 klass = mono_class_get_generic_class (klass)->container_class;
10842 if (generic_inst) {
10843 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10844 return_val_if_nok (error, NULL);
10847 if (klass == method->klass)
10850 /*This is possible if definition == FALSE.
10851 * Do it here to be really sure we don't read invalid memory.
10853 if (slot >= klass->vtable_size)
10856 mono_class_setup_vtable (klass);
10858 result = klass->vtable [slot];
10859 if (result == NULL) {
10860 /* It is an abstract method */
10861 gboolean found = FALSE;
10862 gpointer iter = NULL;
10863 while ((result = mono_class_get_methods (klass, &iter))) {
10864 if (result->slot == slot) {
10869 /* found might be FALSE if we looked in an abstract class
10870 * that doesn't override an abstract method of its
10872 * abstract class Base {
10873 * public abstract void Foo ();
10875 * abstract class Derived : Base { }
10876 * class Child : Derived {
10877 * public override void Foo () { }
10880 * if m was Child.Foo and we ask for the base method,
10881 * then we get here with klass == Derived and found == FALSE
10883 /* but it shouldn't be the case that if we're looking
10884 * for the definition and didn't find a result; the
10885 * loop above should've taken us as far as we could
10887 g_assert (!(definition && !found));
10892 g_assert (result != NULL);