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 g_ptr_array_add (*res, ic);
2930 g_hash_table_insert (*ifaces, ic, ic);
2931 mono_class_init (ic);
2932 if (mono_class_has_failure (ic)) {
2933 mono_error_set_type_load_class (error, ic, "Error Loading class");
2937 collect_implemented_interfaces_aux (ic, res, ifaces, error);
2938 return_if_nok (error);
2943 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2945 GPtrArray *res = NULL;
2946 GHashTable *ifaces = NULL;
2948 collect_implemented_interfaces_aux (klass, &res, &ifaces, error);
2950 g_hash_table_destroy (ifaces);
2951 if (!mono_error_ok (error)) {
2953 g_ptr_array_free (res, TRUE);
2960 compare_interface_ids (const void *p_key, const void *p_element)
2962 const MonoClass *key = (const MonoClass *)p_key;
2963 const MonoClass *element = *(const MonoClass **)p_element;
2965 return (key->interface_id - element->interface_id);
2968 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2970 mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
2972 MonoClass **result = (MonoClass **)mono_binary_search (
2974 klass->interfaces_packed,
2975 klass->interface_offsets_count,
2976 sizeof (MonoClass *),
2977 compare_interface_ids);
2979 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2986 * mono_class_interface_offset_with_variance:
2988 * Return the interface offset of \p itf in \p klass. Sets \p non_exact_match to TRUE if the match required variance check
2989 * If \p itf is an interface with generic variant arguments, try to find the compatible one.
2991 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2993 * FIXME figure out MS disambiguation rules and fix this function.
2996 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match)
2998 int i = mono_class_interface_offset (klass, itf);
2999 *non_exact_match = FALSE;
3003 if (itf->is_array_special_interface && klass->rank < 2) {
3004 MonoClass *gtd = mono_class_get_generic_type_definition (itf);
3006 for (i = 0; i < klass->interface_offsets_count; i++) {
3007 // printf ("\t%s\n", mono_type_get_full_name (klass->interfaces_packed [i]));
3008 if (mono_class_get_generic_type_definition (klass->interfaces_packed [i]) == gtd) {
3009 *non_exact_match = TRUE;
3010 return klass->interface_offsets_packed [i];
3015 if (!mono_class_has_variant_generic_params (itf))
3018 for (i = 0; i < klass->interface_offsets_count; i++) {
3019 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
3020 *non_exact_match = TRUE;
3021 return klass->interface_offsets_packed [i];
3029 print_implemented_interfaces (MonoClass *klass)
3033 GPtrArray *ifaces = NULL;
3035 int ancestor_level = 0;
3037 name = mono_type_get_full_name (klass);
3038 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
3041 for (i = 0; i < klass->interface_offsets_count; i++)
3042 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3043 klass->interfaces_packed [i]->interface_id,
3044 klass->interface_offsets_packed [i],
3045 mono_class_get_method_count (klass->interfaces_packed [i]),
3046 klass->interfaces_packed [i]->name_space,
3047 klass->interfaces_packed [i]->name );
3048 printf ("Interface flags: ");
3049 for (i = 0; i <= klass->max_interface_id; i++)
3050 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
3051 printf ("(%d,T)", i);
3053 printf ("(%d,F)", i);
3055 printf ("Dump interface flags:");
3056 #ifdef COMPRESSED_INTERFACE_BITMAP
3058 const uint8_t* p = klass->interface_bitmap;
3059 i = klass->max_interface_id;
3061 printf (" %d x 00 %02X", p [0], p [1]);
3067 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
3068 printf (" %02X", klass->interface_bitmap [i]);
3071 while (klass != NULL) {
3072 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
3073 ifaces = mono_class_get_implemented_interfaces (klass, &error);
3074 if (!mono_error_ok (&error)) {
3075 printf (" Type failed due to %s\n", mono_error_get_message (&error));
3076 mono_error_cleanup (&error);
3077 } else if (ifaces) {
3078 for (i = 0; i < ifaces->len; i++) {
3079 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3080 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
3081 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
3083 mono_class_interface_offset (klass, ic),
3084 mono_class_get_method_count (ic),
3088 g_ptr_array_free (ifaces, TRUE);
3091 klass = klass->parent;
3096 * Return the number of virtual methods.
3097 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3098 * Return -1 on failure.
3099 * FIXME It would be nice if this information could be cached somewhere.
3102 count_virtual_methods (MonoClass *klass)
3104 int i, mcount, vcount = 0;
3106 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3108 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3109 mono_class_setup_methods (klass);
3110 if (mono_class_has_failure (klass))
3113 mcount = mono_class_get_method_count (klass);
3114 for (i = 0; i < mcount; ++i) {
3115 flags = klass->methods [i]->flags;
3116 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3120 int first_idx = mono_class_get_first_method_idx (klass);
3121 mcount = mono_class_get_method_count (klass);
3122 for (i = 0; i < mcount; ++i) {
3123 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
3125 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3133 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3141 m = (l + num_ifaces) / 2;
3142 if (interfaces_full [m] == ic)
3144 if (l == num_ifaces)
3146 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3155 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3157 int i = find_interface (num_ifaces, interfaces_full, ic);
3161 interface_offsets_full [i] = offset;
3164 for (i = 0; i < num_ifaces; ++i) {
3165 if (interfaces_full [i]) {
3167 if (interfaces_full [i]->interface_id < ic->interface_id)
3170 while (end < num_ifaces && interfaces_full [end]) end++;
3171 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3172 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3174 interfaces_full [i] = ic;
3175 interface_offsets_full [i] = offset;
3181 #ifdef COMPRESSED_INTERFACE_BITMAP
3184 * Compressed interface bitmap design.
3186 * Interface bitmaps take a large amount of memory, because their size is
3187 * linear with the maximum interface id assigned in the process (each interface
3188 * is assigned a unique id as it is loaded). The number of interface classes
3189 * is high because of the many implicit interfaces implemented by arrays (we'll
3190 * need to lazy-load them in the future).
3191 * Most classes implement a very small number of interfaces, so the bitmap is
3192 * sparse. This bitmap needs to be checked by interface casts, so access to the
3193 * needed bit must be fast and doable with few jit instructions.
3195 * The current compression format is as follows:
3196 * *) it is a sequence of one or more two-byte elements
3197 * *) the first byte in the element is the count of empty bitmap bytes
3198 * at the current bitmap position
3199 * *) the second byte in the element is an actual bitmap byte at the current
3202 * As an example, the following compressed bitmap bytes:
3203 * 0x07 0x01 0x00 0x7
3204 * correspond to the following bitmap:
3205 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3207 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3208 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3209 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3213 * mono_compress_bitmap:
3214 * \param dest destination buffer
3215 * \param bitmap bitmap buffer
3216 * \param size size of \p bitmap in bytes
3218 * This is a mono internal function.
3219 * The \p bitmap data is compressed into a format that is small but
3220 * still searchable in few instructions by the JIT and runtime.
3221 * The compressed data is stored in the buffer pointed to by the
3222 * \p dest array. Passing a NULL value for \p dest allows to just compute
3223 * the size of the buffer.
3224 * This compression algorithm assumes the bits set in the bitmap are
3225 * few and far between, like in interface bitmaps.
3226 * \returns The size of the compressed bitmap in bytes.
3229 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3233 const uint8_t *end = bitmap + size;
3234 while (bitmap < end) {
3235 if (*bitmap || numz == 255) {
3259 * mono_class_interface_match:
3260 * \param bitmap a compressed bitmap buffer
3261 * \param id the index to check in the bitmap
3263 * This is a mono internal function.
3264 * Checks if a bit is set in a compressed interface bitmap. \p id must
3265 * be already checked for being smaller than the maximum id encoded in the
3268 * \returns A non-zero value if bit \p id is set in the bitmap \p bitmap,
3272 mono_class_interface_match (const uint8_t *bitmap, int id)
3275 id -= bitmap [0] * 8;
3279 return bitmap [1] & (1 << id);
3288 * Return -1 on failure and set klass->has_failure and store a MonoErrorBoxed with the details.
3289 * LOCKING: Acquires the loader lock.
3292 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3296 int i, j, num_ifaces;
3298 MonoClass **interfaces_full = NULL;
3299 int *interface_offsets_full = NULL;
3301 GPtrArray **ifaces_array = NULL;
3302 int interface_offsets_count;
3304 mono_loader_lock ();
3306 mono_class_setup_supertypes (klass);
3308 /* compute maximum number of slots and maximum interface id */
3310 num_ifaces = 0; /* this can include duplicated ones */
3311 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3312 for (j = 0; j < klass->idepth; j++) {
3313 k = klass->supertypes [j];
3315 num_ifaces += k->interface_count;
3316 for (i = 0; i < k->interface_count; i++) {
3317 ic = k->interfaces [i];
3319 mono_class_init (ic);
3321 if (max_iid < ic->interface_id)
3322 max_iid = ic->interface_id;
3324 ifaces = mono_class_get_implemented_interfaces (k, &error);
3325 if (!mono_error_ok (&error)) {
3326 char *name = mono_type_get_full_name (k);
3327 mono_class_set_type_load_failure (klass, "Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error));
3329 mono_error_cleanup (&error);
3334 num_ifaces += ifaces->len;
3335 for (i = 0; i < ifaces->len; ++i) {
3336 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3337 if (max_iid < ic->interface_id)
3338 max_iid = ic->interface_id;
3340 ifaces_array [j] = ifaces;
3344 if (MONO_CLASS_IS_INTERFACE (klass)) {
3346 if (max_iid < klass->interface_id)
3347 max_iid = klass->interface_id;
3350 /* compute vtable offset for interfaces */
3351 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3352 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3354 for (i = 0; i < num_ifaces; i++)
3355 interface_offsets_full [i] = -1;
3357 /* skip the current class */
3358 for (j = 0; j < klass->idepth - 1; j++) {
3359 k = klass->supertypes [j];
3360 ifaces = ifaces_array [j];
3363 for (i = 0; i < ifaces->len; ++i) {
3365 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3367 /*Force the sharing of interface offsets between parent and subtypes.*/
3368 io = mono_class_interface_offset (k, ic);
3370 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3375 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3376 ifaces = ifaces_array [klass->idepth - 1];
3378 for (i = 0; i < ifaces->len; ++i) {
3380 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3381 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3383 count = count_virtual_methods (ic);
3385 char *name = mono_type_get_full_name (ic);
3386 mono_class_set_type_load_failure (klass, "Error calculating interface offset of %s", name);
3395 if (MONO_CLASS_IS_INTERFACE (klass))
3396 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3398 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3399 if (interface_offsets_full [i] != -1)
3400 interface_offsets_count ++;
3403 /* Publish the data */
3404 klass->max_interface_id = max_iid;
3406 * We might get called multiple times:
3407 * - mono_class_init ()
3408 * - mono_class_setup_vtable ().
3409 * - mono_class_setup_interface_offsets ().
3410 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3411 * means we have to overwrite those when called from other places (#4440).
3413 if (klass->interfaces_packed) {
3415 g_assert (klass->interface_offsets_count == interface_offsets_count);
3419 klass->interface_offsets_count = interface_offsets_count;
3420 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3421 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3422 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3423 #ifdef COMPRESSED_INTERFACE_BITMAP
3424 bitmap = g_malloc0 (bsize);
3426 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3428 for (i = 0; i < interface_offsets_count; i++) {
3429 guint32 id = interfaces_full [i]->interface_id;
3430 bitmap [id >> 3] |= (1 << (id & 7));
3431 klass->interfaces_packed [i] = interfaces_full [i];
3432 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3434 #ifdef COMPRESSED_INTERFACE_BITMAP
3435 i = mono_compress_bitmap (NULL, bitmap, bsize);
3436 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3437 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3440 klass->interface_bitmap = bitmap;
3444 mono_loader_unlock ();
3446 g_free (interfaces_full);
3447 g_free (interface_offsets_full);
3448 for (i = 0; i < klass->idepth; i++) {
3449 ifaces = ifaces_array [i];
3451 g_ptr_array_free (ifaces, TRUE);
3453 g_free (ifaces_array);
3455 //printf ("JUST DONE: ");
3456 //print_implemented_interfaces (klass);
3462 * Setup interface offsets for interfaces.
3464 * - klass->max_interface_id
3465 * - klass->interface_offsets_count
3466 * - klass->interfaces_packed
3467 * - klass->interface_offsets_packed
3468 * - klass->interface_bitmap
3470 * This function can fail @class.
3473 mono_class_setup_interface_offsets (MonoClass *klass)
3475 setup_interface_offsets (klass, 0, FALSE);
3478 /*Checks if @klass has @parent as one of it's parents type gtd
3482 * Bar<T> : Foo<Bar<Bar<T>>>
3486 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3488 klass = mono_class_get_generic_type_definition (klass);
3489 parent = mono_class_get_generic_type_definition (parent);
3490 mono_class_setup_supertypes (klass);
3491 mono_class_setup_supertypes (parent);
3493 return klass->idepth >= parent->idepth &&
3494 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3498 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3500 MonoGenericInst *ginst;
3503 if (!mono_class_is_ginst (klass)) {
3504 mono_class_setup_vtable_full (klass, in_setup);
3505 return !mono_class_has_failure (klass);
3508 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3509 if (mono_class_set_type_load_failure_causedby_class (klass, mono_class_get_generic_class (klass)->container_class, "Failed to load generic definition vtable"))
3512 ginst = mono_class_get_generic_class (klass)->context.class_inst;
3513 for (i = 0; i < ginst->type_argc; ++i) {
3515 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3517 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3518 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3519 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3521 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3522 mono_class_set_type_load_failure (klass, "Failed to load generic parameter %d", i);
3530 * mono_class_setup_vtable:
3532 * Creates the generic vtable of CLASS.
3533 * Initializes the following fields in MonoClass:
3536 * Plus all the fields initialized by setup_interface_offsets ().
3537 * If there is an error during vtable construction, klass->has_failure
3538 * is set and details are stored in a MonoErrorBoxed.
3540 * LOCKING: Acquires the loader lock.
3543 mono_class_setup_vtable (MonoClass *klass)
3545 mono_class_setup_vtable_full (klass, NULL);
3549 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3552 MonoMethod **overrides;
3553 MonoGenericContext *context;
3561 if (MONO_CLASS_IS_INTERFACE (klass)) {
3562 /* This sets method->slot for all methods if this is an interface */
3563 mono_class_setup_methods (klass);
3567 if (mono_class_has_failure (klass))
3570 if (g_list_find (in_setup, klass))
3573 mono_loader_lock ();
3575 if (klass->vtable) {
3576 mono_loader_unlock ();
3580 UnlockedIncrement (&mono_stats.generic_vtable_count);
3581 in_setup = g_list_prepend (in_setup, klass);
3583 if (mono_class_is_ginst (klass)) {
3584 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3585 mono_loader_unlock ();
3586 g_list_remove (in_setup, klass);
3590 context = mono_class_get_context (klass);
3591 type_token = mono_class_get_generic_class (klass)->container_class->type_token;
3593 context = (MonoGenericContext *) mono_class_try_get_generic_container (klass); //FIXME is this a case of a try?
3594 type_token = klass->type_token;
3597 if (image_is_dynamic (klass->image)) {
3598 /* Generic instances can have zero method overrides without causing any harm.
3599 * This is true since we don't do layout all over again for them, we simply inflate
3600 * the layout of the parent.
3602 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum, &error);
3603 if (!is_ok (&error)) {
3604 mono_loader_unlock ();
3605 g_list_remove (in_setup, klass);
3606 mono_class_set_type_load_failure (klass, "Could not load list of method overrides due to %s", mono_error_get_message (&error));
3607 mono_error_cleanup (&error);
3611 /* The following call fails if there are missing methods in the type */
3612 /* FIXME it's probably a good idea to avoid this for generic instances. */
3613 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3617 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3619 mono_class_set_type_load_failure (klass, "Could not load list of method overrides");
3623 mono_loader_unlock ();
3624 g_list_remove (in_setup, klass);
3629 #define DEBUG_INTERFACE_VTABLE_CODE 0
3630 #define TRACE_INTERFACE_VTABLE_CODE 0
3631 #define VERIFY_INTERFACE_VTABLE_CODE 0
3632 #define VTABLE_SELECTOR (1)
3634 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3635 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3636 if (!(VTABLE_SELECTOR)) break; \
3640 #define DEBUG_INTERFACE_VTABLE(stmt)
3643 #if TRACE_INTERFACE_VTABLE_CODE
3644 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3645 if (!(VTABLE_SELECTOR)) break; \
3649 #define TRACE_INTERFACE_VTABLE(stmt)
3652 #if VERIFY_INTERFACE_VTABLE_CODE
3653 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3654 if (!(VTABLE_SELECTOR)) break; \
3658 #define VERIFY_INTERFACE_VTABLE(stmt)
3662 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3664 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3668 GString *res = g_string_new ("");
3670 g_string_append_c (res, '(');
3671 for (i = 0; i < sig->param_count; ++i) {
3673 g_string_append_c (res, ',');
3674 mono_type_get_desc (res, sig->params [i], include_namespace);
3676 g_string_append (res, ")=>");
3677 if (sig->ret != NULL) {
3678 mono_type_get_desc (res, sig->ret, include_namespace);
3680 g_string_append (res, "NULL");
3683 g_string_free (res, FALSE);
3687 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3688 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3689 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3690 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3698 is_wcf_hack_disabled (void)
3700 static gboolean disabled;
3701 static gboolean inited = FALSE;
3703 disabled = g_hasenv ("MONO_DISABLE_WCF_HACK");
3710 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3712 MonoMethodSignature *cmsig, *imsig;
3713 if (strcmp (im->name, cm->name) == 0) {
3714 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3715 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3718 if (! slot_is_empty) {
3719 if (require_newslot) {
3720 if (! interface_is_explicitly_implemented_by_class) {
3721 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3724 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3725 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3729 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3732 cmsig = mono_method_signature (cm);
3733 imsig = mono_method_signature (im);
3734 if (!cmsig || !imsig) {
3735 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3739 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3740 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3741 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3742 TRACE_INTERFACE_VTABLE (printf ("]"));
3745 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3746 if (mono_security_core_clr_enabled ())
3747 mono_security_core_clr_check_override (klass, cm, im);
3749 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3750 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3751 char *body_name = mono_method_full_name (cm, TRUE);
3752 char *decl_name = mono_method_full_name (im, TRUE);
3753 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3761 MonoClass *ic = im->klass;
3762 const char *ic_name_space = ic->name_space;
3763 const char *ic_name = ic->name;
3766 if (! require_newslot) {
3767 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3770 if (cm->klass->rank == 0) {
3771 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3774 cmsig = mono_method_signature (cm);
3775 imsig = mono_method_signature (im);
3776 if (!cmsig || !imsig) {
3777 mono_class_set_type_load_failure (klass, "Could not resolve the signature of a virtual method");
3781 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3782 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3783 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3784 TRACE_INTERFACE_VTABLE (printf ("]"));
3787 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3788 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3791 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3792 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3795 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))) {
3796 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3800 subname = strstr (cm->name, ic_name_space);
3801 if (subname != cm->name) {
3802 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3805 subname += strlen (ic_name_space);
3806 if (subname [0] != '.') {
3807 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3811 if (strstr (subname, ic_name) != subname) {
3812 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3815 subname += strlen (ic_name);
3816 if (subname [0] != '.') {
3817 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3821 if (strcmp (subname, im->name) != 0) {
3822 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3826 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3827 if (mono_security_core_clr_enabled ())
3828 mono_security_core_clr_check_override (klass, cm, im);
3830 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3831 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3832 char *body_name = mono_method_full_name (cm, TRUE);
3833 char *decl_name = mono_method_full_name (im, TRUE);
3834 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
3844 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3846 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3847 MonoMethod *method = key;
3848 MonoMethod *override = value;
3849 MonoClass *method_class = mono_method_get_class (method);
3850 MonoClass *override_class = mono_method_get_class (override);
3852 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3853 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3854 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3857 print_overrides (GHashTable *override_map, const char *message) {
3859 printf ("Override map \"%s\" START:\n", message);
3860 g_hash_table_foreach (override_map, foreach_override, NULL);
3861 printf ("Override map \"%s\" END.\n", message);
3863 printf ("Override map \"%s\" EMPTY.\n", message);
3867 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3868 char *full_name = mono_type_full_name (&klass->byval_arg);
3872 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3874 if (print_interfaces) {
3875 print_implemented_interfaces (klass);
3876 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3879 if (klass->parent) {
3880 parent_size = klass->parent->vtable_size;
3884 for (i = 0; i < size; ++i) {
3885 MonoMethod *cm = vtable [i];
3886 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3887 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3889 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3897 #if VERIFY_INTERFACE_VTABLE_CODE
3899 mono_method_try_get_vtable_index (MonoMethod *method)
3901 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3902 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3903 if (imethod->declaring->is_generic)
3904 return imethod->declaring->slot;
3906 return method->slot;
3910 mono_class_verify_vtable (MonoClass *klass)
3913 char *full_name = mono_type_full_name (&klass->byval_arg);
3915 printf ("*** Verifying VTable of class '%s' \n", full_name);
3919 if (!klass->methods)
3922 count = mono_class_method_count (klass);
3923 for (i = 0; i < count; ++i) {
3924 MonoMethod *cm = klass->methods [i];
3927 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3931 full_name = mono_method_full_name (cm, TRUE);
3933 slot = mono_method_try_get_vtable_index (cm);
3935 if (slot >= klass->vtable_size) {
3936 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
3940 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
3941 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
3942 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3943 g_free (other_name);
3946 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3953 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum)
3956 char *method_signature;
3959 for (index = 0; index < onum; ++index) {
3960 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)", im_slot, overrides [index*2+1]->name,
3961 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3963 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3964 type_name = mono_type_full_name (&klass->byval_arg);
3965 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s",
3966 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3967 g_free (method_signature);
3969 mono_class_setup_methods (klass);
3970 if (mono_class_has_failure (klass)) {
3971 char *name = mono_type_get_full_name (klass);
3972 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods", name);
3976 mcount = mono_class_get_method_count (klass);
3977 for (index = 0; index < mcount; ++index) {
3978 MonoMethod *cm = klass->methods [index];
3979 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3981 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)", cm->name, method_signature);
3982 g_free (method_signature);
3987 mono_method_get_method_definition (MonoMethod *method)
3989 while (method->is_inflated)
3990 method = ((MonoMethodInflated*)method)->declaring;
3995 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
3999 for (i = 0; i < onum; ++i) {
4000 MonoMethod *decl = overrides [i * 2];
4001 MonoMethod *body = overrides [i * 2 + 1];
4003 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4004 mono_class_set_type_load_failure (klass, "Method belongs to a different class than the declared one");
4008 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4009 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4010 mono_class_set_type_load_failure (klass, "Method must not be static to override a base type");
4012 mono_class_set_type_load_failure (klass, "Method must be virtual to override a base type");
4016 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4017 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4018 mono_class_set_type_load_failure (klass, "Cannot override a static method in a base type");
4020 mono_class_set_type_load_failure (klass, "Cannot override a non virtual method in a base type");
4024 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4025 mono_class_set_type_load_failure (klass, "Method overrides a class or interface that is not extended or implemented by this type");
4029 body = mono_method_get_method_definition (body);
4030 decl = mono_method_get_method_definition (decl);
4032 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4033 char *body_name = mono_method_full_name (body, TRUE);
4034 char *decl_name = mono_method_full_name (decl, TRUE);
4035 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4045 mono_class_need_stelemref_method (MonoClass *klass)
4047 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4051 apply_override (MonoClass *klass, MonoMethod **vtable, MonoMethod *decl, MonoMethod *override)
4054 dslot = mono_method_get_vtable_slot (decl);
4056 mono_class_set_type_load_failure (klass, "");
4060 dslot += mono_class_interface_offset (klass, decl->klass);
4061 vtable [dslot] = override;
4062 if (!MONO_CLASS_IS_INTERFACE (override->klass)) {
4064 * If override from an interface, then it is an override of a default interface method,
4065 * don't override its slot.
4067 vtable [dslot]->slot = dslot;
4070 if (mono_security_core_clr_enabled ())
4071 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4077 * LOCKING: this is supposed to be called with the loader lock held.
4080 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4084 MonoMethod **vtable = NULL;
4085 int i, max_vtsize = 0, cur_slot = 0;
4087 GPtrArray *ifaces = NULL;
4088 GHashTable *override_map = NULL;
4090 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4091 int first_non_interface_slot;
4093 GSList *virt_methods = NULL, *l;
4094 int stelemref_slot = 0;
4099 if (overrides && !verify_class_overrides (klass, overrides, onum))
4102 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4103 if (!mono_error_ok (&error)) {
4104 char *name = mono_type_get_full_name (klass);
4105 mono_class_set_type_load_failure (klass, "Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error));
4107 mono_error_cleanup (&error);
4109 } else if (ifaces) {
4110 for (i = 0; i < ifaces->len; i++) {
4111 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4112 max_vtsize += mono_class_get_method_count (ic);
4114 g_ptr_array_free (ifaces, TRUE);
4118 if (klass->parent) {
4119 mono_class_init (klass->parent);
4120 mono_class_setup_vtable_full (klass->parent, in_setup);
4122 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class failed to load"))
4125 max_vtsize += klass->parent->vtable_size;
4126 cur_slot = klass->parent->vtable_size;
4129 max_vtsize += mono_class_get_method_count (klass);
4131 /*Array have a slot for stelemref*/
4132 if (mono_class_need_stelemref_method (klass)) {
4133 stelemref_slot = cur_slot;
4138 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4140 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4141 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4144 max_iid = klass->max_interface_id;
4145 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4147 /* Optimized version for generic instances */
4148 if (mono_class_is_ginst (klass)) {
4150 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4153 mono_class_setup_vtable_full (gklass, in_setup);
4154 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Could not load generic definition"))
4157 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4158 klass->vtable_size = gklass->vtable_size;
4159 for (i = 0; i < gklass->vtable_size; ++i)
4160 if (gklass->vtable [i]) {
4161 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4162 if (!mono_error_ok (&error)) {
4163 mono_class_set_type_load_failure (klass, "Could not inflate method due to %s", mono_error_get_message (&error));
4164 mono_error_cleanup (&error);
4168 tmp [i]->slot = gklass->vtable [i]->slot;
4170 mono_memory_barrier ();
4171 klass->vtable = tmp;
4173 /* Have to set method->slot for abstract virtual methods */
4174 if (klass->methods && gklass->methods) {
4175 int mcount = mono_class_get_method_count (klass);
4176 for (i = 0; i < mcount; ++i)
4177 if (klass->methods [i]->slot == -1)
4178 klass->methods [i]->slot = gklass->methods [i]->slot;
4184 vtable = (MonoMethod **)g_malloc0 (sizeof (gpointer) * max_vtsize);
4186 if (klass->parent && klass->parent->vtable_size) {
4187 MonoClass *parent = klass->parent;
4190 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4192 // Also inherit parent interface vtables, just as a starting point.
4193 // This is needed otherwise bug-77127.exe fails when the property methods
4194 // have different names in the iterface and the class, because for child
4195 // classes the ".override" information is not used anymore.
4196 for (i = 0; i < parent->interface_offsets_count; i++) {
4197 MonoClass *parent_interface = parent->interfaces_packed [i];
4198 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4199 /*FIXME this is now dead code as this condition will never hold true.
4200 Since interface offsets are inherited then the offset of an interface implemented
4201 by a parent will never be the out of it's vtable boundary.
4203 if (interface_offset >= parent->vtable_size) {
4204 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4207 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4208 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4209 int mcount = mono_class_get_method_count (parent_interface);
4210 for (j = 0; j < mcount && !mono_class_has_failure (klass); j++) {
4211 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4212 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4213 parent_interface_offset + j, parent_interface_offset, j,
4214 interface_offset + j, interface_offset, j));
4221 /*Array have a slot for stelemref*/
4222 if (mono_class_need_stelemref_method (klass)) {
4223 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4225 method->slot = stelemref_slot;
4227 g_assert (method->slot == stelemref_slot);
4229 vtable [stelemref_slot] = method;
4232 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4234 /* Process overrides from interface default methods */
4235 // FIXME: Ordering between interfaces
4236 for (int ifindex = 0; ifindex < klass->interface_offsets_count; ifindex++) {
4237 ic = klass->interfaces_packed [ifindex];
4239 mono_class_setup_methods (ic);
4240 if (mono_class_has_failure (ic))
4243 MonoMethod **iface_overrides;
4245 gboolean ok = mono_class_get_overrides_full (ic->image, ic->type_token, &iface_overrides, &iface_onum, mono_class_get_context (ic));
4247 for (int i = 0; i < iface_onum; i++) {
4248 MonoMethod *decl = iface_overrides [i*2];
4249 MonoMethod *override = iface_overrides [i*2 + 1];
4250 if (!apply_override (klass, vtable, decl, override))
4254 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4255 g_hash_table_insert (override_map, decl, override);
4257 g_free (iface_overrides);
4261 /* override interface methods */
4262 for (i = 0; i < onum; i++) {
4263 MonoMethod *decl = overrides [i*2];
4264 MonoMethod *override = overrides [i*2 + 1];
4265 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4266 if (!apply_override (klass, vtable, decl, override))
4270 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4271 g_hash_table_insert (override_map, decl, override);
4275 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4276 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4279 * Create a list of virtual methods to avoid calling
4280 * mono_class_get_virtual_methods () which is slow because of the metadata
4284 gpointer iter = NULL;
4287 virt_methods = NULL;
4288 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4289 virt_methods = g_slist_prepend (virt_methods, cm);
4291 if (mono_class_has_failure (klass))
4295 // Loop on all implemented interfaces...
4296 for (i = 0; i < klass->interface_offsets_count; i++) {
4297 MonoClass *parent = klass->parent;
4299 gboolean interface_is_explicitly_implemented_by_class;
4302 ic = klass->interfaces_packed [i];
4303 ic_offset = mono_class_interface_offset (klass, ic);
4305 mono_class_setup_methods (ic);
4306 if (mono_class_has_failure (ic))
4309 // Check if this interface is explicitly implemented (instead of just inherited)
4310 if (parent != NULL) {
4311 int implemented_interfaces_index;
4312 interface_is_explicitly_implemented_by_class = FALSE;
4313 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4314 if (ic == klass->interfaces [implemented_interfaces_index]) {
4315 interface_is_explicitly_implemented_by_class = TRUE;
4320 interface_is_explicitly_implemented_by_class = TRUE;
4323 // Loop on all interface methods...
4324 int mcount = mono_class_get_method_count (ic);
4325 for (im_index = 0; im_index < mcount; im_index++) {
4326 MonoMethod *im = ic->methods [im_index];
4327 int im_slot = ic_offset + im->slot;
4328 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4330 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4333 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4335 // If there is an explicit implementation, just use it right away,
4336 // otherwise look for a matching method
4337 if (override_im == NULL) {
4341 // First look for a suitable method among the class methods
4342 for (l = virt_methods; l; l = l->next) {
4343 cm = (MonoMethod *)l->data;
4344 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)));
4345 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4346 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4347 vtable [im_slot] = cm;
4348 /* Why do we need this? */
4353 TRACE_INTERFACE_VTABLE (printf ("\n"));
4354 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4358 // If the slot is still empty, look in all the inherited virtual methods...
4359 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4360 MonoClass *parent = klass->parent;
4361 // Reverse order, so that last added methods are preferred
4362 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4363 MonoMethod *cm = parent->vtable [cm_index];
4365 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));
4366 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4367 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4368 vtable [im_slot] = cm;
4369 /* Why do we need this? */
4375 if (mono_class_has_failure (klass)) /*Might be set by check_interface_method_override*/
4377 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4381 if (vtable [im_slot] == NULL) {
4382 if (!(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
4383 TRACE_INTERFACE_VTABLE (printf (" Using default iface method %s.\n", mono_method_full_name (im, 1)));
4384 vtable [im_slot] = im;
4388 g_assert (vtable [im_slot] == override_im);
4393 // If the class is not abstract, check that all its interface slots are full.
4394 // The check is done here and not directly at the end of the loop above because
4395 // it can happen (for injected generic array interfaces) that the same slot is
4396 // processed multiple times (those interfaces have overlapping slots), and it
4397 // will not always be the first pass the one that fills the slot.
4398 if (!mono_class_is_abstract (klass)) {
4399 for (i = 0; i < klass->interface_offsets_count; i++) {
4403 ic = klass->interfaces_packed [i];
4404 ic_offset = mono_class_interface_offset (klass, ic);
4406 int mcount = mono_class_get_method_count (ic);
4407 for (im_index = 0; im_index < mcount; im_index++) {
4408 MonoMethod *im = ic->methods [im_index];
4409 int im_slot = ic_offset + im->slot;
4411 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4414 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4415 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4416 if (vtable [im_slot] == NULL) {
4417 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4424 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4425 for (l = virt_methods; l; l = l->next) {
4426 cm = (MonoMethod *)l->data;
4428 * If the method is REUSE_SLOT, we must check in the
4429 * base class for a method to override.
4431 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4433 for (k = klass->parent; k ; k = k->parent) {
4438 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4439 MonoMethodSignature *cmsig, *m1sig;
4441 cmsig = mono_method_signature (cm);
4442 m1sig = mono_method_signature (m1);
4444 if (!cmsig || !m1sig) {
4445 /* FIXME proper error message */
4446 mono_class_set_type_load_failure (klass, "");
4450 if (!strcmp(cm->name, m1->name) &&
4451 mono_metadata_signature_equal (cmsig, m1sig)) {
4453 if (mono_security_core_clr_enabled ())
4454 mono_security_core_clr_check_override (klass, cm, m1);
4456 slot = mono_method_get_vtable_slot (m1);
4460 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4461 char *body_name = mono_method_full_name (cm, TRUE);
4462 char *decl_name = mono_method_full_name (m1, TRUE);
4463 mono_class_set_type_load_failure (klass, "Method %s overrides method '%s' which is not accessible", body_name, decl_name);
4469 g_assert (cm->slot < max_vtsize);
4471 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4472 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4473 mono_method_full_name (m1, 1), m1,
4474 mono_method_full_name (cm, 1), cm));
4475 g_hash_table_insert (override_map, m1, cm);
4479 if (mono_class_has_failure (k))
4489 /*Non final newslot methods must be given a non-interface vtable slot*/
4490 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4494 cm->slot = cur_slot++;
4496 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4497 vtable [cm->slot] = cm;
4500 /* override non interface methods */
4501 for (i = 0; i < onum; i++) {
4502 MonoMethod *decl = overrides [i*2];
4503 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4504 g_assert (decl->slot != -1);
4505 vtable [decl->slot] = overrides [i*2 + 1];
4506 overrides [i * 2 + 1]->slot = decl->slot;
4508 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4509 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4510 mono_method_full_name (decl, 1), decl,
4511 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4512 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4514 if (mono_security_core_clr_enabled ())
4515 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4520 * If a method occupies more than one place in the vtable, and it is
4521 * overriden, then change the other occurances too.
4526 for (i = 0; i < max_vtsize; ++i)
4528 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4530 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4535 g_hash_table_destroy (override_map);
4536 override_map = NULL;
4539 g_slist_free (virt_methods);
4540 virt_methods = NULL;
4542 g_assert (cur_slot <= max_vtsize);
4544 /* Ensure that all vtable slots are filled with concrete instance methods */
4545 if (!mono_class_is_abstract (klass)) {
4546 for (i = 0; i < cur_slot; ++i) {
4547 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4548 char *type_name = mono_type_get_full_name (klass);
4549 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4550 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4552 g_free (method_name);
4559 if (mono_class_is_ginst (klass)) {
4560 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4562 mono_class_init (gklass);
4564 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4566 /* Check that the vtable_size value computed in mono_class_init () is correct */
4567 if (klass->vtable_size)
4568 g_assert (cur_slot == klass->vtable_size);
4569 klass->vtable_size = cur_slot;
4572 /* Try to share the vtable with our parent. */
4573 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4574 mono_memory_barrier ();
4575 klass->vtable = klass->parent->vtable;
4577 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4578 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4579 mono_memory_barrier ();
4580 klass->vtable = tmp;
4583 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4584 if (mono_print_vtable) {
4587 print_implemented_interfaces (klass);
4589 for (i = 0; i <= max_iid; i++)
4590 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4593 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4594 klass->vtable_size, icount);
4596 for (i = 0; i < cur_slot; ++i) {
4601 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4602 mono_method_full_name (cm, TRUE));
4608 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4609 klass->name, max_iid);
4611 for (i = 0; i < klass->interface_count; i++) {
4612 ic = klass->interfaces [i];
4613 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4614 mono_class_interface_offset (klass, ic),
4615 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4618 for (k = klass->parent; k ; k = k->parent) {
4619 for (i = 0; i < k->interface_count; i++) {
4620 ic = k->interfaces [i];
4621 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4622 mono_class_interface_offset (klass, ic),
4623 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4631 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4636 char *name = mono_type_get_full_name (klass);
4637 mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4641 g_hash_table_destroy (override_map);
4643 g_slist_free (virt_methods);
4648 * mono_method_get_vtable_slot:
4650 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4651 * LOCKING: Acquires the loader lock.
4653 * FIXME Use proper MonoError machinery here.
4656 mono_method_get_vtable_slot (MonoMethod *method)
4658 if (method->slot == -1) {
4659 mono_class_setup_vtable (method->klass);
4660 if (mono_class_has_failure (method->klass))
4662 if (method->slot == -1) {
4666 if (!mono_class_is_ginst (method->klass)) {
4667 g_assert (method->is_inflated);
4668 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4671 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4672 g_assert (mono_class_is_ginst (method->klass));
4673 gklass = mono_class_get_generic_class (method->klass)->container_class;
4674 mono_class_setup_methods (method->klass);
4675 g_assert (method->klass->methods);
4676 mcount = mono_class_get_method_count (method->klass);
4677 for (i = 0; i < mcount; ++i) {
4678 if (method->klass->methods [i] == method)
4681 g_assert (i < mcount);
4682 g_assert (gklass->methods);
4683 method->slot = gklass->methods [i]->slot;
4685 g_assert (method->slot != -1);
4687 return method->slot;
4691 * mono_method_get_vtable_index:
4692 * \param method a method
4694 * Returns the index into the runtime vtable to access the method or,
4695 * in the case of a virtual generic method, the virtual generic method
4696 * thunk. Returns -1 on failure.
4698 * FIXME Use proper MonoError machinery here.
4701 mono_method_get_vtable_index (MonoMethod *method)
4703 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4704 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4705 if (imethod->declaring->is_generic)
4706 return mono_method_get_vtable_slot (imethod->declaring);
4708 return mono_method_get_vtable_slot (method);
4711 static MonoMethod *default_ghc = NULL;
4712 static MonoMethod *default_finalize = NULL;
4713 static int finalize_slot = -1;
4714 static int ghc_slot = -1;
4717 initialize_object_slots (MonoClass *klass)
4722 if (klass == mono_defaults.object_class) {
4723 mono_class_setup_vtable (klass);
4724 for (i = 0; i < klass->vtable_size; ++i) {
4725 MonoMethod *cm = klass->vtable [i];
4727 if (!strcmp (cm->name, "GetHashCode"))
4729 else if (!strcmp (cm->name, "Finalize"))
4733 g_assert (ghc_slot > 0);
4734 default_ghc = klass->vtable [ghc_slot];
4736 g_assert (finalize_slot > 0);
4737 default_finalize = klass->vtable [finalize_slot];
4742 MonoMethod *array_method;
4744 } GenericArrayMethodInfo;
4746 static int generic_array_method_num = 0;
4747 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4750 generic_array_methods (MonoClass *klass)
4752 int i, count_generic = 0, mcount;
4753 GList *list = NULL, *tmp;
4754 if (generic_array_method_num)
4755 return generic_array_method_num;
4756 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4757 g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4758 mcount = mono_class_get_method_count (klass->parent);
4759 for (i = 0; i < mcount; i++) {
4760 MonoMethod *m = klass->parent->methods [i];
4761 if (!strncmp (m->name, "InternalArray__", 15)) {
4763 list = g_list_prepend (list, m);
4766 list = g_list_reverse (list);
4767 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4769 for (tmp = list; tmp; tmp = tmp->next) {
4770 const char *mname, *iname;
4772 MonoMethod *m = (MonoMethod *)tmp->data;
4773 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4774 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4776 generic_array_method_info [i].array_method = m;
4777 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4778 iname = "System.Collections.Generic.ICollection`1.";
4779 mname = m->name + 27;
4780 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4781 iname = "System.Collections.Generic.IEnumerable`1.";
4782 mname = m->name + 27;
4783 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4784 iname = "System.Collections.Generic.IReadOnlyList`1.";
4785 mname = m->name + strlen (ireadonlylist_prefix);
4786 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4787 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4788 mname = m->name + strlen (ireadonlycollection_prefix);
4789 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4790 iname = "System.Collections.Generic.IList`1.";
4791 mname = m->name + 15;
4793 g_assert_not_reached ();
4796 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4797 strcpy (name, iname);
4798 strcpy (name + strlen (iname), mname);
4799 generic_array_method_info [i].name = name;
4802 /*g_print ("array generic methods: %d\n", count_generic);*/
4804 generic_array_method_num = count_generic;
4806 return generic_array_method_num;
4810 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos, GHashTable *cache)
4812 MonoGenericContext tmp_context;
4815 tmp_context.class_inst = NULL;
4816 tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4817 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4819 for (i = 0; i < generic_array_method_num; i++) {
4821 MonoMethod *m = generic_array_method_info [i].array_method;
4822 MonoMethod *inflated, *helper;
4824 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4825 mono_error_assert_ok (&error);
4826 helper = g_hash_table_lookup (cache, inflated);
4828 helper = mono_marshal_get_generic_array_helper (klass, generic_array_method_info [i].name, inflated);
4829 g_hash_table_insert (cache, inflated, helper);
4831 methods [pos ++] = helper;
4836 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4838 int null_length = strlen ("(null)");
4839 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4840 char *s = (char *)mono_image_alloc (image, len);
4843 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4844 g_assert (result == len - 1);
4851 * \param klass the class to initialize
4853 * Compute the \c instance_size, \c class_size and other infos that cannot be
4854 * computed at \c mono_class_get time. Also compute vtable_size if possible.
4855 * Initializes the following fields in \p klass:
4856 * - all the fields initialized by \c mono_class_init_sizes
4861 * LOCKING: Acquires the loader lock.
4863 * \returns TRUE on success or FALSE if there was a problem in loading
4864 * the type (incorrect assemblies, missing assemblies, methods, etc).
4867 mono_class_init (MonoClass *klass)
4869 int i, vtable_size = 0, array_method_count = 0;
4870 MonoCachedClassInfo cached_info;
4871 gboolean has_cached_info;
4872 gboolean locked = FALSE;
4873 gboolean ghcimpl = FALSE;
4874 gboolean has_cctor = FALSE;
4875 int first_iface_slot = 0;
4879 /* Double-checking locking pattern */
4880 if (klass->inited || mono_class_has_failure (klass))
4881 return !mono_class_has_failure (klass);
4883 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4886 * This function can recursively call itself.
4888 GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4889 if (g_slist_find (init_list, klass)) {
4890 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4891 goto leave_no_init_pending;
4893 init_list = g_slist_prepend (init_list, klass);
4894 mono_native_tls_set_value (init_pending_tls_id, init_list);
4897 * We want to avoid doing complicated work inside locks, so we compute all the required
4898 * information and write it to @klass inside a lock.
4901 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4902 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4906 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4907 MonoClass *element_class = klass->element_class;
4908 if (!element_class->inited)
4909 mono_class_init (element_class);
4910 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4914 UnlockedIncrement (&mono_stats.initialized_class_count);
4916 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4917 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4919 mono_class_init (gklass);
4920 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4923 mono_class_setup_interface_id (klass);
4926 if (klass->parent && !klass->parent->inited)
4927 mono_class_init (klass->parent);
4929 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4931 /* Compute instance size etc. */
4932 init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4933 if (mono_class_has_failure (klass))
4936 mono_class_setup_supertypes (klass);
4939 initialize_object_slots (klass);
4942 * Initialize the rest of the data without creating a generic vtable if possible.
4943 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4944 * also avoid computing a generic vtable.
4946 if (has_cached_info) {
4948 vtable_size = cached_info.vtable_size;
4949 ghcimpl = cached_info.ghcimpl;
4950 has_cctor = cached_info.has_cctor;
4951 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4952 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4953 * The first slot if for array with.
4955 static int szarray_vtable_size[2] = { 0 };
4957 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4960 if (!szarray_vtable_size [slot]) {
4961 mono_class_setup_vtable (klass);
4962 szarray_vtable_size [slot] = klass->vtable_size;
4963 vtable_size = klass->vtable_size;
4965 vtable_size = szarray_vtable_size[slot];
4967 } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4968 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4970 /* Generic instance case */
4971 ghcimpl = gklass->ghcimpl;
4972 has_cctor = gklass->has_cctor;
4974 mono_class_setup_vtable (gklass);
4975 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4978 vtable_size = gklass->vtable_size;
4982 /* ghcimpl is not currently used
4984 if (klass->parent) {
4985 MonoMethod *cmethod = klass->vtable [ghc_slot];
4986 if (cmethod->is_inflated)
4987 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4988 if (cmethod == default_ghc) {
4994 /* C# doesn't allow interfaces to have cctors */
4995 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4996 MonoMethod *cmethod = NULL;
4998 if (mono_class_is_ginst (klass)) {
4999 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5001 /* Generic instance case */
5002 ghcimpl = gklass->ghcimpl;
5003 has_cctor = gklass->has_cctor;
5004 } else if (klass->type_token && !image_is_dynamic(klass->image)) {
5005 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5006 /* The find_method function ignores the 'flags' argument */
5007 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5010 mono_class_setup_methods (klass);
5011 if (mono_class_has_failure (klass))
5014 int mcount = mono_class_get_method_count (klass);
5015 for (i = 0; i < mcount; ++i) {
5016 MonoMethod *method = klass->methods [i];
5017 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5018 (strcmp (".cctor", method->name) == 0)) {
5028 array_method_count = 3 + (klass->rank > 1? 2: 1);
5030 if (klass->interface_count) {
5031 int count_generic = generic_array_methods (klass);
5032 array_method_count += klass->interface_count * count_generic;
5036 if (klass->parent) {
5037 if (!klass->parent->vtable_size)
5038 mono_class_setup_vtable (klass->parent);
5039 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5041 g_assert (klass->parent->vtable_size);
5042 first_iface_slot = klass->parent->vtable_size;
5043 if (mono_class_need_stelemref_method (klass))
5048 * Do the actual changes to @klass inside the loader lock
5050 mono_loader_lock ();
5053 if (klass->inited || mono_class_has_failure (klass)) {
5054 mono_loader_unlock ();
5055 /* Somebody might have gotten in before us */
5056 return !mono_class_has_failure (klass);
5059 UnlockedIncrement (&mono_stats.initialized_class_count);
5061 if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5062 UnlockedIncrement (&mono_stats.generic_class_count);
5064 if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5065 klass->nested_classes_inited = TRUE;
5066 klass->ghcimpl = ghcimpl;
5067 klass->has_cctor = has_cctor;
5069 klass->vtable_size = vtable_size;
5070 if (has_cached_info) {
5071 klass->has_finalize = cached_info.has_finalize;
5072 klass->has_finalize_inited = TRUE;
5075 mono_class_set_method_count (klass, array_method_count);
5077 mono_loader_unlock ();
5080 setup_interface_offsets (klass, first_iface_slot, TRUE);
5082 if (mono_security_core_clr_enabled ())
5083 mono_security_core_clr_check_inheritance (klass);
5085 if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5086 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5091 init_list = mono_native_tls_get_value (init_pending_tls_id);
5092 init_list = g_slist_remove (init_list, klass);
5093 mono_native_tls_set_value (init_pending_tls_id, init_list);
5095 leave_no_init_pending:
5097 mono_loader_unlock ();
5099 /* Leave this for last */
5100 mono_loader_lock ();
5102 mono_loader_unlock ();
5104 return !mono_class_has_failure (klass);
5108 * mono_class_has_finalizer:
5110 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5114 mono_class_has_finalizer (MonoClass *klass)
5116 gboolean has_finalize = FALSE;
5118 if (klass->has_finalize_inited)
5119 return klass->has_finalize;
5121 /* Interfaces and valuetypes are not supposed to have finalizers */
5122 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5123 MonoMethod *cmethod = NULL;
5125 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5126 } else if (mono_class_is_ginst (klass)) {
5127 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5129 has_finalize = mono_class_has_finalizer (gklass);
5130 } else if (klass->parent && klass->parent->has_finalize) {
5131 has_finalize = TRUE;
5133 if (klass->parent) {
5135 * Can't search in metadata for a method named Finalize, because that
5136 * ignores overrides.
5138 mono_class_setup_vtable (klass);
5139 if (mono_class_has_failure (klass))
5142 cmethod = klass->vtable [finalize_slot];
5146 g_assert (klass->vtable_size > finalize_slot);
5148 if (klass->parent) {
5149 if (cmethod->is_inflated)
5150 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5151 if (cmethod != default_finalize)
5152 has_finalize = TRUE;
5158 mono_loader_lock ();
5159 if (!klass->has_finalize_inited) {
5160 klass->has_finalize = has_finalize ? 1 : 0;
5162 mono_memory_barrier ();
5163 klass->has_finalize_inited = TRUE;
5165 mono_loader_unlock ();
5167 return klass->has_finalize;
5171 mono_is_corlib_image (MonoImage *image)
5173 return image == mono_defaults.corlib;
5177 * LOCKING: this assumes the loader lock is held
5180 mono_class_setup_mono_type (MonoClass *klass)
5182 const char *name = klass->name;
5183 const char *nspace = klass->name_space;
5184 gboolean is_corlib = mono_is_corlib_image (klass->image);
5186 klass->this_arg.byref = 1;
5187 klass->this_arg.data.klass = klass;
5188 klass->this_arg.type = MONO_TYPE_CLASS;
5189 klass->byval_arg.data.klass = klass;
5190 klass->byval_arg.type = MONO_TYPE_CLASS;
5192 if (is_corlib && !strcmp (nspace, "System")) {
5193 if (!strcmp (name, "ValueType")) {
5195 * do not set the valuetype bit for System.ValueType.
5196 * klass->valuetype = 1;
5198 klass->blittable = TRUE;
5199 } else if (!strcmp (name, "Enum")) {
5201 * do not set the valuetype bit for System.Enum.
5202 * klass->valuetype = 1;
5204 klass->valuetype = 0;
5205 klass->enumtype = 0;
5206 } else if (!strcmp (name, "Object")) {
5207 klass->byval_arg.type = MONO_TYPE_OBJECT;
5208 klass->this_arg.type = MONO_TYPE_OBJECT;
5209 } else if (!strcmp (name, "String")) {
5210 klass->byval_arg.type = MONO_TYPE_STRING;
5211 klass->this_arg.type = MONO_TYPE_STRING;
5212 } else if (!strcmp (name, "TypedReference")) {
5213 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5214 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5218 if (klass->valuetype) {
5219 int t = MONO_TYPE_VALUETYPE;
5221 if (is_corlib && !strcmp (nspace, "System")) {
5224 if (!strcmp (name, "Boolean")) {
5225 t = MONO_TYPE_BOOLEAN;
5226 } else if (!strcmp(name, "Byte")) {
5228 klass->blittable = TRUE;
5232 if (!strcmp (name, "Char")) {
5237 if (!strcmp (name, "Double")) {
5239 klass->blittable = TRUE;
5243 if (!strcmp (name, "Int32")) {
5245 klass->blittable = TRUE;
5246 } else if (!strcmp(name, "Int16")) {
5248 klass->blittable = TRUE;
5249 } else if (!strcmp(name, "Int64")) {
5251 klass->blittable = TRUE;
5252 } else if (!strcmp(name, "IntPtr")) {
5254 klass->blittable = TRUE;
5258 if (!strcmp (name, "Single")) {
5260 klass->blittable = TRUE;
5261 } else if (!strcmp(name, "SByte")) {
5263 klass->blittable = TRUE;
5267 if (!strcmp (name, "UInt32")) {
5269 klass->blittable = TRUE;
5270 } else if (!strcmp(name, "UInt16")) {
5272 klass->blittable = TRUE;
5273 } else if (!strcmp(name, "UInt64")) {
5275 klass->blittable = TRUE;
5276 } else if (!strcmp(name, "UIntPtr")) {
5278 klass->blittable = TRUE;
5282 if (!strcmp (name, "TypedReference")) {
5283 t = MONO_TYPE_TYPEDBYREF;
5284 klass->blittable = TRUE;
5288 if (!strcmp (name, "Void")) {
5296 klass->byval_arg.type = (MonoTypeEnum)t;
5297 klass->this_arg.type = (MonoTypeEnum)t;
5300 if (MONO_CLASS_IS_INTERFACE (klass)) {
5301 klass->interface_id = mono_get_unique_iid (klass);
5303 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5304 //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5305 /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5306 * MS returns diferrent types based on which instance is called. For example:
5307 * object obj = new byte[10][];
5308 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5309 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5312 if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5313 klass->is_array_special_interface = 1;
5320 * COM initialization is delayed until needed.
5321 * However when a [ComImport] attribute is present on a type it will trigger
5322 * the initialization. This is not a problem unless the BCL being executed
5323 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5326 init_com_from_comimport (MonoClass *klass)
5328 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5329 if (mono_security_core_clr_enabled ()) {
5330 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5331 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5332 /* but it can not be made available for application (i.e. user code) since all COM calls
5333 * are considered native calls. In this case we fail with a TypeLoadException (just like
5334 * Silverlight 2 does */
5335 mono_class_set_type_load_failure (klass, "");
5340 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5342 #endif /*DISABLE_COM*/
5345 * LOCKING: this assumes the loader lock is held
5348 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5350 gboolean system_namespace;
5351 gboolean is_corlib = mono_is_corlib_image (klass->image);
5353 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5355 /* if root of the hierarchy */
5356 if (system_namespace && !strcmp (klass->name, "Object")) {
5357 klass->parent = NULL;
5358 klass->instance_size = sizeof (MonoObject);
5361 if (!strcmp (klass->name, "<Module>")) {
5362 klass->parent = NULL;
5363 klass->instance_size = 0;
5367 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5368 /* Imported COM Objects always derive from __ComObject. */
5370 if (MONO_CLASS_IS_IMPORT (klass)) {
5371 init_com_from_comimport (klass);
5372 if (parent == mono_defaults.object_class)
5373 parent = mono_class_get_com_object_class ();
5377 /* set the parent to something useful and safe, but mark the type as broken */
5378 parent = mono_defaults.object_class;
5379 mono_class_set_type_load_failure (klass, "");
5383 klass->parent = parent;
5385 if (mono_class_is_ginst (parent) && !parent->name) {
5387 * If the parent is a generic instance, we may get
5388 * called before it is fully initialized, especially
5389 * before it has its name.
5394 #ifndef DISABLE_REMOTING
5395 klass->marshalbyref = parent->marshalbyref;
5396 klass->contextbound = parent->contextbound;
5399 klass->delegate = parent->delegate;
5401 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5402 mono_class_set_is_com_object (klass);
5404 if (system_namespace) {
5405 #ifndef DISABLE_REMOTING
5406 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5407 klass->marshalbyref = 1;
5409 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5410 klass->contextbound = 1;
5412 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5413 klass->delegate = 1;
5416 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5417 (strcmp (klass->parent->name_space, "System") == 0)))
5418 klass->valuetype = 1;
5419 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5420 klass->valuetype = klass->enumtype = 1;
5422 /*klass->enumtype = klass->parent->enumtype; */
5424 /* initialize com types if COM interfaces are present */
5426 if (MONO_CLASS_IS_IMPORT (klass))
5427 init_com_from_comimport (klass);
5429 klass->parent = NULL;
5435 * mono_class_setup_supertypes:
5438 * Build the data structure needed to make fast type checks work.
5439 * This currently sets two fields in @class:
5440 * - idepth: distance between @class and System.Object in the type
5442 * - supertypes: array of classes: each element has a class in the hierarchy
5443 * starting from @class up to System.Object
5445 * LOCKING: Acquires the loader lock.
5448 mono_class_setup_supertypes (MonoClass *klass)
5451 MonoClass **supertypes;
5453 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5457 if (klass->parent && !klass->parent->supertypes)
5458 mono_class_setup_supertypes (klass->parent);
5460 idepth = klass->parent->idepth + 1;
5464 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5465 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5467 if (klass->parent) {
5468 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5471 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5472 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5474 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5477 mono_memory_barrier ();
5479 mono_loader_lock ();
5480 klass->idepth = idepth;
5481 /* Needed so idepth is visible before supertypes is set */
5482 mono_memory_barrier ();
5483 klass->supertypes = supertypes;
5484 mono_loader_unlock ();
5488 discard_gclass_due_to_failure (MonoClass *gclass, void *user_data)
5490 return mono_class_get_generic_class (gclass)->container_class == user_data;
5494 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5496 MonoClass *gtd = (MonoClass*)user_data;
5497 /* Only try to fix generic instances of @gtd */
5498 if (mono_class_get_generic_class (gclass)->container_class != gtd)
5501 /* Check if the generic instance has no parent. */
5502 if (gtd->parent && !gclass->parent)
5503 mono_generic_class_setup_parent (gclass, gtd);
5509 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5511 mono_class_set_type_load_failure (klass, "%s", msg);
5512 mono_error_set_type_load_class (error, klass, "%s", msg);
5516 * mono_class_create_from_typedef:
5517 * \param image: image where the token is valid
5518 * \param type_token: typedef token
5519 * \param error: used to return any error found while creating the type
5521 * Create the MonoClass* representing the specified type token.
5522 * \p type_token must be a TypeDef token.
5524 * FIXME: don't return NULL on failure, just let the caller figure it out.
5527 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5529 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5530 MonoClass *klass, *parent = NULL;
5531 guint32 cols [MONO_TYPEDEF_SIZE];
5532 guint32 cols_next [MONO_TYPEDEF_SIZE];
5533 guint tidx = mono_metadata_token_index (type_token);
5534 MonoGenericContext *context = NULL;
5535 const char *name, *nspace;
5537 MonoClass **interfaces;
5538 guint32 field_last, method_last;
5539 guint32 nesting_tokeen;
5543 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5544 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5548 mono_loader_lock ();
5550 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5551 mono_loader_unlock ();
5555 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5557 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5558 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5560 if (mono_metadata_has_generic_params (image, type_token)) {
5561 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5562 klass->class_kind = MONO_CLASS_GTD;
5563 UnlockedAdd (&classes_size, sizeof (MonoClassGtd));
5566 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5567 klass->class_kind = MONO_CLASS_DEF;
5568 UnlockedAdd (&classes_size, sizeof (MonoClassDef));
5573 klass->name_space = nspace;
5575 MONO_PROFILER_RAISE (class_loading, (klass));
5577 klass->image = image;
5578 klass->type_token = type_token;
5579 mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5581 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5584 * Check whether we're a generic type definition.
5586 if (mono_class_is_gtd (klass)) {
5587 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5588 generic_container->owner.klass = klass;
5589 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5590 context = &generic_container->context;
5591 mono_class_set_generic_container (klass, generic_container);
5592 MonoType *canonical_inst = &((MonoClassGtd*)klass)->canonical_inst;
5593 canonical_inst->type = MONO_TYPE_GENERICINST;
5594 canonical_inst->data.generic_class = mono_metadata_lookup_generic_class (klass, context->class_inst, FALSE);
5595 enable_gclass_recording ();
5598 if (cols [MONO_TYPEDEF_EXTENDS]) {
5600 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5602 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5603 /*WARNING: this must satisfy mono_metadata_type_hash*/
5604 klass->this_arg.byref = 1;
5605 klass->this_arg.data.klass = klass;
5606 klass->this_arg.type = MONO_TYPE_CLASS;
5607 klass->byval_arg.data.klass = klass;
5608 klass->byval_arg.type = MONO_TYPE_CLASS;
5610 parent = mono_class_get_checked (image, parent_token, error);
5611 if (parent && context) /* Always inflate */
5612 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5614 if (parent == NULL) {
5615 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5616 goto parent_failure;
5619 for (tmp = parent; tmp; tmp = tmp->parent) {
5621 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5622 goto parent_failure;
5624 if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5625 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5626 goto parent_failure;
5631 mono_class_setup_parent (klass, parent);
5633 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5634 mono_class_setup_mono_type (klass);
5636 if (mono_class_is_gtd (klass))
5637 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5640 * This might access klass->byval_arg for recursion generated by generic constraints,
5641 * so it has to come after setup_mono_type ().
5643 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5644 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5645 if (!mono_error_ok (error)) {
5646 /*FIXME implement a mono_class_set_failure_from_mono_error */
5647 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5648 mono_loader_unlock ();
5649 MONO_PROFILER_RAISE (class_failed, (klass));
5654 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5658 if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5662 klass->cast_class = klass->element_class = klass;
5663 if (mono_is_corlib_image (klass->image)) {
5664 switch (klass->byval_arg.type) {
5666 if (mono_defaults.byte_class)
5667 klass->cast_class = mono_defaults.byte_class;
5670 if (mono_defaults.sbyte_class)
5671 mono_defaults.sbyte_class = klass;
5674 if (mono_defaults.uint16_class)
5675 mono_defaults.uint16_class = klass;
5678 if (mono_defaults.int16_class)
5679 klass->cast_class = mono_defaults.int16_class;
5682 if (mono_defaults.uint32_class)
5683 mono_defaults.uint32_class = klass;
5686 if (mono_defaults.int32_class)
5687 klass->cast_class = mono_defaults.int32_class;
5690 if (mono_defaults.uint64_class)
5691 mono_defaults.uint64_class = klass;
5694 if (mono_defaults.int64_class)
5695 klass->cast_class = mono_defaults.int64_class;
5700 if (!klass->enumtype) {
5701 if (!mono_metadata_interfaces_from_typedef_full (
5702 image, type_token, &interfaces, &icount, FALSE, context, error)){
5704 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5705 mono_loader_unlock ();
5706 MONO_PROFILER_RAISE (class_failed, (klass));
5710 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5711 g_assert(icount <= 65535);
5713 klass->interfaces = interfaces;
5714 klass->interface_count = icount;
5715 klass->interfaces_inited = 1;
5718 /*g_print ("Load class %s\n", name);*/
5721 * Compute the field and method lists
5723 int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5724 mono_class_set_first_field_idx (klass, first_field_idx);
5725 int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5726 mono_class_set_first_method_idx (klass, first_method_idx);
5728 if (tt->rows > tidx){
5729 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5730 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5731 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5733 field_last = image->tables [MONO_TABLE_FIELD].rows;
5734 method_last = image->tables [MONO_TABLE_METHOD].rows;
5737 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5738 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5739 mono_class_set_field_count (klass, field_last - first_field_idx);
5740 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5741 mono_class_set_method_count (klass, method_last - first_method_idx);
5743 /* reserve space to store vector pointer in arrays */
5744 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5745 klass->instance_size += 2 * sizeof (gpointer);
5746 g_assert (mono_class_get_field_count (klass) == 0);
5749 if (klass->enumtype) {
5750 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5751 if (!enum_basetype) {
5752 /*set it to a default value as the whole runtime can't handle this to be null*/
5753 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5754 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5755 mono_loader_unlock ();
5756 MONO_PROFILER_RAISE (class_failed, (klass));
5759 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5763 * If we're a generic type definition, load the constraints.
5764 * We must do this after the class has been constructed to make certain recursive scenarios
5767 if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5768 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5769 mono_loader_unlock ();
5770 MONO_PROFILER_RAISE (class_failed, (klass));
5774 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5775 if (!strncmp (name, "Vector", 6))
5776 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");
5777 } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5778 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5779 klass->simd_type = 1;
5782 mono_loader_unlock ();
5784 MONO_PROFILER_RAISE (class_loaded, (klass));
5789 if (mono_class_is_gtd (klass))
5790 disable_gclass_recording (discard_gclass_due_to_failure, klass);
5792 mono_class_setup_mono_type (klass);
5793 mono_loader_unlock ();
5794 MONO_PROFILER_RAISE (class_failed, (klass));
5798 /** Is klass a Nullable<T> ginst? */
5800 mono_class_is_nullable (MonoClass *klass)
5802 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5803 return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5807 /** if klass is T? return T */
5809 mono_class_get_nullable_param (MonoClass *klass)
5811 g_assert (mono_class_is_nullable (klass));
5812 return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5816 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5820 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5822 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5823 if (!mono_error_ok (&error)) {
5824 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5825 klass->parent = mono_defaults.object_class;
5826 mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5827 mono_error_cleanup (&error);
5830 mono_loader_lock ();
5832 mono_class_setup_parent (klass, klass->parent);
5834 if (klass->enumtype) {
5835 klass->cast_class = gtd->cast_class;
5836 klass->element_class = gtd->element_class;
5838 mono_loader_unlock ();
5842 mono_type_is_primitive (MonoType *type)
5844 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5845 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5849 * Create the `MonoClass' for an instantiation of a generic type.
5850 * We only do this if we actually need it.
5853 mono_generic_class_get_class (MonoGenericClass *gclass)
5855 MonoClass *klass, *gklass;
5857 if (gclass->cached_class)
5858 return gclass->cached_class;
5860 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5862 gklass = gclass->container_class;
5864 if (gklass->nested_in) {
5865 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5866 klass->nested_in = gklass->nested_in;
5869 klass->name = gklass->name;
5870 klass->name_space = gklass->name_space;
5872 klass->image = gklass->image;
5873 klass->type_token = gklass->type_token;
5875 klass->class_kind = MONO_CLASS_GINST;
5877 ((MonoClassGenericInst*)klass)->generic_class = gclass;
5879 klass->byval_arg.type = MONO_TYPE_GENERICINST;
5880 klass->this_arg.type = klass->byval_arg.type;
5881 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5882 klass->this_arg.byref = TRUE;
5883 klass->enumtype = gklass->enumtype;
5884 klass->valuetype = gklass->valuetype;
5887 if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5888 g_assert (gclass->context.class_inst);
5889 g_assert (gclass->context.class_inst->type_argc > 0);
5890 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5891 klass->simd_type = 1;
5893 klass->is_array_special_interface = gklass->is_array_special_interface;
5895 klass->cast_class = klass->element_class = klass;
5897 if (gclass->is_dynamic) {
5899 * 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.
5900 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5901 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5903 if (!gklass->wastypebuilder)
5906 if (klass->enumtype) {
5908 * For enums, gklass->fields might not been set, but instance_size etc. is
5909 * already set in mono_reflection_create_internal_class (). For non-enums,
5910 * these will be computed normally in mono_class_layout_fields ().
5912 klass->instance_size = gklass->instance_size;
5913 klass->sizes.class_size = gklass->sizes.class_size;
5914 klass->size_inited = 1;
5918 mono_loader_lock ();
5920 if (gclass->cached_class) {
5921 mono_loader_unlock ();
5922 return gclass->cached_class;
5925 if (record_gclass_instantiation > 0)
5926 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5928 if (mono_class_is_nullable (klass))
5929 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5931 MONO_PROFILER_RAISE (class_loading, (klass));
5933 mono_generic_class_setup_parent (klass, gklass);
5935 if (gclass->is_dynamic)
5936 mono_class_setup_supertypes (klass);
5938 mono_memory_barrier ();
5939 gclass->cached_class = klass;
5941 MONO_PROFILER_RAISE (class_loaded, (klass));
5943 ++class_ginst_count;
5944 inflated_classes_size += sizeof (MonoClassGenericInst);
5946 mono_loader_unlock ();
5952 get_image_for_container (MonoGenericContainer *container)
5955 if (container->is_anonymous) {
5956 result = container->owner.image;
5959 if (container->is_method) {
5960 MonoMethod *method = container->owner.method;
5961 g_assert_checked (method);
5962 klass = method->klass;
5964 klass = container->owner.klass;
5966 g_assert_checked (klass);
5967 result = klass->image;
5974 get_image_for_generic_param (MonoGenericParam *param)
5976 MonoGenericContainer *container = mono_generic_param_owner (param);
5977 g_assert_checked (container);
5978 return get_image_for_container (container);
5981 // Make a string in the designated image consisting of a single integer.
5982 #define INT_STRING_SIZE 16
5984 make_generic_name_string (MonoImage *image, int num)
5986 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5987 g_snprintf (name, INT_STRING_SIZE, "%d", num);
5991 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5992 // pinfo is derived from param by the caller for us.
5994 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5996 MonoClass *klass, **ptr;
5998 MonoGenericContainer *container = mono_generic_param_owner (param);
5999 g_assert_checked (container);
6001 MonoImage *image = get_image_for_container (container);
6002 gboolean is_mvar = container->is_method;
6003 gboolean is_anonymous = container->is_anonymous;
6005 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
6006 klass->class_kind = MONO_CLASS_GPARAM;
6007 UnlockedAdd (&classes_size, sizeof (MonoClassGenericParam));
6008 UnlockedIncrement (&class_gparam_count);
6011 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6013 int n = mono_generic_param_num (param);
6014 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6018 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6019 } else if (is_mvar) {
6020 MonoMethod *omethod = container->owner.method;
6021 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6023 MonoClass *oklass = container->owner.klass;
6024 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6027 MONO_PROFILER_RAISE (class_loading, (klass));
6029 // Count non-NULL items in pinfo->constraints
6032 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6036 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6037 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6039 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6040 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6042 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6045 if (count - pos > 0) {
6046 klass->interface_count = count - pos;
6047 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6048 klass->interfaces_inited = TRUE;
6049 for (i = pos; i < count; i++)
6050 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6053 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6055 klass->inited = TRUE;
6056 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6057 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6059 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6060 klass->this_arg.type = klass->byval_arg.type;
6061 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6062 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6063 klass->this_arg.byref = TRUE;
6065 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6066 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6068 /*Init these fields to sane values*/
6069 klass->min_align = 1;
6071 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6072 * constrained to, the JIT depends on this.
6074 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6075 mono_memory_barrier ();
6076 klass->size_inited = 1;
6078 mono_class_setup_supertypes (klass);
6080 if (count - pos > 0) {
6081 mono_class_setup_vtable (klass->parent);
6082 if (mono_class_has_failure (klass->parent))
6083 mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6085 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6091 #define FAST_CACHE_SIZE 16
6094 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6095 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6096 * we cache the MonoClasses.
6097 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6098 * LOCKING: Takes the image lock depending on @take_lock.
6101 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6103 int n = mono_generic_param_num (param);
6104 MonoImage *image = get_image_for_generic_param (param);
6105 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6106 MonoClass *klass = NULL;
6111 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6112 // For high numbers or constraints we have to use pointer hashes.
6113 if (param->gshared_constraint) {
6114 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6117 mono_image_lock (image);
6118 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6120 mono_image_unlock (image);
6125 if (n < FAST_CACHE_SIZE) {
6127 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6129 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6131 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6134 mono_image_lock (image);
6135 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6137 mono_image_unlock (image);
6144 * LOCKING: Image lock (param->image) must be held
6147 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6149 int n = mono_generic_param_num (param);
6150 MonoImage *image = get_image_for_generic_param (param);
6151 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6155 if (param->gshared_constraint) {
6156 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6158 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6159 mono_memory_barrier ();
6161 image->mvar_cache_constrained = ht;
6163 image->var_cache_constrained = ht;
6165 g_hash_table_insert (ht, param, klass);
6166 } else if (n < FAST_CACHE_SIZE) {
6168 /* Requires locking to avoid droping an already published class */
6169 if (!image->mvar_cache_fast)
6170 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6171 image->mvar_cache_fast [n] = klass;
6173 if (!image->var_cache_fast)
6174 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6175 image->var_cache_fast [n] = klass;
6178 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6180 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6182 ht = g_hash_table_new (NULL, NULL);
6183 mono_memory_barrier ();
6185 image->mvar_cache_slow = ht;
6187 image->var_cache_slow = ht;
6190 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6195 * LOCKING: Acquires the image lock (@image).
6198 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6200 MonoImage *image = get_image_for_generic_param (param);
6201 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6202 MonoClass *klass, *klass2;
6204 // If a klass already exists for this object and is cached, return it.
6205 if (pinfo) // Non-anonymous
6206 klass = pinfo->pklass;
6208 klass = get_anon_gparam_class (param, TRUE);
6213 // Create a new klass
6214 klass = make_generic_param_class (param, pinfo);
6216 // Now we need to cache the klass we created.
6217 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6218 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6219 // and allow our newly-created klass object to just leak.
6220 mono_memory_barrier ();
6222 mono_image_lock (image);
6224 // Here "klass2" refers to the klass potentially created by the other thread.
6225 if (pinfo) // Repeat check from above
6226 klass2 = pinfo->pklass;
6228 klass2 = get_anon_gparam_class (param, FALSE);
6235 pinfo->pklass = klass;
6237 set_anon_gparam_class (param, klass);
6239 mono_image_unlock (image);
6241 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6243 MONO_PROFILER_RAISE (class_failed, (klass2));
6245 MONO_PROFILER_RAISE (class_loaded, (klass));
6251 * mono_class_from_generic_parameter:
6252 * \param param Parameter to find/construct a class for.
6253 * \param arg2 Is ignored.
6254 * \param arg3 Is ignored.
6257 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6259 return mono_class_from_generic_parameter_internal (param);
6263 * mono_ptr_class_get:
6266 mono_ptr_class_get (MonoType *type)
6269 MonoClass *el_class;
6273 el_class = mono_class_from_mono_type (type);
6274 image = el_class->image;
6276 mono_image_lock (image);
6277 if (image->ptr_cache) {
6278 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6279 mono_image_unlock (image);
6283 mono_image_unlock (image);
6285 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6287 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6288 ++class_pointer_count;
6290 result->parent = NULL; /* no parent for PTR types */
6291 result->name_space = el_class->name_space;
6292 name = g_strdup_printf ("%s*", el_class->name);
6293 result->name = mono_image_strdup (image, name);
6294 result->class_kind = MONO_CLASS_POINTER;
6297 MONO_PROFILER_RAISE (class_loading, (result));
6299 result->image = el_class->image;
6300 result->inited = TRUE;
6301 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6302 result->cast_class = result->element_class = el_class;
6303 result->blittable = TRUE;
6305 result->byval_arg.type = MONO_TYPE_PTR;
6306 result->this_arg.type = result->byval_arg.type;
6307 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6308 result->this_arg.byref = TRUE;
6310 mono_class_setup_supertypes (result);
6312 mono_image_lock (image);
6313 if (image->ptr_cache) {
6315 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6316 mono_image_unlock (image);
6317 MONO_PROFILER_RAISE (class_failed, (result));
6321 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6323 g_hash_table_insert (image->ptr_cache, el_class, result);
6324 mono_image_unlock (image);
6326 MONO_PROFILER_RAISE (class_loaded, (result));
6332 mono_fnptr_class_get (MonoMethodSignature *sig)
6334 MonoClass *result, *cached;
6335 static GHashTable *ptr_hash = NULL;
6337 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6339 mono_loader_lock ();
6341 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6342 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6343 mono_loader_unlock ();
6347 result = g_new0 (MonoClass, 1);
6349 result->parent = NULL; /* no parent for PTR types */
6350 result->name_space = "System";
6351 result->name = "MonoFNPtrFakeClass";
6352 result->class_kind = MONO_CLASS_POINTER;
6354 result->image = mono_defaults.corlib; /* need to fix... */
6355 result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6356 result->cast_class = result->element_class = result;
6357 result->byval_arg.type = MONO_TYPE_FNPTR;
6358 result->this_arg.type = result->byval_arg.type;
6359 result->this_arg.data.method = result->byval_arg.data.method = sig;
6360 result->this_arg.byref = TRUE;
6361 result->blittable = TRUE;
6362 result->inited = TRUE;
6364 mono_class_setup_supertypes (result);
6366 mono_loader_lock ();
6368 cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6371 mono_loader_unlock ();
6375 MONO_PROFILER_RAISE (class_loading, (result));
6377 UnlockedAdd (&classes_size, sizeof (MonoClassPointer));
6378 ++class_pointer_count;
6380 g_hash_table_insert (ptr_hash, sig, result);
6382 mono_loader_unlock ();
6384 MONO_PROFILER_RAISE (class_loaded, (result));
6390 * mono_class_from_mono_type:
6391 * \param type describes the type to return
6392 * \returns a \c MonoClass for the specified \c MonoType, the value is never NULL.
6395 mono_class_from_mono_type (MonoType *type)
6397 switch (type->type) {
6398 case MONO_TYPE_OBJECT:
6399 return type->data.klass? type->data.klass: mono_defaults.object_class;
6400 case MONO_TYPE_VOID:
6401 return type->data.klass? type->data.klass: mono_defaults.void_class;
6402 case MONO_TYPE_BOOLEAN:
6403 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6404 case MONO_TYPE_CHAR:
6405 return type->data.klass? type->data.klass: mono_defaults.char_class;
6407 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6409 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6411 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6413 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6415 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6417 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6419 return type->data.klass? type->data.klass: mono_defaults.int_class;
6421 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6423 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6425 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6427 return type->data.klass? type->data.klass: mono_defaults.single_class;
6429 return type->data.klass? type->data.klass: mono_defaults.double_class;
6430 case MONO_TYPE_STRING:
6431 return type->data.klass? type->data.klass: mono_defaults.string_class;
6432 case MONO_TYPE_TYPEDBYREF:
6433 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6434 case MONO_TYPE_ARRAY:
6435 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6437 return mono_ptr_class_get (type->data.type);
6438 case MONO_TYPE_FNPTR:
6439 return mono_fnptr_class_get (type->data.method);
6440 case MONO_TYPE_SZARRAY:
6441 return mono_array_class_get (type->data.klass, 1);
6442 case MONO_TYPE_CLASS:
6443 case MONO_TYPE_VALUETYPE:
6444 return type->data.klass;
6445 case MONO_TYPE_GENERICINST:
6446 return mono_generic_class_get_class (type->data.generic_class);
6447 case MONO_TYPE_MVAR:
6449 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6451 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6452 g_assert_not_reached ();
6455 // Yes, this returns NULL, even if it is documented as not doing so, but there
6456 // is no way for the code to make it this far, due to the assert above.
6461 * mono_type_retrieve_from_typespec
6462 * \param image context where the image is created
6463 * \param type_spec typespec token
6464 * \param context the generic context used to evaluate generic instantiations in
6467 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6469 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6471 *did_inflate = FALSE;
6476 if (context && (context->class_inst || context->method_inst)) {
6477 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6479 if (!mono_error_ok (error)) {
6485 *did_inflate = TRUE;
6492 * mono_class_create_from_typespec
6493 * \param image context where the image is created
6494 * \param type_spec typespec token
6495 * \param context the generic context used to evaluate generic instantiations in
6498 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6501 gboolean inflated = FALSE;
6502 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6503 return_val_if_nok (error, NULL);
6504 ret = mono_class_from_mono_type (t);
6506 mono_metadata_free_type (t);
6511 * mono_bounded_array_class_get:
6512 * \param element_class element class
6513 * \param rank the dimension of the array class
6514 * \param bounded whenever the array has non-zero bounds
6515 * \returns A class object describing the array with element type \p element_type and
6516 * dimension \p rank.
6519 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6522 MonoClass *klass, *cached, *k;
6523 MonoClass *parent = NULL;
6524 GSList *list, *rootlist = NULL;
6528 g_assert (rank <= 255);
6531 /* bounded only matters for one-dimensional arrays */
6534 image = eclass->image;
6538 if (rank == 1 && !bounded) {
6540 * This case is very frequent not just during compilation because of calls
6541 * from mono_class_from_mono_type (), mono_array_new (),
6542 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6544 mono_os_mutex_lock (&image->szarray_cache_lock);
6545 if (!image->szarray_cache)
6546 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6547 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6548 mono_os_mutex_unlock (&image->szarray_cache_lock);
6550 mono_loader_lock ();
6551 if (!image->array_cache)
6552 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6553 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6554 for (list = rootlist; list; list = list->next) {
6555 k = (MonoClass *)list->data;
6556 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6561 mono_loader_unlock ();
6566 parent = mono_defaults.array_class;
6567 if (!parent->inited)
6568 mono_class_init (parent);
6570 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6572 klass->image = image;
6573 klass->name_space = eclass->name_space;
6574 klass->class_kind = MONO_CLASS_ARRAY;
6576 nsize = strlen (eclass->name);
6577 name = (char *)g_malloc (nsize + 2 + rank + 1);
6578 memcpy (name, eclass->name, nsize);
6581 memset (name + nsize + 1, ',', rank - 1);
6583 name [nsize + rank] = '*';
6584 name [nsize + rank + bounded] = ']';
6585 name [nsize + rank + bounded + 1] = 0;
6586 klass->name = mono_image_strdup (image, name);
6589 klass->type_token = 0;
6590 klass->parent = parent;
6591 klass->instance_size = mono_class_instance_size (klass->parent);
6593 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF) {
6594 /*Arrays of those two types are invalid.*/
6595 MonoError prepared_error;
6596 error_init (&prepared_error);
6597 mono_error_set_invalid_program (&prepared_error, "Arrays of System.TypedReference types are invalid.");
6598 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6599 mono_error_cleanup (&prepared_error);
6600 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6601 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6602 if (!ref_info_handle || eclass->wastypebuilder) {
6603 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6604 g_assert (ref_info_handle && !eclass->wastypebuilder);
6606 /* element_size -1 is ok as this is not an instantitable type*/
6607 klass->sizes.element_size = -1;
6609 klass->sizes.element_size = -1;
6611 mono_class_setup_supertypes (klass);
6613 if (mono_class_is_ginst (eclass))
6614 mono_class_init (eclass);
6615 if (!eclass->size_inited)
6616 mono_class_setup_fields (eclass);
6617 mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6618 /*FIXME we fail the array type, but we have to let other fields be set.*/
6620 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6624 if (eclass->enumtype)
6625 klass->cast_class = eclass->element_class;
6627 klass->cast_class = eclass;
6629 switch (klass->cast_class->byval_arg.type) {
6631 klass->cast_class = mono_defaults.byte_class;
6634 klass->cast_class = mono_defaults.int16_class;
6637 #if SIZEOF_VOID_P == 4
6641 klass->cast_class = mono_defaults.int32_class;
6644 #if SIZEOF_VOID_P == 8
6648 klass->cast_class = mono_defaults.int64_class;
6654 klass->element_class = eclass;
6656 if ((rank > 1) || bounded) {
6657 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6658 klass->byval_arg.type = MONO_TYPE_ARRAY;
6659 klass->byval_arg.data.array = at;
6660 at->eklass = eclass;
6662 /* FIXME: complete.... */
6664 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6665 klass->byval_arg.data.klass = eclass;
6667 klass->this_arg = klass->byval_arg;
6668 klass->this_arg.byref = 1;
6671 MonoError prepared_error;
6672 error_init (&prepared_error);
6673 name = mono_type_get_full_name (klass);
6674 mono_error_set_type_load_class (&prepared_error, klass, "%s has too many dimensions.", name);
6675 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6676 mono_error_cleanup (&prepared_error);
6680 mono_loader_lock ();
6682 /* Check cache again */
6684 if (rank == 1 && !bounded) {
6685 mono_os_mutex_lock (&image->szarray_cache_lock);
6686 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6687 mono_os_mutex_unlock (&image->szarray_cache_lock);
6689 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6690 for (list = rootlist; list; list = list->next) {
6691 k = (MonoClass *)list->data;
6692 if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6699 mono_loader_unlock ();
6703 MONO_PROFILER_RAISE (class_loading, (klass));
6705 UnlockedAdd (&classes_size, sizeof (MonoClassArray));
6706 ++class_array_count;
6708 if (rank == 1 && !bounded) {
6709 mono_os_mutex_lock (&image->szarray_cache_lock);
6710 g_hash_table_insert (image->szarray_cache, eclass, klass);
6711 mono_os_mutex_unlock (&image->szarray_cache_lock);
6713 list = g_slist_append (rootlist, klass);
6714 g_hash_table_insert (image->array_cache, eclass, list);
6717 mono_loader_unlock ();
6719 MONO_PROFILER_RAISE (class_loaded, (klass));
6725 * mono_array_class_get:
6726 * \param element_class element class
6727 * \param rank the dimension of the array class
6728 * \returns A class object describing the array with element type \p element_type and
6729 * dimension \p rank.
6732 mono_array_class_get (MonoClass *eclass, guint32 rank)
6734 return mono_bounded_array_class_get (eclass, rank, FALSE);
6738 * mono_class_instance_size:
6739 * \param klass a class
6741 * Use to get the size of a class in bytes.
6743 * \returns The size of an object instance
6746 mono_class_instance_size (MonoClass *klass)
6748 if (!klass->size_inited)
6749 mono_class_init (klass);
6751 return klass->instance_size;
6755 * mono_class_min_align:
6756 * \param klass a class
6758 * Use to get the computed minimum alignment requirements for the specified class.
6760 * Returns: minimum alignment requirements
6763 mono_class_min_align (MonoClass *klass)
6765 if (!klass->size_inited)
6766 mono_class_init (klass);
6768 return klass->min_align;
6772 * mono_class_value_size:
6773 * \param klass a class
6775 * This function is used for value types, and return the
6776 * space and the alignment to store that kind of value object.
6778 * \returns the size of a value of kind \p klass
6781 mono_class_value_size (MonoClass *klass, guint32 *align)
6785 /* fixme: check disable, because we still have external revereces to
6786 * mscorlib and Dummy Objects
6788 /*g_assert (klass->valuetype);*/
6790 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6793 *align = klass->min_align;
6799 * mono_class_data_size:
6800 * \param klass a class
6802 * \returns The size of the static class data
6805 mono_class_data_size (MonoClass *klass)
6808 mono_class_init (klass);
6809 /* This can happen with dynamically created types */
6810 if (!klass->fields_inited)
6811 mono_class_setup_fields (klass);
6813 /* in arrays, sizes.class_size is unioned with element_size
6814 * and arrays have no static fields
6818 return klass->sizes.class_size;
6822 * Auxiliary routine to mono_class_get_field
6824 * Takes a field index instead of a field token.
6826 static MonoClassField *
6827 mono_class_get_field_idx (MonoClass *klass, int idx)
6829 mono_class_setup_fields (klass);
6830 if (mono_class_has_failure (klass))
6834 int first_field_idx = mono_class_get_first_field_idx (klass);
6835 int fcount = mono_class_get_field_count (klass);
6836 if (klass->image->uncompressed_metadata) {
6838 * first_field_idx points to the FieldPtr table, while idx points into the
6839 * Field table, so we have to do a search.
6841 /*FIXME this is broken for types with multiple fields with the same name.*/
6842 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6845 for (i = 0; i < fcount; ++i)
6846 if (mono_field_get_name (&klass->fields [i]) == name)
6847 return &klass->fields [i];
6848 g_assert_not_reached ();
6851 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6852 return &klass->fields [idx - first_field_idx];
6856 klass = klass->parent;
6862 * mono_class_get_field:
6863 * \param class the class to lookup the field.
6864 * \param field_token the field token
6866 * \returns A \c MonoClassField representing the type and offset of
6867 * the field, or a NULL value if the field does not belong to this
6871 mono_class_get_field (MonoClass *klass, guint32 field_token)
6873 int idx = mono_metadata_token_index (field_token);
6875 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6877 return mono_class_get_field_idx (klass, idx - 1);
6881 * mono_class_get_field_from_name:
6882 * \param klass the class to lookup the field.
6883 * \param name the field name
6885 * Search the class \p klass and its parents for a field with the name \p name.
6887 * \returns The \c MonoClassField pointer of the named field or NULL
6890 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6892 return mono_class_get_field_from_name_full (klass, name, NULL);
6896 * mono_class_get_field_from_name_full:
6897 * \param klass the class to lookup the field.
6898 * \param name the field name
6899 * \param type the type of the fields. This optional.
6901 * Search the class \p klass and it's parents for a field with the name \p name and type \p type.
6903 * If \p klass is an inflated generic type, the type comparison is done with the equivalent field
6904 * of its generic type definition.
6906 * \returns The MonoClassField pointer of the named field or NULL
6909 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6913 mono_class_setup_fields (klass);
6914 if (mono_class_has_failure (klass))
6918 int fcount = mono_class_get_field_count (klass);
6919 for (i = 0; i < fcount; ++i) {
6920 MonoClassField *field = &klass->fields [i];
6922 if (strcmp (name, mono_field_get_name (field)) != 0)
6926 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6927 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6932 klass = klass->parent;
6938 * mono_class_get_field_token:
6939 * \param field the field we need the token of
6941 * Get the token of a field. Note that the tokesn is only valid for the image
6942 * the field was loaded from. Don't use this function for fields in dynamic types.
6944 * \returns The token representing the field in the image it was loaded from.
6947 mono_class_get_field_token (MonoClassField *field)
6949 MonoClass *klass = field->parent;
6952 mono_class_setup_fields (klass);
6957 int first_field_idx = mono_class_get_first_field_idx (klass);
6958 int fcount = mono_class_get_field_count (klass);
6959 for (i = 0; i < fcount; ++i) {
6960 if (&klass->fields [i] == field) {
6961 int idx = first_field_idx + i + 1;
6963 if (klass->image->uncompressed_metadata)
6964 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6965 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6968 klass = klass->parent;
6971 g_assert_not_reached ();
6976 mono_field_get_index (MonoClassField *field)
6978 int index = field - field->parent->fields;
6979 g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6985 * mono_class_get_field_default_value:
6987 * Return the default value of the field as a pointer into the metadata blob.
6990 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6993 guint32 constant_cols [MONO_CONSTANT_SIZE];
6995 MonoClass *klass = field->parent;
6996 MonoFieldDefaultValue *def_values;
6998 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7000 def_values = mono_class_get_field_def_values (klass);
7002 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
7004 mono_class_set_field_def_values (klass, def_values);
7007 field_index = mono_field_get_index (field);
7009 if (!def_values [field_index].data) {
7010 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7014 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7016 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7017 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7018 mono_memory_barrier ();
7019 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7022 *def_type = def_values [field_index].def_type;
7023 return def_values [field_index].data;
7027 mono_property_get_index (MonoProperty *prop)
7029 MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
7030 int index = prop - info->properties;
7032 g_assert (index >= 0 && index < info->count);
7038 * mono_class_get_property_default_value:
7040 * Return the default value of the field as a pointer into the metadata blob.
7043 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7046 guint32 constant_cols [MONO_CONSTANT_SIZE];
7047 MonoClass *klass = property->parent;
7049 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7051 * We don't cache here because it is not used by C# so it's quite rare, but
7052 * we still do the lookup in klass->ext because that is where the data
7053 * is stored for dynamic assemblies.
7056 if (image_is_dynamic (klass->image)) {
7057 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7058 int prop_index = mono_property_get_index (property);
7059 if (info->def_values && info->def_values [prop_index].data) {
7060 *def_type = info->def_values [prop_index].def_type;
7061 return info->def_values [prop_index].data;
7065 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7069 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7070 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7071 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7075 * mono_class_get_event_token:
7078 mono_class_get_event_token (MonoEvent *event)
7080 MonoClass *klass = event->parent;
7084 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7086 for (i = 0; i < info->count; ++i) {
7087 if (&info->events [i] == event)
7088 return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7091 klass = klass->parent;
7094 g_assert_not_reached ();
7099 * mono_class_get_property_from_name:
7100 * \param klass a class
7101 * \param name name of the property to lookup in the specified class
7103 * Use this method to lookup a property in a class
7104 * \returns the \c MonoProperty with the given name, or NULL if the property
7105 * does not exist on the \p klass.
7108 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7112 gpointer iter = NULL;
7113 while ((p = mono_class_get_properties (klass, &iter))) {
7114 if (! strcmp (name, p->name))
7117 klass = klass->parent;
7123 * mono_class_get_property_token:
7124 * \param prop MonoProperty to query
7126 * \returns The ECMA token for the specified property.
7129 mono_class_get_property_token (MonoProperty *prop)
7131 MonoClass *klass = prop->parent;
7135 gpointer iter = NULL;
7136 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7137 while ((p = mono_class_get_properties (klass, &iter))) {
7138 if (&info->properties [i] == prop)
7139 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7143 klass = klass->parent;
7146 g_assert_not_reached ();
7151 * mono_class_name_from_token:
7154 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7156 const char *name, *nspace;
7157 if (image_is_dynamic (image))
7158 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7160 switch (type_token & 0xff000000){
7161 case MONO_TOKEN_TYPE_DEF: {
7162 guint32 cols [MONO_TYPEDEF_SIZE];
7163 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7164 guint tidx = mono_metadata_token_index (type_token);
7166 if (tidx > tt->rows)
7167 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7169 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7170 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7171 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7172 if (strlen (nspace) == 0)
7173 return g_strdup_printf ("%s", name);
7175 return g_strdup_printf ("%s.%s", nspace, name);
7178 case MONO_TOKEN_TYPE_REF: {
7180 guint32 cols [MONO_TYPEREF_SIZE];
7181 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7182 guint tidx = mono_metadata_token_index (type_token);
7185 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7187 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7188 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7189 mono_error_cleanup (&error);
7193 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7194 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7195 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7196 if (strlen (nspace) == 0)
7197 return g_strdup_printf ("%s", name);
7199 return g_strdup_printf ("%s.%s", nspace, name);
7202 case MONO_TOKEN_TYPE_SPEC:
7203 return g_strdup_printf ("Typespec 0x%08x", type_token);
7205 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7210 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7212 if (image_is_dynamic (image))
7213 return g_strdup_printf ("DynamicAssembly %s", image->name);
7215 switch (type_token & 0xff000000){
7216 case MONO_TOKEN_TYPE_DEF:
7217 if (image->assembly)
7218 return mono_stringify_assembly_name (&image->assembly->aname);
7219 else if (image->assembly_name)
7220 return g_strdup (image->assembly_name);
7221 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7222 case MONO_TOKEN_TYPE_REF: {
7224 MonoAssemblyName aname;
7225 guint32 cols [MONO_TYPEREF_SIZE];
7226 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7227 guint32 idx = mono_metadata_token_index (type_token);
7230 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7232 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7233 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7234 mono_error_cleanup (&error);
7237 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7239 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7240 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7241 case MONO_RESOLUTION_SCOPE_MODULE:
7243 return g_strdup ("");
7244 case MONO_RESOLUTION_SCOPE_MODULEREF:
7246 return g_strdup ("");
7247 case MONO_RESOLUTION_SCOPE_TYPEREF:
7249 return g_strdup ("");
7250 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7251 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7252 return mono_stringify_assembly_name (&aname);
7254 g_assert_not_reached ();
7258 case MONO_TOKEN_TYPE_SPEC:
7260 return g_strdup ("");
7262 g_assert_not_reached ();
7269 * mono_class_get_full:
7270 * \param image the image where the class resides
7271 * \param type_token the token for the class
7272 * \param context the generic context used to evaluate generic instantiations in
7273 * \deprecated Functions that expose \c MonoGenericContext are going away in mono 4.0
7274 * \returns The \c MonoClass that represents \p type_token in \p image
7277 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7281 klass = mono_class_get_checked (image, type_token, &error);
7283 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7284 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7286 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7292 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7297 klass = mono_class_get_checked (image, type_token, error);
7299 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7300 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7305 * mono_class_get_checked:
7306 * \param image the image where the class resides
7307 * \param type_token the token for the class
7308 * \param error error object to return any error
7310 * \returns The MonoClass that represents \p type_token in \p image, or NULL on error.
7313 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7315 MonoClass *klass = NULL;
7319 if (image_is_dynamic (image)) {
7320 int table = mono_metadata_token_table (type_token);
7322 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7323 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7326 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7330 switch (type_token & 0xff000000){
7331 case MONO_TOKEN_TYPE_DEF:
7332 klass = mono_class_create_from_typedef (image, type_token, error);
7334 case MONO_TOKEN_TYPE_REF:
7335 klass = mono_class_from_typeref_checked (image, type_token, error);
7337 case MONO_TOKEN_TYPE_SPEC:
7338 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7341 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7345 /* Generic case, should be avoided for when a better error is possible. */
7346 if (!klass && mono_error_ok (error)) {
7347 char *name = mono_class_name_from_token (image, type_token);
7348 char *assembly = mono_assembly_name_from_token (image, type_token);
7349 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x (class/assembly %s, %s)", type_token, name, assembly);
7357 * mono_type_get_checked:
7358 * \param image the image where the type resides
7359 * \param type_token the token for the type
7360 * \param context the generic context used to evaluate generic instantiations in
7361 * \param error Error handling context
7363 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7365 * \returns The MonoType that represents \p type_token in \p image
7368 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7370 MonoType *type = NULL;
7371 gboolean inflated = FALSE;
7375 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7376 if (image_is_dynamic (image)) {
7377 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7378 return_val_if_nok (error, NULL);
7379 return mono_class_get_type (klass);
7382 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7383 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7390 return mono_class_get_type (klass);
7393 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7400 MonoType *tmp = type;
7401 type = mono_class_get_type (mono_class_from_mono_type (type));
7402 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7403 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7404 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7406 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7408 if (type->type != tmp->type)
7411 mono_metadata_free_type (tmp);
7418 * \param image image where the class token will be looked up.
7419 * \param type_token a type token from the image
7420 * \returns the \c MonoClass with the given \p type_token on the \p image
7423 mono_class_get (MonoImage *image, guint32 type_token)
7425 return mono_class_get_full (image, type_token, NULL);
7429 * mono_image_init_name_cache:
7431 * Initializes the class name cache stored in image->name_cache.
7433 * LOCKING: Acquires the corresponding image lock.
7436 mono_image_init_name_cache (MonoImage *image)
7438 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7439 guint32 cols [MONO_TYPEDEF_SIZE];
7442 guint32 i, visib, nspace_index;
7443 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7445 if (image->name_cache)
7448 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7450 if (image_is_dynamic (image)) {
7451 mono_image_lock (image);
7452 if (image->name_cache) {
7453 /* Somebody initialized it before us */
7454 g_hash_table_destroy (the_name_cache);
7456 mono_atomic_store_release (&image->name_cache, the_name_cache);
7458 mono_image_unlock (image);
7462 /* Temporary hash table to avoid lookups in the nspace_table */
7463 name_cache2 = g_hash_table_new (NULL, NULL);
7465 for (i = 1; i <= t->rows; ++i) {
7466 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7467 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7469 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7470 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7472 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7474 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7475 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7477 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7478 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7479 if (!nspace_table) {
7480 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7481 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7482 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7485 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7488 /* Load type names from EXPORTEDTYPES table */
7490 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7491 guint32 cols [MONO_EXP_TYPE_SIZE];
7494 for (i = 0; i < t->rows; ++i) {
7495 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7497 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7498 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7502 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7503 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7505 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7506 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7507 if (!nspace_table) {
7508 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7509 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7510 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7513 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7517 g_hash_table_destroy (name_cache2);
7519 mono_image_lock (image);
7520 if (image->name_cache) {
7521 /* Somebody initialized it before us */
7522 g_hash_table_destroy (the_name_cache);
7524 mono_atomic_store_release (&image->name_cache, the_name_cache);
7526 mono_image_unlock (image);
7529 /*FIXME Only dynamic assemblies should allow this operation.*/
7531 * mono_image_add_to_name_cache:
7534 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7535 const char *name, guint32 index)
7537 GHashTable *nspace_table;
7538 GHashTable *name_cache;
7541 mono_image_init_name_cache (image);
7542 mono_image_lock (image);
7544 name_cache = image->name_cache;
7545 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7546 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7547 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7550 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7551 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7553 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7555 mono_image_unlock (image);
7564 find_nocase (gpointer key, gpointer value, gpointer user_data)
7566 char *name = (char*)key;
7567 FindUserData *data = (FindUserData*)user_data;
7569 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7570 data->value = value;
7574 * mono_class_from_name_case:
7575 * \param image The MonoImage where the type is looked up in
7576 * \param name_space the type namespace
7577 * \param name the type short name.
7578 * \deprecated use the mono_class_from_name_case_checked variant instead.
7580 * Obtains a \c MonoClass with a given namespace and a given name which
7581 * is located in the given \c MonoImage. The namespace and name
7582 * lookups are case insensitive.
7585 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7588 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7589 mono_error_cleanup (&error);
7595 * mono_class_from_name_case_checked:
7596 * \param image The MonoImage where the type is looked up in
7597 * \param name_space the type namespace
7598 * \param name the type short name.
7601 * Obtains a MonoClass with a given namespace and a given name which
7602 * is located in the given MonoImage. The namespace and name
7603 * lookups are case insensitive.
7605 * \returns The MonoClass if the given namespace and name were found, or NULL if it
7606 * was not found. The \p error object will contain information about the problem
7610 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7612 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7613 guint32 cols [MONO_TYPEDEF_SIZE];
7620 if (image_is_dynamic (image)) {
7622 FindUserData user_data;
7624 mono_image_init_name_cache (image);
7625 mono_image_lock (image);
7627 user_data.key = name_space;
7628 user_data.value = NULL;
7629 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7631 if (user_data.value) {
7632 GHashTable *nspace_table = (GHashTable*)user_data.value;
7634 user_data.key = name;
7635 user_data.value = NULL;
7637 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7639 if (user_data.value)
7640 token = GPOINTER_TO_UINT (user_data.value);
7643 mono_image_unlock (image);
7646 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7652 /* add a cache if needed */
7653 for (i = 1; i <= t->rows; ++i) {
7654 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7655 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7657 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7658 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7660 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7662 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7663 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7664 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7665 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7671 return_nested_in (MonoClass *klass, char *nested)
7674 char *s = strchr (nested, '/');
7675 gpointer iter = NULL;
7682 while ((found = mono_class_get_nested_types (klass, &iter))) {
7683 if (strcmp (found->name, nested) == 0) {
7685 return return_nested_in (found, s);
7693 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7695 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7696 MonoImage *file_image;
7703 * The EXPORTEDTYPES table only contains public types, so have to search the
7705 * Note: image->modules contains the contents of the MODULEREF table, while
7706 * the real module list is in the FILE table.
7708 for (i = 0; i < file_table->rows; i++) {
7709 guint32 cols [MONO_FILE_SIZE];
7710 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7711 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7714 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7716 klass = mono_class_from_name_checked (file_image, name_space, name, error);
7717 if (klass || !is_ok (error))
7726 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7728 GHashTable *nspace_table;
7729 MonoImage *loaded_image;
7738 // Checking visited images avoids stack overflows when cyclic references exist.
7739 if (g_hash_table_lookup (visited_images, image))
7742 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7744 if ((nested = strchr (name, '/'))) {
7745 int pos = nested - name;
7746 int len = strlen (name);
7749 memcpy (buf, name, len + 1);
7751 nested = buf + pos + 1;
7755 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7756 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7757 gboolean res = get_class_from_name (image, name_space, name, &klass);
7760 klass = search_modules (image, name_space, name, error);
7765 return klass ? return_nested_in (klass, nested) : NULL;
7771 mono_image_init_name_cache (image);
7772 mono_image_lock (image);
7774 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7777 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7779 mono_image_unlock (image);
7781 if (!token && image_is_dynamic (image) && image->modules) {
7782 /* Search modules as well */
7783 for (i = 0; i < image->module_count; ++i) {
7784 MonoImage *module = image->modules [i];
7786 klass = mono_class_from_name_checked (module, name_space, name, error);
7787 if (klass || !is_ok (error))
7793 klass = search_modules (image, name_space, name, error);
7794 if (klass || !is_ok (error))
7799 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7800 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7801 guint32 cols [MONO_EXP_TYPE_SIZE];
7804 idx = mono_metadata_token_index (token);
7806 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7808 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7809 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7810 loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7813 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7815 return klass ? return_nested_in (klass, nested) : NULL;
7817 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7818 guint32 assembly_idx;
7820 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7822 mono_assembly_load_reference (image, assembly_idx - 1);
7823 g_assert (image->references [assembly_idx - 1]);
7824 if (image->references [assembly_idx - 1] == (gpointer)-1)
7826 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7828 return klass ? return_nested_in (klass, nested) : NULL;
7831 g_assert_not_reached ();
7835 token = MONO_TOKEN_TYPE_DEF | token;
7837 klass = mono_class_get_checked (image, token, error);
7839 return return_nested_in (klass, nested);
7844 * mono_class_from_name_checked:
7845 * \param image The MonoImage where the type is looked up in
7846 * \param name_space the type namespace
7847 * \param name the type short name.
7849 * Obtains a MonoClass with a given namespace and a given name which
7850 * is located in the given MonoImage.
7852 * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7853 * set if the class was not found or it will return NULL and set the error if there was a loading error.
7856 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7859 GHashTable *visited_images;
7861 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7863 klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7865 g_hash_table_destroy (visited_images);
7871 * mono_class_from_name:
7872 * \param image The \c MonoImage where the type is looked up in
7873 * \param name_space the type namespace
7874 * \param name the type short name.
7876 * Obtains a \c MonoClass with a given namespace and a given name which
7877 * is located in the given \c MonoImage.
7879 * To reference nested classes, use the "/" character as a separator.
7880 * For example use \c "Foo/Bar" to reference the class \c Bar that is nested
7881 * inside \c Foo, like this: "class Foo { class Bar {} }".
7884 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7889 klass = mono_class_from_name_checked (image, name_space, name, &error);
7890 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7896 * mono_class_load_from_name:
7897 * \param image The MonoImage where the type is looked up in
7898 * \param name_space the type namespace
7899 * \param name the type short name.
7901 * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7902 * This function should be used by the runtime for critical types to which there's no way to recover but crash
7903 * If they are missing. Thing of System.Object or System.String.
7906 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7911 klass = mono_class_from_name_checked (image, name_space, name, &error);
7913 g_error ("Runtime critical type %s.%s not found", name_space, name);
7914 if (!mono_error_ok (&error))
7915 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7920 * mono_class_try_load_from_name:
7921 * \param image The MonoImage where the type is looked up in
7922 * \param name_space the type namespace
7923 * \param name the type short name.
7925 * This function tries to load a type, returning the class was found or NULL otherwise.
7926 * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7928 * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7929 * a type that we would otherwise assume to be available but was not due some error.
7933 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7938 klass = mono_class_from_name_checked (image, name_space, name, &error);
7939 if (!mono_error_ok (&error))
7940 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7946 * mono_class_is_subclass_of:
7947 * \param klass class to probe if it is a subclass of another one
7948 * \param klassc the class we suspect is the base class
7949 * \param check_interfaces whether we should perform interface checks
7951 * This method determines whether \p klass is a subclass of \p klassc.
7953 * If the \p check_interfaces flag is set, then if \p klassc is an interface
7954 * this method return TRUE if the \p klass implements the interface or
7955 * if \p klass is an interface, if one of its base classes is \p klass.
7957 * If \p check_interfaces is false, then if \p klass is not an interface,
7958 * it returns TRUE if the \p klass is a subclass of \p klassc.
7960 * if \p klass is an interface and \p klassc is \c System.Object, then this function
7965 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7966 gboolean check_interfaces)
7968 /* FIXME test for interfaces with variant generic arguments */
7969 mono_class_init (klass);
7970 mono_class_init (klassc);
7972 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7973 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7975 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7978 for (i = 0; i < klass->interface_count; i ++) {
7979 MonoClass *ic = klass->interfaces [i];
7984 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7989 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7992 if (klassc == mono_defaults.object_class)
7999 mono_type_is_generic_argument (MonoType *type)
8001 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8005 mono_class_has_variant_generic_params (MonoClass *klass)
8008 MonoGenericContainer *container;
8010 if (!mono_class_is_ginst (klass))
8013 container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
8015 for (i = 0; i < container->type_argc; ++i)
8016 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8023 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8025 if (target == candidate)
8028 if (check_for_reference_conv &&
8029 mono_type_is_generic_argument (&target->byval_arg) &&
8030 mono_type_is_generic_argument (&candidate->byval_arg)) {
8031 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8032 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8034 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8037 if (!mono_class_is_assignable_from (target, candidate))
8043 * @container the generic container from the GTD
8044 * @klass: the class to be assigned to
8045 * @oklass: the source class
8047 * Both @klass and @oklass must be instances of the same generic interface.
8049 * Returns: TRUE if @klass can be assigned to a @klass variable
8052 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8055 MonoType **klass_argv, **oklass_argv;
8056 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8057 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8059 if (klass == oklass)
8062 /*Viable candidates are instances of the same generic interface*/
8063 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8066 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8067 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8069 for (j = 0; j < container->type_argc; ++j) {
8070 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8071 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8073 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8077 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8078 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8080 if (param1_class != param2_class) {
8081 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8082 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8084 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8085 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8095 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8097 MonoGenericParam *gparam, *ogparam;
8098 MonoGenericParamInfo *tinfo, *cinfo;
8099 MonoClass **candidate_class;
8100 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8103 if (target == candidate)
8105 if (target->byval_arg.type != candidate->byval_arg.type)
8108 gparam = target->byval_arg.data.generic_param;
8109 ogparam = candidate->byval_arg.data.generic_param;
8110 tinfo = mono_generic_param_info (gparam);
8111 cinfo = mono_generic_param_info (ogparam);
8113 class_constraint_satisfied = FALSE;
8114 valuetype_constraint_satisfied = FALSE;
8116 /*candidate must have a super set of target's special constraints*/
8117 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8118 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8120 if (cinfo->constraints) {
8121 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8122 MonoClass *cc = *candidate_class;
8124 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8125 class_constraint_satisfied = TRUE;
8126 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8127 valuetype_constraint_satisfied = TRUE;
8130 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8131 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8133 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8135 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8137 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8138 valuetype_constraint_satisfied)) {
8143 /*candidate type constraints must be a superset of target's*/
8144 if (tinfo->constraints) {
8145 MonoClass **target_class;
8146 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8147 MonoClass *tc = *target_class;
8150 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8151 * check it's constraints since it satisfy the constraint by itself.
8153 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8156 if (!cinfo->constraints)
8159 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8160 MonoClass *cc = *candidate_class;
8162 if (mono_class_is_assignable_from (tc, cc))
8166 * This happens when we have the following:
8168 * Bar<K> where K : IFace
8169 * Foo<T, U> where T : U where U : IFace
8171 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8174 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8175 if (mono_gparam_is_assignable_from (target, cc))
8179 if (!*candidate_class)
8184 /*candidate itself must have a constraint that satisfy target*/
8185 if (cinfo->constraints) {
8186 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8187 MonoClass *cc = *candidate_class;
8188 if (mono_class_is_assignable_from (target, cc))
8196 * mono_class_is_assignable_from:
8197 * \param klass the class to be assigned to
8198 * \param oklass the source class
8200 * \returns TRUE if an instance of class \p oklass can be assigned to an
8201 * instance of class \p klass
8204 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8207 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8209 mono_class_init (klass);
8211 if (!oklass->inited)
8212 mono_class_init (oklass);
8214 if (mono_class_has_failure (klass) || mono_class_has_failure (oklass))
8217 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8218 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8220 return mono_gparam_is_assignable_from (klass, oklass);
8223 if (MONO_CLASS_IS_INTERFACE (klass)) {
8224 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8225 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8226 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8230 for (i = 0; constraints [i]; ++i) {
8231 if (mono_class_is_assignable_from (klass, constraints [i]))
8239 /* interface_offsets might not be set for dynamic classes */
8240 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8242 * oklass might be a generic type parameter but they have
8243 * interface_offsets set.
8245 gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8246 if (!is_ok (&error)) {
8247 mono_error_cleanup (&error);
8252 if (!oklass->interface_bitmap)
8253 /* Happens with generic instances of not-yet created dynamic types */
8255 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8258 if (klass->is_array_special_interface && oklass->rank == 1) {
8259 //XXX we could offset this by having the cast target computed at JIT time
8260 //XXX we could go even further and emit a wrapper that would do the extra type check
8261 MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8262 MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8264 // 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
8265 // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8266 if (iface_klass->valuetype)
8267 iface_klass = iface_klass->cast_class;
8269 //array covariant casts only operates on scalar to scalar
8270 //This is so int[] can't be casted to IComparable<int>[]
8271 if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8275 if (mono_class_has_variant_generic_params (klass)) {
8277 mono_class_setup_interfaces (oklass, &error);
8278 if (!mono_error_ok (&error)) {
8279 mono_error_cleanup (&error);
8283 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8284 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8285 MonoClass *iface = oklass->interfaces_packed [i];
8287 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8292 } else if (klass->delegate) {
8293 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8295 }else if (klass->rank) {
8296 MonoClass *eclass, *eoclass;
8298 if (oklass->rank != klass->rank)
8301 /* vectors vs. one dimensional arrays */
8302 if (oklass->byval_arg.type != klass->byval_arg.type)
8305 eclass = klass->cast_class;
8306 eoclass = oklass->cast_class;
8309 * a is b does not imply a[] is b[] when a is a valuetype, and
8310 * b is a reference type.
8313 if (eoclass->valuetype) {
8314 if ((eclass == mono_defaults.enum_class) ||
8315 (eclass == mono_defaults.enum_class->parent) ||
8316 (eclass == mono_defaults.object_class))
8320 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8321 } else if (mono_class_is_nullable (klass)) {
8322 if (mono_class_is_nullable (oklass))
8323 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8325 return mono_class_is_assignable_from (klass->cast_class, oklass);
8326 } else if (klass == mono_defaults.object_class)
8329 return mono_class_has_parent (oklass, klass);
8332 /*Check if @oklass is variant compatible with @klass.*/
8334 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8337 MonoType **klass_argv, **oklass_argv;
8338 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8339 MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8341 /*Viable candidates are instances of the same generic interface*/
8342 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8345 klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8346 oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8348 for (j = 0; j < container->type_argc; ++j) {
8349 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8350 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8352 if (param1_class->valuetype != param2_class->valuetype)
8356 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8357 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8359 if (param1_class != param2_class) {
8360 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8361 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8363 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8364 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8372 /*Check if @candidate implements the interface @target*/
8374 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8378 gboolean is_variant = mono_class_has_variant_generic_params (target);
8380 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8381 if (mono_class_is_variant_compatible_slow (target, candidate))
8386 if (candidate == target)
8389 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8390 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8391 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info_raw (candidate); /* FIXME use handles */
8393 if (tb && tb->interfaces) {
8394 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8395 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8396 MonoClass *iface_class;
8398 /* we can't realize the type here since it can do pretty much anything. */
8401 iface_class = mono_class_from_mono_type (iface->type);
8402 if (iface_class == target)
8404 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8406 if (mono_class_implement_interface_slow (target, iface_class))
8411 /*setup_interfaces don't mono_class_init anything*/
8412 /*FIXME this doesn't handle primitive type arrays.
8413 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8414 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8416 mono_class_setup_interfaces (candidate, &error);
8417 if (!mono_error_ok (&error)) {
8418 mono_error_cleanup (&error);
8422 for (i = 0; i < candidate->interface_count; ++i) {
8423 if (candidate->interfaces [i] == target)
8426 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8429 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8433 candidate = candidate->parent;
8434 } while (candidate);
8440 * Check if @oklass can be assigned to @klass.
8441 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8444 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8446 if (candidate == target)
8448 if (target == mono_defaults.object_class)
8451 if (mono_class_has_parent (candidate, target))
8454 /*If target is not an interface there is no need to check them.*/
8455 if (MONO_CLASS_IS_INTERFACE (target))
8456 return mono_class_implement_interface_slow (target, candidate);
8458 if (target->delegate && mono_class_has_variant_generic_params (target))
8459 return mono_class_is_variant_compatible (target, candidate, FALSE);
8462 MonoClass *eclass, *eoclass;
8464 if (target->rank != candidate->rank)
8467 /* vectors vs. one dimensional arrays */
8468 if (target->byval_arg.type != candidate->byval_arg.type)
8471 eclass = target->cast_class;
8472 eoclass = candidate->cast_class;
8475 * a is b does not imply a[] is b[] when a is a valuetype, and
8476 * b is a reference type.
8479 if (eoclass->valuetype) {
8480 if ((eclass == mono_defaults.enum_class) ||
8481 (eclass == mono_defaults.enum_class->parent) ||
8482 (eclass == mono_defaults.object_class))
8486 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8488 /*FIXME properly handle nullables */
8489 /*FIXME properly handle (M)VAR */
8494 * mono_class_get_cctor:
8495 * \param klass A MonoClass pointer
8497 * \returns The static constructor of \p klass if it exists, NULL otherwise.
8500 mono_class_get_cctor (MonoClass *klass)
8502 MonoCachedClassInfo cached_info;
8504 if (image_is_dynamic (klass->image)) {
8506 * has_cctor is not set for these classes because mono_class_init () is
8509 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8512 mono_class_init (klass);
8514 if (!klass->has_cctor)
8517 if (mono_class_is_ginst (klass) && !klass->methods)
8518 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8520 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8522 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8523 if (!mono_error_ok (&error))
8524 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8528 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8532 * mono_class_get_finalizer:
8533 * \param klass: The MonoClass pointer
8535 * \returns The finalizer method of \p klass if it exists, NULL otherwise.
8538 mono_class_get_finalizer (MonoClass *klass)
8540 MonoCachedClassInfo cached_info;
8543 mono_class_init (klass);
8544 if (!mono_class_has_finalizer (klass))
8547 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8549 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8550 if (!mono_error_ok (&error))
8551 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8554 mono_class_setup_vtable (klass);
8555 return klass->vtable [finalize_slot];
8560 * mono_class_needs_cctor_run:
8561 * \param klass the MonoClass pointer
8562 * \param caller a MonoMethod describing the caller
8564 * Determines whenever the class has a static constructor and whenever it
8565 * needs to be called when executing CALLER.
8568 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8572 method = mono_class_get_cctor (klass);
8574 return (method == caller) ? FALSE : TRUE;
8580 * mono_class_array_element_size:
8583 * \returns The number of bytes an element of type \p klass uses when stored into an array.
8586 mono_class_array_element_size (MonoClass *klass)
8588 MonoType *type = &klass->byval_arg;
8591 switch (type->type) {
8594 case MONO_TYPE_BOOLEAN:
8598 case MONO_TYPE_CHAR:
8607 case MONO_TYPE_CLASS:
8608 case MONO_TYPE_STRING:
8609 case MONO_TYPE_OBJECT:
8610 case MONO_TYPE_SZARRAY:
8611 case MONO_TYPE_ARRAY:
8612 return sizeof (gpointer);
8617 case MONO_TYPE_VALUETYPE:
8618 if (type->data.klass->enumtype) {
8619 type = mono_class_enum_basetype (type->data.klass);
8620 klass = klass->element_class;
8623 return mono_class_instance_size (klass) - sizeof (MonoObject);
8624 case MONO_TYPE_GENERICINST:
8625 type = &type->data.generic_class->container_class->byval_arg;
8628 case MONO_TYPE_MVAR: {
8631 return mono_type_size (type, &align);
8633 case MONO_TYPE_VOID:
8637 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8643 * mono_array_element_size:
8644 * \param ac pointer to a \c MonoArrayClass
8646 * \returns The size of single array element.
8648 * LOCKING: Acquires the loader lock.
8651 mono_array_element_size (MonoClass *ac)
8653 g_assert (ac->rank);
8654 if (G_UNLIKELY (!ac->size_inited)) {
8655 mono_class_setup_fields (ac);
8657 return ac->sizes.element_size;
8664 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8665 MonoGenericContext *context)
8668 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8669 g_assert (mono_error_ok (&error));
8674 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8675 MonoGenericContext *context, MonoError *error)
8679 if (image_is_dynamic (image)) {
8680 MonoClass *tmp_handle_class;
8681 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8683 mono_error_assert_ok (error);
8684 g_assert (tmp_handle_class);
8686 *handle_class = tmp_handle_class;
8688 if (tmp_handle_class == mono_defaults.typehandle_class)
8689 return &((MonoClass*)obj)->byval_arg;
8694 switch (token & 0xff000000) {
8695 case MONO_TOKEN_TYPE_DEF:
8696 case MONO_TOKEN_TYPE_REF:
8697 case MONO_TOKEN_TYPE_SPEC: {
8700 *handle_class = mono_defaults.typehandle_class;
8701 type = mono_type_get_checked (image, token, context, error);
8705 mono_class_init (mono_class_from_mono_type (type));
8706 /* We return a MonoType* as handle */
8709 case MONO_TOKEN_FIELD_DEF: {
8711 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8713 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8717 *handle_class = mono_defaults.fieldhandle_class;
8718 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8722 mono_class_init (klass);
8723 return mono_class_get_field (klass, token);
8725 case MONO_TOKEN_METHOD_DEF:
8726 case MONO_TOKEN_METHOD_SPEC: {
8728 meth = mono_get_method_checked (image, token, NULL, context, error);
8730 *handle_class = mono_defaults.methodhandle_class;
8736 case MONO_TOKEN_MEMBER_REF: {
8737 guint32 cols [MONO_MEMBERREF_SIZE];
8739 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8740 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8741 mono_metadata_decode_blob_size (sig, &sig);
8742 if (*sig == 0x6) { /* it's a field */
8744 MonoClassField *field;
8745 field = mono_field_from_token_checked (image, token, &klass, context, error);
8747 *handle_class = mono_defaults.fieldhandle_class;
8751 meth = mono_get_method_checked (image, token, NULL, context, error);
8753 *handle_class = mono_defaults.methodhandle_class;
8758 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8764 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8766 MonoClass *handle_class;
8768 return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8772 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8774 return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8777 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8780 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8782 get_cached_class_info = func;
8786 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8788 if (!get_cached_class_info)
8791 return get_cached_class_info (klass, res);
8795 mono_install_get_class_from_name (MonoGetClassFromName func)
8797 get_class_from_name = func;
8801 * mono_class_get_image:
8803 * Use this method to get the \c MonoImage* where this class came from.
8805 * \returns The image where this class is defined.
8808 mono_class_get_image (MonoClass *klass)
8810 return klass->image;
8814 * mono_class_get_element_class:
8815 * \param klass the \c MonoClass to act on
8817 * Use this function to get the element class of an array.
8819 * \returns The element class of an array.
8822 mono_class_get_element_class (MonoClass *klass)
8824 return klass->element_class;
8828 * mono_class_is_valuetype:
8829 * \param klass the \c MonoClass to act on
8831 * Use this method to determine if the provided \c MonoClass* represents a value type,
8832 * or a reference type.
8834 * \returns TRUE if the \c MonoClass represents a \c ValueType, FALSE if it represents a reference type.
8837 mono_class_is_valuetype (MonoClass *klass)
8839 return klass->valuetype;
8843 * mono_class_is_enum:
8844 * \param klass the \c MonoClass to act on
8846 * Use this function to determine if the provided \c MonoClass* represents an enumeration.
8848 * \returns TRUE if the \c MonoClass represents an enumeration.
8851 mono_class_is_enum (MonoClass *klass)
8853 return klass->enumtype;
8857 * mono_class_enum_basetype:
8858 * \param klass the \c MonoClass to act on
8860 * Use this function to get the underlying type for an enumeration value.
8862 * \returns The underlying type representation for an enumeration.
8865 mono_class_enum_basetype (MonoClass *klass)
8867 if (klass->element_class == klass)
8868 /* SRE or broken types */
8871 return &klass->element_class->byval_arg;
8875 * mono_class_get_parent
8876 * \param klass the \c MonoClass to act on
8878 * \returns The parent class for this class.
8881 mono_class_get_parent (MonoClass *klass)
8883 return klass->parent;
8887 * mono_class_get_nesting_type:
8888 * \param klass the \c MonoClass to act on
8890 * Use this function to obtain the class that the provided \c MonoClass* is nested on.
8892 * If the return is NULL, this indicates that this class is not nested.
8894 * \returns The container type where this type is nested or NULL if this type is not a nested type.
8897 mono_class_get_nesting_type (MonoClass *klass)
8899 return klass->nested_in;
8903 * mono_class_get_rank:
8904 * \param klass the MonoClass to act on
8906 * \returns The rank for the array (the number of dimensions).
8909 mono_class_get_rank (MonoClass *klass)
8915 * mono_class_get_name
8916 * \param klass the \c MonoClass to act on
8918 * \returns The name of the class.
8921 mono_class_get_name (MonoClass *klass)
8927 * mono_class_get_namespace:
8928 * \param klass the \c MonoClass to act on
8930 * \returns The namespace of the class.
8933 mono_class_get_namespace (MonoClass *klass)
8935 return klass->name_space;
8939 * mono_class_get_type:
8940 * \param klass the \c MonoClass to act on
8942 * This method returns the internal \c MonoType representation for the class.
8944 * \returns The \c MonoType from the class.
8947 mono_class_get_type (MonoClass *klass)
8949 return &klass->byval_arg;
8953 * mono_class_get_type_token:
8954 * \param klass the \c MonoClass to act on
8956 * This method returns type token for the class.
8958 * \returns The type token for the class.
8961 mono_class_get_type_token (MonoClass *klass)
8963 return klass->type_token;
8967 * mono_class_get_byref_type:
8968 * \param klass the \c MonoClass to act on
8973 mono_class_get_byref_type (MonoClass *klass)
8975 return &klass->this_arg;
8979 * mono_class_num_fields:
8980 * \param klass the \c MonoClass to act on
8982 * \returns The number of static and instance fields in the class.
8985 mono_class_num_fields (MonoClass *klass)
8987 return mono_class_get_field_count (klass);
8991 * mono_class_num_methods:
8992 * \param klass the \c MonoClass to act on
8994 * \returns The number of methods in the class.
8997 mono_class_num_methods (MonoClass *klass)
8999 return mono_class_get_method_count (klass);
9003 * mono_class_num_properties
9004 * \param klass the \c MonoClass to act on
9006 * \returns The number of properties in the class.
9009 mono_class_num_properties (MonoClass *klass)
9011 mono_class_setup_properties (klass);
9013 return mono_class_get_property_info (klass)->count;
9017 * mono_class_num_events:
9018 * \param klass the \c MonoClass to act on
9020 * \returns The number of events in the class.
9023 mono_class_num_events (MonoClass *klass)
9025 mono_class_setup_events (klass);
9027 return mono_class_get_event_info (klass)->count;
9031 * mono_class_get_fields:
9032 * \param klass the \c MonoClass to act on
9034 * This routine is an iterator routine for retrieving the fields in a class.
9036 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9037 * iterate over all of the elements. When no more values are
9038 * available, the return value is NULL.
9040 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
9043 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9045 MonoClassField* field;
9049 mono_class_setup_fields (klass);
9050 if (mono_class_has_failure (klass))
9052 /* start from the first */
9053 if (mono_class_get_field_count (klass)) {
9054 *iter = &klass->fields [0];
9055 return &klass->fields [0];
9061 field = (MonoClassField *)*iter;
9063 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9071 * mono_class_get_methods:
9072 * \param klass the \c MonoClass to act on
9074 * This routine is an iterator routine for retrieving the fields in a class.
9076 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9077 * iterate over all of the elements. When no more values are
9078 * available, the return value is NULL.
9080 * \returns a \c MonoMethod on each iteration or NULL when no more methods are available.
9083 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9085 MonoMethod** method;
9089 mono_class_setup_methods (klass);
9092 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9093 * FIXME we should better report this error to the caller
9095 if (!klass->methods)
9097 /* start from the first */
9098 if (mono_class_get_method_count (klass)) {
9099 *iter = &klass->methods [0];
9100 return klass->methods [0];
9106 method = (MonoMethod **)*iter;
9108 if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9116 * mono_class_get_virtual_methods:
9118 * Iterate over the virtual methods of KLASS.
9120 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9123 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9125 gboolean static_iter = FALSE;
9131 * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
9132 * and the upper bits contain an index. Otherwise, the iterator is a pointer into
9135 if ((gsize)(*iter) & 1)
9137 /* Use the static metadata only if klass->methods is not yet initialized */
9138 if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
9142 MonoMethod** methodptr;
9145 mono_class_setup_methods (klass);
9147 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9148 * FIXME we should better report this error to the caller
9150 if (!klass->methods)
9152 /* start from the first */
9153 methodptr = &klass->methods [0];
9155 methodptr = (MonoMethod **)*iter;
9159 g_assert ((guint64)(*iter) > 0x100);
9160 int mcount = mono_class_get_method_count (klass);
9161 while (methodptr < &klass->methods [mcount]) {
9162 if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9166 if (methodptr < &klass->methods [mcount]) {
9173 /* Search directly in metadata to avoid calling setup_methods () */
9174 MonoMethod *res = NULL;
9180 start_index = GPOINTER_TO_UINT (*iter) >> 1;
9183 int first_idx = mono_class_get_first_method_idx (klass);
9184 int mcount = mono_class_get_method_count (klass);
9185 for (i = start_index; i < mcount; ++i) {
9188 /* first_idx points into the methodptr table */
9189 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9191 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9197 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9198 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9200 /* Add 1 here so the if (*iter) check fails */
9201 *iter = GUINT_TO_POINTER (((i + 1) << 1) | 1);
9210 * mono_class_get_properties:
9211 * \param klass the \c MonoClass to act on
9213 * This routine is an iterator routine for retrieving the properties in a class.
9215 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9216 * iterate over all of the elements. When no more values are
9217 * available, the return value is NULL.
9219 * Returns: a \c MonoProperty* on each invocation, or NULL when no more are available.
9222 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9224 MonoProperty* property;
9228 mono_class_setup_properties (klass);
9229 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9230 /* start from the first */
9232 *iter = &info->properties [0];
9233 return (MonoProperty *)*iter;
9239 property = (MonoProperty *)*iter;
9241 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9242 if (property < &info->properties [info->count]) {
9244 return (MonoProperty *)*iter;
9250 * mono_class_get_events:
9251 * \param klass the \c MonoClass to act on
9253 * This routine is an iterator routine for retrieving the properties in a class.
9255 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9256 * iterate over all of the elements. When no more values are
9257 * available, the return value is NULL.
9259 * \returns a \c MonoEvent* on each invocation, or NULL when no more are available.
9262 mono_class_get_events (MonoClass* klass, gpointer *iter)
9268 mono_class_setup_events (klass);
9269 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9270 /* start from the first */
9272 *iter = &info->events [0];
9273 return (MonoEvent *)*iter;
9279 event = (MonoEvent *)*iter;
9281 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9282 if (event < &info->events [info->count]) {
9284 return (MonoEvent *)*iter;
9290 * mono_class_get_interfaces
9291 * \param klass the \c MonoClass to act on
9293 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9295 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9296 * iterate over all of the elements. When no more values are
9297 * available, the return value is NULL.
9299 * \returns a \c MonoClass* on each invocation, or NULL when no more are available.
9302 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9310 mono_class_init (klass);
9311 if (!klass->interfaces_inited) {
9312 mono_class_setup_interfaces (klass, &error);
9313 if (!mono_error_ok (&error)) {
9314 mono_error_cleanup (&error);
9318 /* start from the first */
9319 if (klass->interface_count) {
9320 *iter = &klass->interfaces [0];
9321 return klass->interfaces [0];
9327 iface = (MonoClass **)*iter;
9329 if (iface < &klass->interfaces [klass->interface_count]) {
9337 setup_nested_types (MonoClass *klass)
9340 GList *classes, *nested_classes, *l;
9343 if (klass->nested_classes_inited)
9346 if (!klass->type_token) {
9347 mono_loader_lock ();
9348 klass->nested_classes_inited = TRUE;
9349 mono_loader_unlock ();
9353 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9357 guint32 cols [MONO_NESTED_CLASS_SIZE];
9358 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9359 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9360 if (!mono_error_ok (&error)) {
9361 /*FIXME don't swallow the error message*/
9362 mono_error_cleanup (&error);
9364 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9368 classes = g_list_prepend (classes, nclass);
9370 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9373 nested_classes = NULL;
9374 for (l = classes; l; l = l->next)
9375 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9376 g_list_free (classes);
9378 mono_loader_lock ();
9379 if (!klass->nested_classes_inited) {
9380 mono_class_set_nested_classes_property (klass, nested_classes);
9381 mono_memory_barrier ();
9382 klass->nested_classes_inited = TRUE;
9384 mono_loader_unlock ();
9388 * mono_class_get_nested_types
9389 * \param klass the \c MonoClass to act on
9391 * This routine is an iterator routine for retrieving the nested types of a class.
9392 * This works only if \p klass is non-generic, or a generic type definition.
9394 * You must pass a \c gpointer that points to zero and is treated as an opaque handle to
9395 * iterate over all of the elements. When no more values are
9396 * available, the return value is NULL.
9398 * \returns a \c Monoclass* on each invocation, or NULL when no more are available.
9401 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9407 if (!klass->nested_classes_inited)
9408 setup_nested_types (klass);
9411 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9412 /* start from the first */
9413 if (nested_classes) {
9414 *iter = nested_classes;
9415 return (MonoClass *)nested_classes->data;
9417 /* no nested types */
9421 item = (GList *)*iter;
9425 return (MonoClass *)item->data;
9432 * mono_class_is_delegate
9433 * \param klass the \c MonoClass to act on
9435 * \returns TRUE if the \c MonoClass represents a \c System.Delegate.
9438 mono_class_is_delegate (MonoClass *klass)
9440 return klass->delegate;
9444 * mono_class_implements_interface
9445 * \param klass The MonoClass to act on
9446 * \param interface The interface to check if \p klass implements.
9448 * \returns TRUE if \p klass implements \p interface.
9451 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9453 return mono_class_is_assignable_from (iface, klass);
9457 * mono_field_get_name:
9458 * \param field the \c MonoClassField to act on
9460 * \returns The name of the field.
9463 mono_field_get_name (MonoClassField *field)
9469 * mono_field_get_type:
9470 * \param field the \c MonoClassField to act on
9471 * \returns \c MonoType of the field.
9474 mono_field_get_type (MonoClassField *field)
9477 MonoType *type = mono_field_get_type_checked (field, &error);
9478 if (!mono_error_ok (&error)) {
9479 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9480 mono_error_cleanup (&error);
9487 * mono_field_get_type_checked:
9488 * \param field the \c MonoClassField to act on
9489 * \param error used to return any error found while retrieving \p field type
9491 * \returns \c MonoType of the field.
9494 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9498 mono_field_resolve_type (field, error);
9503 * mono_field_get_parent:
9504 * \param field the \c MonoClassField to act on
9506 * \returns \c MonoClass where the field was defined.
9509 mono_field_get_parent (MonoClassField *field)
9511 return field->parent;
9515 * mono_field_get_flags;
9516 * \param field the \c MonoClassField to act on
9518 * The metadata flags for a field are encoded using the
9519 * \c FIELD_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9521 * \returns The flags for the field.
9524 mono_field_get_flags (MonoClassField *field)
9527 return mono_field_resolve_flags (field);
9528 return field->type->attrs;
9532 * mono_field_get_offset:
9533 * \param field the \c MonoClassField to act on
9535 * \returns The field offset.
9538 mono_field_get_offset (MonoClassField *field)
9540 return field->offset;
9544 mono_field_get_rva (MonoClassField *field)
9548 MonoClass *klass = field->parent;
9549 MonoFieldDefaultValue *def_values;
9551 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9553 def_values = mono_class_get_field_def_values (klass);
9555 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9557 mono_class_set_field_def_values (klass, def_values);
9560 field_index = mono_field_get_index (field);
9562 if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9563 int first_field_idx = mono_class_get_first_field_idx (klass);
9564 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9566 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9567 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9570 return def_values [field_index].data;
9574 * mono_field_get_data:
9575 * \param field the \c MonoClassField to act on
9577 * \returns A pointer to the metadata constant value or to the field
9578 * data if it has an RVA flag.
9581 mono_field_get_data (MonoClassField *field)
9583 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9584 MonoTypeEnum def_type;
9586 return mono_class_get_field_default_value (field, &def_type);
9587 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9588 return mono_field_get_rva (field);
9595 * mono_property_get_name:
9596 * \param prop the \c MonoProperty to act on
9597 * \returns The name of the property
9600 mono_property_get_name (MonoProperty *prop)
9606 * mono_property_get_set_method
9607 * \param prop the \c MonoProperty to act on.
9608 * \returns The setter method of the property, a \c MonoMethod.
9611 mono_property_get_set_method (MonoProperty *prop)
9617 * mono_property_get_get_method
9618 * \param prop the MonoProperty to act on.
9619 * \returns The getter method of the property (A \c MonoMethod)
9622 mono_property_get_get_method (MonoProperty *prop)
9628 * mono_property_get_parent:
9629 * \param prop the \c MonoProperty to act on.
9630 * \returns The \c MonoClass where the property was defined.
9633 mono_property_get_parent (MonoProperty *prop)
9635 return prop->parent;
9639 * mono_property_get_flags:
9640 * \param prop the \c MonoProperty to act on.
9642 * The metadata flags for a property are encoded using the
9643 * \c PROPERTY_ATTRIBUTE_* constants. See the \c tabledefs.h file for details.
9645 * \returns The flags for the property.
9648 mono_property_get_flags (MonoProperty *prop)
9654 * mono_event_get_name:
9655 * \param event the MonoEvent to act on
9656 * \returns The name of the event.
9659 mono_event_get_name (MonoEvent *event)
9665 * mono_event_get_add_method:
9666 * \param event The \c MonoEvent to act on.
9667 * \returns The \c add method for the event, a \c MonoMethod.
9670 mono_event_get_add_method (MonoEvent *event)
9676 * mono_event_get_remove_method:
9677 * \param event The \c MonoEvent to act on.
9678 * \returns The \c remove method for the event, a \c MonoMethod.
9681 mono_event_get_remove_method (MonoEvent *event)
9683 return event->remove;
9687 * mono_event_get_raise_method:
9688 * \param event The \c MonoEvent to act on.
9689 * \returns The \c raise method for the event, a \c MonoMethod.
9692 mono_event_get_raise_method (MonoEvent *event)
9694 return event->raise;
9698 * mono_event_get_parent:
9699 * \param event the MonoEvent to act on.
9700 * \returns The \c MonoClass where the event is defined.
9703 mono_event_get_parent (MonoEvent *event)
9705 return event->parent;
9709 * mono_event_get_flags
9710 * \param event the \c MonoEvent to act on.
9712 * The metadata flags for an event are encoded using the
9713 * \c EVENT_* constants. See the \c tabledefs.h file for details.
9715 * \returns The flags for the event.
9718 mono_event_get_flags (MonoEvent *event)
9720 return event->attrs;
9724 * mono_class_get_method_from_name:
9725 * \param klass where to look for the method
9726 * \param name name of the method
9727 * \param param_count number of parameters. -1 for any number.
9729 * Obtains a \c MonoMethod with a given name and number of parameters.
9730 * It only works if there are no multiple signatures for any given method name.
9733 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9735 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9739 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9741 MonoMethod *res = NULL;
9744 /* Search directly in the metadata to avoid calling setup_methods () */
9745 int first_idx = mono_class_get_first_method_idx (klass);
9746 int mcount = mono_class_get_method_count (klass);
9747 for (i = 0; i < mcount; ++i) {
9749 guint32 cols [MONO_METHOD_SIZE];
9751 MonoMethodSignature *sig;
9753 /* first_idx points into the methodptr table */
9754 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9756 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9757 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9759 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9762 if (param_count == -1) {
9766 sig = mono_method_signature_checked (method, &error);
9768 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9771 if (sig->param_count == param_count) {
9782 * mono_class_get_method_from_name_flags:
9783 * \param klass where to look for the method
9784 * \param name_space name of the method
9785 * \param param_count number of parameters. -1 for any number.
9786 * \param flags flags which must be set in the method
9788 * Obtains a \c MonoMethod with a given name and number of parameters.
9789 * It only works if there are no multiple signatures for any given method name.
9792 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9794 MonoMethod *res = NULL;
9797 mono_class_init (klass);
9799 if (mono_class_is_ginst (klass) && !klass->methods) {
9800 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9803 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9804 if (!mono_error_ok (&error))
9805 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9810 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9811 mono_class_setup_methods (klass);
9813 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9814 See mono/tests/array_load_exception.il
9815 FIXME we should better report this error to the caller
9817 if (!klass->methods)
9819 int mcount = mono_class_get_method_count (klass);
9820 for (i = 0; i < mcount; ++i) {
9821 MonoMethod *method = klass->methods [i];
9823 if (method->name[0] == name [0] &&
9824 !strcmp (name, method->name) &&
9825 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9826 ((method->flags & flags) == flags)) {
9833 res = find_method_in_metadata (klass, name, param_count, flags);
9840 * mono_class_set_failure:
9841 * \param klass class in which the failure was detected
9842 * \param ex_type the kind of exception/error to be thrown (later)
9843 * \param ex_data exception data (specific to each type of exception/error)
9845 * Keep a detected failure informations in the class for later processing.
9846 * Note that only the first failure is kept.
9848 * LOCKING: Acquires the loader lock.
9851 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9853 g_assert (boxed_error != NULL);
9855 if (mono_class_has_failure (klass))
9858 mono_loader_lock ();
9859 klass->has_failure = 1;
9860 mono_class_set_exception_data (klass, boxed_error);
9861 mono_loader_unlock ();
9867 mono_class_has_failure (const MonoClass *klass)
9869 g_assert (klass != NULL);
9870 return klass->has_failure != 0;
9875 * mono_class_set_type_load_failure:
9876 * \param klass class in which the failure was detected
9877 * \param fmt \c printf -style error message string.
9879 * Collect detected failure informaion in the class for later processing.
9880 * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class()
9881 * Note that only the first failure is kept.
9883 * LOCKING: Acquires the loader lock.
9885 * \returns FALSE if a failure was already set on the class, or TRUE otherwise.
9888 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9890 MonoError prepare_error;
9893 if (mono_class_has_failure (klass))
9896 error_init (&prepare_error);
9898 va_start (args, fmt);
9899 mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9902 MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9903 mono_error_cleanup (&prepare_error);
9904 return mono_class_set_failure (klass, box);
9908 * mono_classes_init:
9910 * Initialize the resources used by this module.
9911 * Known racy counters: `class_gparam_count`, `classes_size` and `inflated_methods_size`
9913 MONO_NO_SANITIZE_THREAD
9915 mono_classes_init (void)
9917 mono_os_mutex_init (&classes_mutex);
9919 mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9920 mono_native_tls_alloc (&init_pending_tls_id, NULL);
9922 mono_counters_register ("MonoClassDef count",
9923 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9924 mono_counters_register ("MonoClassGtd count",
9925 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9926 mono_counters_register ("MonoClassGenericInst count",
9927 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9928 mono_counters_register ("MonoClassGenericParam count",
9929 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9930 mono_counters_register ("MonoClassArray count",
9931 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9932 mono_counters_register ("MonoClassPointer count",
9933 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9934 mono_counters_register ("Inflated methods size",
9935 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9936 mono_counters_register ("Inflated classes size",
9937 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9938 mono_counters_register ("MonoClass size",
9939 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9943 * mono_classes_cleanup:
9945 * Free the resources used by this module.
9948 mono_classes_cleanup (void)
9950 mono_native_tls_free (setup_fields_tls_id);
9951 mono_native_tls_free (init_pending_tls_id);
9953 if (global_interface_bitset)
9954 mono_bitset_free (global_interface_bitset);
9955 global_interface_bitset = NULL;
9956 mono_os_mutex_destroy (&classes_mutex);
9960 * mono_class_get_exception_for_failure:
9961 * \param klass class in which the failure was detected
9963 * \returns a constructed MonoException than the caller can then throw
9964 * using mono_raise_exception - or NULL if no failure is present (or
9965 * doesn't result in an exception).
9968 mono_class_get_exception_for_failure (MonoClass *klass)
9970 if (!mono_class_has_failure (klass))
9972 MonoError unboxed_error;
9973 error_init (&unboxed_error);
9974 mono_error_set_for_class_failure (&unboxed_error, klass);
9975 return mono_error_convert_to_exception (&unboxed_error);
9979 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9981 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9982 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9984 if (outer_klass == inner_klass)
9986 inner_klass = inner_klass->nested_in;
9987 } while (inner_klass);
9992 mono_class_get_generic_type_definition (MonoClass *klass)
9994 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
9995 return gklass ? gklass->container_class : klass;
9999 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10001 * Generic instantiations are ignored for all super types of @klass.
10003 * Visibility checks ignoring generic instantiations.
10006 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10009 klass = mono_class_get_generic_type_definition (klass);
10010 parent = mono_class_get_generic_type_definition (parent);
10011 mono_class_setup_supertypes (klass);
10013 for (i = 0; i < klass->idepth; ++i) {
10014 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10020 * Subtype can only access parent members with family protection if the site object
10021 * is subclass of Subtype. For example:
10022 * class A { protected int x; }
10024 * void valid_access () {
10028 * void invalid_access () {
10035 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10037 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10040 if (context_klass == NULL)
10042 /*if access_klass is not member_klass context_klass must be type compat*/
10043 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10049 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10052 if (accessing == accessed)
10054 if (!accessed || !accessing)
10057 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10058 * anywhere so untrusted friends are not safe to access platform's code internals */
10059 if (mono_security_core_clr_enabled ()) {
10060 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10064 mono_assembly_load_friends (accessed);
10065 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10066 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10067 /* Be conservative with checks */
10068 if (!friend_->name)
10070 if (g_ascii_strcasecmp (accessing->aname.name, friend_->name))
10072 if (friend_->public_key_token [0]) {
10073 if (!accessing->aname.public_key_token [0])
10075 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10084 * If klass is a generic type or if it is derived from a generic type, return the
10085 * MonoClass of the generic definition
10086 * Returns NULL if not found
10089 get_generic_definition_class (MonoClass *klass)
10092 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10093 if (gklass && gklass->container_class)
10094 return gklass->container_class;
10095 klass = klass->parent;
10101 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10104 for (i = 0; i < ginst->type_argc; ++i) {
10105 MonoType *type = ginst->type_argv[i];
10106 switch (type->type) {
10107 case MONO_TYPE_SZARRAY:
10108 if (!can_access_type (access_klass, type->data.klass))
10111 case MONO_TYPE_ARRAY:
10112 if (!can_access_type (access_klass, type->data.array->eklass))
10115 case MONO_TYPE_PTR:
10116 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10119 case MONO_TYPE_CLASS:
10120 case MONO_TYPE_VALUETYPE:
10121 case MONO_TYPE_GENERICINST:
10122 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10132 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10136 if (access_klass == member_klass)
10139 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10142 if (access_klass->element_class && !access_klass->enumtype)
10143 access_klass = access_klass->element_class;
10145 if (member_klass->element_class && !member_klass->enumtype)
10146 member_klass = member_klass->element_class;
10148 access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10150 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10153 if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10156 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10159 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10162 /*Non nested type with nested visibility. We just fail it.*/
10163 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10166 switch (access_level) {
10167 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10168 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10170 case TYPE_ATTRIBUTE_PUBLIC:
10173 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10176 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10177 return is_nesting_type (member_klass, access_klass);
10179 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10180 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10182 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10183 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10185 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10186 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10187 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10189 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10190 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10191 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10196 /* FIXME: check visibility of type, too */
10198 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10200 MonoClass *member_generic_def;
10201 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10204 MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10205 if (((access_gklass && access_gklass->container_class) ||
10206 mono_class_is_gtd (access_klass)) &&
10207 (member_generic_def = get_generic_definition_class (member_klass))) {
10208 MonoClass *access_container;
10210 if (mono_class_is_gtd (access_klass))
10211 access_container = access_klass;
10213 access_container = access_gklass->container_class;
10215 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10219 /* Partition I 8.5.3.2 */
10220 /* the access level values are the same for fields and methods */
10221 switch (access_level) {
10222 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10223 /* same compilation unit */
10224 return access_klass->image == member_klass->image;
10225 case FIELD_ATTRIBUTE_PRIVATE:
10226 return access_klass == member_klass;
10227 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10228 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10229 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10232 case FIELD_ATTRIBUTE_ASSEMBLY:
10233 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10234 case FIELD_ATTRIBUTE_FAMILY:
10235 if (is_valid_family_access (access_klass, member_klass, context_klass))
10238 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10239 if (is_valid_family_access (access_klass, member_klass, context_klass))
10241 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10242 case FIELD_ATTRIBUTE_PUBLIC:
10249 * mono_method_can_access_field:
10250 * \param method Method that will attempt to access the field
10251 * \param field the field to access
10253 * Used to determine if a method is allowed to access the specified field.
10255 * \returns TRUE if the given \p method is allowed to access the \p field while following
10256 * the accessibility rules of the CLI.
10259 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10261 /* FIXME: check all overlapping fields */
10262 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10264 MonoClass *nested = method->klass->nested_in;
10266 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10269 nested = nested->nested_in;
10276 * mono_method_can_access_method:
10277 * \param method Method that will attempt to access the other method
10278 * \param called the method that we want to probe for accessibility.
10280 * Used to determine if the \p method is allowed to access the specified \p called method.
10282 * \returns TRUE if the given \p method is allowed to invoke the \p called while following
10283 * the accessibility rules of the CLI.
10286 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10288 method = mono_method_get_method_definition (method);
10289 called = mono_method_get_method_definition (called);
10290 return mono_method_can_access_method_full (method, called, NULL);
10294 * mono_method_can_access_method_full:
10295 * @method: The caller method
10296 * @called: The called method
10297 * @context_klass: The static type on stack of the owner @called object used
10299 * This function must be used with instance calls, as they have more strict family accessibility.
10300 * It can be used with static methods, but context_klass should be NULL.
10302 * Returns: TRUE if caller have proper visibility and acessibility to @called
10305 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10307 /* Wrappers are except from access checks */
10308 if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10311 MonoClass *access_class = method->klass;
10312 MonoClass *member_class = called->klass;
10313 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10315 MonoClass *nested = access_class->nested_in;
10317 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10320 nested = nested->nested_in;
10327 can = can_access_type (access_class, member_class);
10329 MonoClass *nested = access_class->nested_in;
10331 can = can_access_type (nested, member_class);
10334 nested = nested->nested_in;
10341 if (called->is_inflated) {
10342 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10343 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10352 * mono_method_can_access_field_full:
10353 * @method: The caller method
10354 * @field: The accessed field
10355 * @context_klass: The static type on stack of the owner @field object used
10357 * This function must be used with instance fields, as they have more strict family accessibility.
10358 * It can be used with static fields, but context_klass should be NULL.
10360 * Returns: TRUE if caller have proper visibility and acessibility to @field
10363 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10365 MonoClass *access_class = method->klass;
10366 MonoClass *member_class = field->parent;
10367 /* FIXME: check all overlapping fields */
10368 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10370 MonoClass *nested = access_class->nested_in;
10372 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10375 nested = nested->nested_in;
10382 can = can_access_type (access_class, member_class);
10384 MonoClass *nested = access_class->nested_in;
10386 can = can_access_type (nested, member_class);
10389 nested = nested->nested_in;
10399 * mono_class_can_access_class:
10400 * @source_class: The source class
10401 * @target_class: The accessed class
10403 * This function returns is @target_class is visible to @source_class
10405 * Returns: TRUE if source have proper visibility and acessibility to target
10408 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10410 return can_access_type (source_class, target_class);
10414 * mono_type_is_valid_enum_basetype:
10415 * \param type The MonoType to check
10416 * \returns TRUE if the type can be used as the basetype of an enum
10418 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10419 switch (type->type) {
10422 case MONO_TYPE_BOOLEAN:
10425 case MONO_TYPE_CHAR:
10439 * mono_class_is_valid_enum:
10440 * \param klass An enum class to be validated
10442 * This method verify the required properties an enum should have.
10444 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10445 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10446 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10448 * \returns TRUE if the informed enum class is valid
10451 mono_class_is_valid_enum (MonoClass *klass)
10453 MonoClassField * field;
10454 gpointer iter = NULL;
10455 gboolean found_base_field = FALSE;
10457 g_assert (klass->enumtype);
10458 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10459 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10463 if (!mono_class_is_auto_layout (klass))
10466 while ((field = mono_class_get_fields (klass, &iter))) {
10467 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10468 if (found_base_field)
10470 found_base_field = TRUE;
10471 if (!mono_type_is_valid_enum_basetype (field->type))
10476 if (!found_base_field)
10479 if (mono_class_get_method_count (klass) > 0)
10486 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10488 return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10492 * mono_class_setup_interface_id:
10494 * Initializes MonoClass::interface_id if required.
10496 * LOCKING: Acquires the loader lock.
10499 mono_class_setup_interface_id (MonoClass *klass)
10501 mono_loader_lock ();
10502 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10503 klass->interface_id = mono_get_unique_iid (klass);
10504 mono_loader_unlock ();
10508 * mono_class_setup_interfaces:
10510 * Initialize klass->interfaces/interfaces_count.
10511 * LOCKING: Acquires the loader lock.
10512 * This function can fail the type.
10515 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10517 int i, interface_count;
10518 MonoClass **interfaces;
10520 error_init (error);
10522 if (klass->interfaces_inited)
10525 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10526 MonoType *args [1];
10528 /* generic IList, ICollection, IEnumerable */
10529 interface_count = 2;
10530 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10532 args [0] = &klass->element_class->byval_arg;
10533 interfaces [0] = mono_class_bind_generic_parameters (
10534 mono_defaults.generic_ilist_class, 1, args, FALSE);
10535 interfaces [1] = mono_class_bind_generic_parameters (
10536 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10537 } else if (mono_class_is_ginst (klass)) {
10538 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10540 mono_class_setup_interfaces (gklass, error);
10541 if (!mono_error_ok (error)) {
10542 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10546 interface_count = gklass->interface_count;
10547 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10548 for (i = 0; i < interface_count; i++) {
10549 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10550 if (!mono_error_ok (error)) {
10551 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10556 interface_count = 0;
10560 mono_loader_lock ();
10561 if (!klass->interfaces_inited) {
10562 klass->interface_count = interface_count;
10563 klass->interfaces = interfaces;
10565 mono_memory_barrier ();
10567 klass->interfaces_inited = TRUE;
10569 mono_loader_unlock ();
10573 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10575 MonoClass *klass = field->parent;
10576 MonoImage *image = klass->image;
10577 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10579 int field_idx = field - klass->fields;
10581 error_init (error);
10584 MonoClassField *gfield = >d->fields [field_idx];
10585 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10586 if (!mono_error_ok (error)) {
10587 char *full_name = mono_type_get_full_name (gtd);
10588 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));
10589 g_free (full_name);
10592 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10593 if (!mono_error_ok (error)) {
10594 char *full_name = mono_type_get_full_name (klass);
10595 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));
10596 g_free (full_name);
10600 guint32 cols [MONO_FIELD_SIZE];
10601 MonoGenericContainer *container = NULL;
10602 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10604 /*FIXME, in theory we do not lazy load SRE fields*/
10605 g_assert (!image_is_dynamic (image));
10607 if (mono_class_is_gtd (klass)) {
10608 container = mono_class_get_generic_container (klass);
10610 container = mono_class_get_generic_container (gtd);
10611 g_assert (container);
10614 /* first_field_idx and idx points into the fieldptr table */
10615 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10617 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10618 char *full_name = mono_type_get_full_name (klass);
10619 mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10620 mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10621 g_free (full_name);
10625 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10627 mono_metadata_decode_value (sig, &sig);
10628 /* FIELD signature == 0x06 */
10629 g_assert (*sig == 0x06);
10631 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10633 char *full_name = mono_type_get_full_name (klass);
10634 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));
10635 g_free (full_name);
10638 mono_memory_barrier ();
10639 field->type = ftype;
10643 mono_field_resolve_flags (MonoClassField *field)
10645 MonoClass *klass = field->parent;
10646 MonoImage *image = klass->image;
10647 MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10648 int field_idx = field - klass->fields;
10651 MonoClassField *gfield = >d->fields [field_idx];
10652 return mono_field_get_flags (gfield);
10654 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10656 /*FIXME, in theory we do not lazy load SRE fields*/
10657 g_assert (!image_is_dynamic (image));
10659 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10664 * mono_class_get_fields_lazy:
10665 * \param klass the MonoClass to act on
10667 * This routine is an iterator routine for retrieving the fields in a class.
10668 * Only minimal information about fields are loaded. Accessors must be used
10669 * for all MonoClassField returned.
10671 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10672 * iterate over all of the elements. When no more values are
10673 * available, the return value is NULL.
10675 * \returns a \c MonoClassField* on each iteration, or NULL when no more fields are available.
10678 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10680 MonoClassField* field;
10684 mono_class_setup_basic_field_info (klass);
10685 if (!klass->fields)
10687 /* start from the first */
10688 if (mono_class_get_field_count (klass)) {
10689 *iter = &klass->fields [0];
10690 return (MonoClassField *)*iter;
10696 field = (MonoClassField *)*iter;
10698 if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10700 return (MonoClassField *)*iter;
10706 mono_class_full_name (MonoClass *klass)
10708 return mono_type_full_name (&klass->byval_arg);
10711 /* Declare all shared lazy type lookup functions */
10712 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, "System.Runtime.InteropServices", "SafeHandle")
10715 * mono_method_get_base_method:
10716 * \param method a method
10717 * \param definition if true, get the definition
10718 * \param error set on failure
10720 * Given a virtual method associated with a subclass, return the corresponding
10721 * method from an ancestor. If \p definition is FALSE, returns the method in the
10722 * superclass of the given method. If \p definition is TRUE, return the method
10723 * in the ancestor class where it was first declared. The type arguments will
10724 * be inflated in the ancestor classes. If the method is not associated with a
10725 * class, or isn't virtual, returns the method itself. On failure returns NULL
10726 * and sets \p error.
10729 mono_method_get_base_method (MonoMethod *method, gboolean definition, MonoError *error)
10731 MonoClass *klass, *parent;
10732 MonoGenericContext *generic_inst = NULL;
10733 MonoMethod *result = NULL;
10736 if (method->klass == NULL)
10739 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
10740 MONO_CLASS_IS_INTERFACE (method->klass) ||
10741 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
10744 slot = mono_method_get_vtable_slot (method);
10748 klass = method->klass;
10749 if (mono_class_is_ginst (klass)) {
10750 generic_inst = mono_class_get_context (klass);
10751 klass = mono_class_get_generic_class (klass)->container_class;
10756 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
10757 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
10758 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
10759 or klass is the generic container class and generic_inst is the instantiation.
10761 when we go to the parent, if the parent is an open constructed type, we need to
10762 replace the type parameters by the definitions from the generic_inst, and then take it
10763 apart again into the klass and the generic_inst.
10765 For cases like this:
10766 class C<T> : B<T, int> {
10767 public override void Foo () { ... }
10769 class B<U,V> : A<HashMap<U,V>> {
10770 public override void Foo () { ... }
10773 public virtual void Foo () { ... }
10776 if at each iteration the parent isn't open, we can skip inflating it. if at some
10777 iteration the parent isn't generic (after possible inflation), we set generic_inst to
10780 MonoGenericContext *parent_inst = NULL;
10781 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
10782 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, error);
10783 return_val_if_nok (error, NULL);
10785 if (mono_class_is_ginst (parent)) {
10786 parent_inst = mono_class_get_context (parent);
10787 parent = mono_class_get_generic_class (parent)->container_class;
10790 mono_class_setup_vtable (parent);
10791 if (parent->vtable_size <= slot)
10794 generic_inst = parent_inst;
10797 klass = klass->parent;
10800 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
10801 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10802 return_val_if_nok (error, NULL);
10804 generic_inst = NULL;
10806 if (mono_class_is_ginst (klass)) {
10807 generic_inst = mono_class_get_context (klass);
10808 klass = mono_class_get_generic_class (klass)->container_class;
10813 if (generic_inst) {
10814 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, error);
10815 return_val_if_nok (error, NULL);
10818 if (klass == method->klass)
10821 /*This is possible if definition == FALSE.
10822 * Do it here to be really sure we don't read invalid memory.
10824 if (slot >= klass->vtable_size)
10827 mono_class_setup_vtable (klass);
10829 result = klass->vtable [slot];
10830 if (result == NULL) {
10831 /* It is an abstract method */
10832 gboolean found = FALSE;
10833 gpointer iter = NULL;
10834 while ((result = mono_class_get_methods (klass, &iter))) {
10835 if (result->slot == slot) {
10840 /* found might be FALSE if we looked in an abstract class
10841 * that doesn't override an abstract method of its
10843 * abstract class Base {
10844 * public abstract void Foo ();
10846 * abstract class Derived : Base { }
10847 * class Child : Derived {
10848 * public override void Foo () { }
10851 * if m was Child.Foo and we ask for the base method,
10852 * then we get here with klass == Derived and found == FALSE
10854 /* but it shouldn't be the case that if we're looking
10855 * for the definition and didn't find a result; the
10856 * loop above should've taken us as far as we could
10858 g_assert (!(definition && !found));
10863 g_assert (result != NULL);