2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internals.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internals.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
50 gboolean mono_align_small_structs = FALSE;
53 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
54 guint32 classes_size, class_ext_size;
56 /* Low level lock which protects data structures in this module */
57 static mono_mutex_t classes_mutex;
59 /* Function supplied by the runtime to find classes by name using information from the AOT file */
60 static MonoGetClassFromName get_class_from_name = NULL;
62 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
63 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
64 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
65 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
66 static int generic_array_methods (MonoClass *klass);
67 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
69 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
70 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
71 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
72 static guint32 mono_field_resolve_flags (MonoClassField *field);
73 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
74 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation;
100 static GSList *gclass_recorded_list;
101 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
106 mono_locks_os_acquire (&classes_mutex, ClassesLock);
110 classes_unlock (void)
112 mono_locks_os_release (&classes_mutex, ClassesLock);
116 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
119 enable_gclass_recording (void)
121 ++record_gclass_instantiation;
125 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
128 disable_gclass_recording (gclass_record_func func, void *user_data)
130 GSList **head = &gclass_recorded_list;
132 g_assert (record_gclass_instantiation > 0);
133 --record_gclass_instantiation;
136 GSList *node = *head;
137 if (func ((MonoClass*)node->data, user_data)) {
139 g_slist_free_1 (node);
145 /* We automatically discard all recorded gclasses when disabled. */
146 if (!record_gclass_instantiation && gclass_recorded_list) {
147 g_slist_free (gclass_recorded_list);
148 gclass_recorded_list = NULL;
153 * mono_class_from_typeref:
154 * @image: a MonoImage
155 * @type_token: a TypeRef token
157 * Creates the MonoClass* structure representing the type defined by
158 * the typeref token valid inside @image.
159 * Returns: the MonoClass* representing the typeref token, NULL ifcould
163 mono_class_from_typeref (MonoImage *image, guint32 type_token)
166 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
167 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
172 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
174 guint32 cols [MONO_TYPEREF_SIZE];
175 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
177 const char *name, *nspace;
178 MonoClass *res = NULL;
181 mono_error_init (error);
183 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
186 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
188 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
189 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
191 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
192 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
193 case MONO_RESOLUTION_SCOPE_MODULE:
195 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
196 This is not the observed behavior of existing implementations.
197 The defacto behavior is that it's just a typedef in disguise.
199 /* a typedef in disguise */
200 res = mono_class_from_name_checked (image, nspace, name, error);
203 case MONO_RESOLUTION_SCOPE_MODULEREF:
204 module = mono_image_load_module (image, idx);
206 res = mono_class_from_name_checked (module, nspace, name, error);
209 case MONO_RESOLUTION_SCOPE_TYPEREF: {
210 MonoClass *enclosing;
213 if (idx == mono_metadata_token_index (type_token)) {
214 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
218 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
219 if (!mono_error_ok (error))
222 if (enclosing->nested_classes_inited && enclosing->ext) {
223 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
224 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
226 if (strcmp (res->name, name) == 0)
230 /* Don't call mono_class_init as we might've been called by it recursively */
231 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
233 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
234 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
235 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
237 if (strcmp (nname, name) == 0)
238 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
240 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
243 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
246 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
250 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
251 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
255 if (!image->references || !image->references [idx - 1])
256 mono_assembly_load_reference (image, idx - 1);
257 g_assert (image->references [idx - 1]);
259 /* If the assembly did not load, register this as a type load exception */
260 if (image->references [idx - 1] == REFERENCE_MISSING){
261 MonoAssemblyName aname;
264 mono_assembly_get_assemblyref (image, idx - 1, &aname);
265 human_name = mono_stringify_assembly_name (&aname);
266 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
270 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
273 /* Generic case, should be avoided for when a better error is possible. */
274 if (!res && mono_error_ok (error)) {
275 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
276 mono_error_set_from_loader_error (error);
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
283 mono_loader_assert_no_error ();
289 mono_image_memdup (MonoImage *image, void *data, guint size)
291 void *res = mono_image_alloc (image, size);
292 memcpy (res, data, size);
296 /* Copy everything mono_metadata_free_array free. */
298 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
301 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
303 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
307 a = g_memdup (a, sizeof (MonoArrayType));
309 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
311 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
316 /* Copy everything mono_metadata_free_method_signature free. */
318 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
322 sig = mono_metadata_signature_dup_full (image, sig);
324 sig->ret = mono_metadata_type_dup (image, sig->ret);
325 for (i = 0; i < sig->param_count; ++i)
326 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
332 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
334 MonoAssembly *ta = klass->image->assembly;
337 name = mono_stringify_assembly_name (&ta->aname);
338 g_string_append_printf (str, ", %s", name);
343 mono_type_name_check_byref (MonoType *type, GString *str)
346 g_string_append_c (str, '&');
350 * mono_identifier_escape_type_name_chars:
351 * @str: a destination string
352 * @identifier: an IDENTIFIER in internal form
356 * The displayed form of the identifier is appended to str.
358 * The displayed form of an identifier has the characters ,+&*[]\
359 * that have special meaning in type names escaped with a preceeding
360 * backslash (\) character.
363 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
369 // reserve space for common case: there will be no escaped characters.
370 g_string_set_size(str, n + strlen(identifier));
371 g_string_set_size(str, n);
373 for (const char* s = identifier; *s != 0 ; s++) {
382 g_string_append_c (str, '\\');
383 g_string_append_c (str, *s);
386 g_string_append_c (str, *s);
394 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
395 MonoTypeNameFormat format)
399 switch (type->type) {
400 case MONO_TYPE_ARRAY: {
401 int i, rank = type->data.array->rank;
402 MonoTypeNameFormat nested_format;
404 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
405 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
407 mono_type_get_name_recurse (
408 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
409 g_string_append_c (str, '[');
411 g_string_append_c (str, '*');
412 for (i = 1; i < rank; i++)
413 g_string_append_c (str, ',');
414 g_string_append_c (str, ']');
416 mono_type_name_check_byref (type, str);
418 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
419 _mono_type_get_assembly_name (type->data.array->eklass, str);
422 case MONO_TYPE_SZARRAY: {
423 MonoTypeNameFormat nested_format;
425 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
426 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
428 mono_type_get_name_recurse (
429 &type->data.klass->byval_arg, str, FALSE, nested_format);
430 g_string_append (str, "[]");
432 mono_type_name_check_byref (type, str);
434 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
435 _mono_type_get_assembly_name (type->data.klass, str);
438 case MONO_TYPE_PTR: {
439 MonoTypeNameFormat nested_format;
441 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
442 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
444 mono_type_get_name_recurse (
445 type->data.type, str, FALSE, nested_format);
446 g_string_append_c (str, '*');
448 mono_type_name_check_byref (type, str);
450 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
451 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
456 if (!mono_generic_param_info (type->data.generic_param))
457 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
459 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
461 mono_type_name_check_byref (type, str);
465 klass = mono_class_from_mono_type (type);
466 if (klass->nested_in) {
467 mono_type_get_name_recurse (
468 &klass->nested_in->byval_arg, str, TRUE, format);
469 if (format == MONO_TYPE_NAME_FORMAT_IL)
470 g_string_append_c (str, '.');
472 g_string_append_c (str, '+');
473 } else if (*klass->name_space) {
474 if (format == MONO_TYPE_NAME_FORMAT_IL)
475 g_string_append (str, klass->name_space);
477 mono_identifier_escape_type_name_chars (str, klass->name_space);
478 g_string_append_c (str, '.');
480 if (format == MONO_TYPE_NAME_FORMAT_IL) {
481 char *s = strchr (klass->name, '`');
482 int len = s ? s - klass->name : strlen (klass->name);
483 g_string_append_len (str, klass->name, len);
485 mono_identifier_escape_type_name_chars (str, klass->name);
489 if (klass->generic_class) {
490 MonoGenericClass *gclass = klass->generic_class;
491 MonoGenericInst *inst = gclass->context.class_inst;
492 MonoTypeNameFormat nested_format;
495 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
496 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
498 if (format == MONO_TYPE_NAME_FORMAT_IL)
499 g_string_append_c (str, '<');
501 g_string_append_c (str, '[');
502 for (i = 0; i < inst->type_argc; i++) {
503 MonoType *t = inst->type_argv [i];
506 g_string_append_c (str, ',');
507 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
508 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
509 g_string_append_c (str, '[');
510 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
511 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
512 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
513 g_string_append_c (str, ']');
515 if (format == MONO_TYPE_NAME_FORMAT_IL)
516 g_string_append_c (str, '>');
518 g_string_append_c (str, ']');
519 } else if (klass->generic_container &&
520 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
521 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
524 if (format == MONO_TYPE_NAME_FORMAT_IL)
525 g_string_append_c (str, '<');
527 g_string_append_c (str, '[');
528 for (i = 0; i < klass->generic_container->type_argc; i++) {
530 g_string_append_c (str, ',');
531 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
533 if (format == MONO_TYPE_NAME_FORMAT_IL)
534 g_string_append_c (str, '>');
536 g_string_append_c (str, ']');
539 mono_type_name_check_byref (type, str);
541 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
542 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
543 _mono_type_get_assembly_name (klass, str);
549 * mono_type_get_name_full:
551 * @format: the format for the return string.
554 * Returns: the string representation in a number of formats:
556 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
557 * returned in the formatrequired by System.Reflection, this is the
558 * inverse of mono_reflection_parse_type ().
560 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
561 * be used by the IL assembler.
563 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
565 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
568 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
572 result = g_string_new ("");
574 mono_type_get_name_recurse (type, result, FALSE, format);
576 return g_string_free (result, FALSE);
580 * mono_type_get_full_name:
583 * Returns: the string representation for type as required by System.Reflection.
584 * The inverse of mono_reflection_parse_type ().
587 mono_type_get_full_name (MonoClass *klass)
589 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
593 * mono_type_get_name:
596 * Returns: the string representation for type as it would be represented in IL code.
599 mono_type_get_name (MonoType *type)
601 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
605 * mono_type_get_underlying_type:
608 * Returns: the MonoType for the underlying integer type if @type
609 * is an enum and byref is false, otherwise the type itself.
612 mono_type_get_underlying_type (MonoType *type)
614 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
615 return mono_class_enum_basetype (type->data.klass);
616 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
617 return mono_class_enum_basetype (type->data.generic_class->container_class);
622 * mono_class_is_open_constructed_type:
625 * Returns TRUE if type represents a generics open constructed type.
626 * IOW, not all type parameters required for the instantiation have
627 * been provided or it's a generic type definition.
629 * An open constructed type means it's a non realizable type. Not to
630 * be mixed up with an abstract type - we can't cast or dispatch to
631 * an open type, for example.
634 mono_class_is_open_constructed_type (MonoType *t)
640 case MONO_TYPE_SZARRAY:
641 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
642 case MONO_TYPE_ARRAY:
643 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
645 return mono_class_is_open_constructed_type (t->data.type);
646 case MONO_TYPE_GENERICINST:
647 return t->data.generic_class->context.class_inst->is_open;
648 case MONO_TYPE_CLASS:
649 case MONO_TYPE_VALUETYPE:
650 return t->data.klass->generic_container != NULL;
657 This is a simple function to catch the most common bad instances of generic types.
658 Specially those that might lead to further failures in the runtime.
661 is_valid_generic_argument (MonoType *type)
663 switch (type->type) {
665 //case MONO_TYPE_TYPEDBYREF:
673 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
675 mono_error_init (error);
677 switch (type->type) {
678 case MONO_TYPE_MVAR: {
680 int num = mono_type_get_generic_param_num (type);
681 MonoGenericInst *inst = context->method_inst;
684 if (num >= inst->type_argc) {
685 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
686 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
687 num, info ? info->name : "", inst->type_argc);
691 if (!is_valid_generic_argument (inst->type_argv [num])) {
692 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
693 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
694 num, info ? info->name : "", inst->type_argv [num]->type);
698 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
699 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
700 * ->byref and ->attrs from @type are propagated to the returned type.
702 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
703 nt->byref = type->byref;
704 nt->attrs = type->attrs;
707 case MONO_TYPE_VAR: {
709 int num = mono_type_get_generic_param_num (type);
710 MonoGenericInst *inst = context->class_inst;
713 if (num >= inst->type_argc) {
714 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
715 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
716 num, info ? info->name : "", inst->type_argc);
719 if (!is_valid_generic_argument (inst->type_argv [num])) {
720 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
721 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
722 num, info ? info->name : "", inst->type_argv [num]->type);
725 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
726 nt->byref = type->byref;
727 nt->attrs = type->attrs;
730 case MONO_TYPE_SZARRAY: {
731 MonoClass *eclass = type->data.klass;
732 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
733 if (!inflated || !mono_error_ok (error))
735 nt = mono_metadata_type_dup (image, type);
736 nt->data.klass = mono_class_from_mono_type (inflated);
737 mono_metadata_free_type (inflated);
740 case MONO_TYPE_ARRAY: {
741 MonoClass *eclass = type->data.array->eklass;
742 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
743 if (!inflated || !mono_error_ok (error))
745 nt = mono_metadata_type_dup (image, type);
746 nt->data.array->eklass = mono_class_from_mono_type (inflated);
747 mono_metadata_free_type (inflated);
750 case MONO_TYPE_GENERICINST: {
751 MonoGenericClass *gclass = type->data.generic_class;
752 MonoGenericInst *inst;
754 if (!gclass->context.class_inst->is_open)
757 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
758 if (!mono_error_ok (error))
760 if (inst != gclass->context.class_inst)
761 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
763 if (gclass == type->data.generic_class)
766 nt = mono_metadata_type_dup (image, type);
767 nt->data.generic_class = gclass;
770 case MONO_TYPE_CLASS:
771 case MONO_TYPE_VALUETYPE: {
772 MonoClass *klass = type->data.klass;
773 MonoGenericContainer *container = klass->generic_container;
774 MonoGenericInst *inst;
775 MonoGenericClass *gclass = NULL;
781 /* We can't use context->class_inst directly, since it can have more elements */
782 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
783 if (!mono_error_ok (error))
785 if (inst == container->context.class_inst)
788 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
790 nt = mono_metadata_type_dup (image, type);
791 nt->type = MONO_TYPE_GENERICINST;
792 nt->data.generic_class = gclass;
802 mono_generic_class_get_context (MonoGenericClass *gclass)
804 return &gclass->context;
808 mono_class_get_context (MonoClass *klass)
810 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
814 * mono_class_get_generic_container:
816 * Return the generic container of KLASS which should be a generic type definition.
818 MonoGenericContainer*
819 mono_class_get_generic_container (MonoClass *klass)
821 g_assert (klass->is_generic);
823 return klass->generic_container;
827 * mono_class_get_generic_class:
829 * Return the MonoGenericClass of KLASS, which should be a generic instance.
832 mono_class_get_generic_class (MonoClass *klass)
834 g_assert (klass->is_inflated);
836 return klass->generic_class;
840 * mono_class_inflate_generic_type_with_mempool:
841 * @mempool: a mempool
843 * @context: a generics context
844 * @error: error context
846 * The same as mono_class_inflate_generic_type, but allocates the MonoType
847 * from mempool if it is non-NULL. If it is NULL, the MonoType is
848 * allocated on the heap and is owned by the caller.
849 * The returned type can potentially be the same as TYPE, so it should not be
850 * modified by the caller, and it should be freed using mono_metadata_free_type ().
853 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
855 MonoType *inflated = NULL;
856 mono_error_init (error);
859 inflated = inflate_generic_type (image, type, context, error);
860 if (!mono_error_ok (error))
864 MonoType *shared = mono_metadata_get_shared_type (type);
869 return mono_metadata_type_dup (image, type);
873 mono_stats.inflated_type_count++;
878 * mono_class_inflate_generic_type:
880 * @context: a generics context
882 * If @type is a generic type and @context is not NULL, instantiate it using the
883 * generics context @context.
885 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
886 * on the heap and is owned by the caller. Returns NULL on error.
888 * @deprecated Please use mono_class_inflate_generic_type_checked instead
891 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
895 result = mono_class_inflate_generic_type_checked (type, context, &error);
897 if (!mono_error_ok (&error)) {
898 mono_error_cleanup (&error);
905 * mono_class_inflate_generic_type:
907 * @context: a generics context
908 * @error: error context to use
910 * If @type is a generic type and @context is not NULL, instantiate it using the
911 * generics context @context.
913 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
914 * on the heap and is owned by the caller.
917 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
919 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
923 * mono_class_inflate_generic_type_no_copy:
925 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
929 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
931 MonoType *inflated = NULL;
933 mono_error_init (error);
935 inflated = inflate_generic_type (image, type, context, error);
936 if (!mono_error_ok (error))
943 mono_stats.inflated_type_count++;
948 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
953 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
954 if (!mono_error_ok (error))
957 res = mono_class_from_mono_type (inflated);
958 mono_metadata_free_type (inflated);
963 * mono_class_inflate_generic_class:
965 * Inflate the class GKLASS with CONTEXT.
968 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
973 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
974 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
981 static MonoGenericContext
982 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
984 MonoGenericInst *class_inst = NULL;
985 MonoGenericInst *method_inst = NULL;
986 MonoGenericContext res = { NULL, NULL };
988 mono_error_init (error);
990 if (context->class_inst) {
991 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
992 if (!mono_error_ok (error))
996 if (context->method_inst) {
997 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
998 if (!mono_error_ok (error))
1002 res.class_inst = class_inst;
1003 res.method_inst = method_inst;
1009 * mono_class_inflate_generic_method:
1010 * @method: a generic method
1011 * @context: a generics context
1013 * Instantiate the generic method @method using the generics context @context.
1015 * Returns: the new instantiated method
1018 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1020 return mono_class_inflate_generic_method_full (method, NULL, context);
1024 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1026 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1030 * mono_class_inflate_generic_method_full:
1032 * Instantiate method @method with the generic context @context.
1033 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1034 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1037 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1040 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1041 if (!mono_error_ok (&error))
1042 /*FIXME do proper error handling - on this case, kill this function. */
1043 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1049 * mono_class_inflate_generic_method_full_checked:
1050 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1053 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1056 MonoMethodInflated *iresult, *cached;
1057 MonoMethodSignature *sig;
1058 MonoGenericContext tmp_context;
1060 mono_error_init (error);
1062 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1063 while (method->is_inflated) {
1064 MonoGenericContext *method_context = mono_method_get_context (method);
1065 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1067 tmp_context = inflate_generic_context (method_context, context, error);
1068 if (!mono_error_ok (error))
1070 context = &tmp_context;
1072 if (mono_metadata_generic_context_equal (method_context, context))
1075 method = imethod->declaring;
1079 * A method only needs to be inflated if the context has argument for which it is
1082 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1083 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1086 if (!((method->is_generic && context->method_inst) ||
1087 (method->klass->generic_container && context->class_inst)))
1090 iresult = g_new0 (MonoMethodInflated, 1);
1091 iresult->context = *context;
1092 iresult->declaring = method;
1094 if (!context->method_inst && method->is_generic)
1095 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1097 if (!context->class_inst) {
1098 g_assert (!iresult->declaring->klass->generic_class);
1099 if (iresult->declaring->klass->generic_container)
1100 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1101 else if (iresult->declaring->klass->generic_class)
1102 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1104 /* This can happen with some callers like mono_object_get_virtual_method () */
1105 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1106 iresult->context.class_inst = NULL;
1108 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1111 mono_image_set_lock (set);
1112 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1113 mono_image_set_unlock (set);
1117 return (MonoMethod*)cached;
1120 mono_stats.inflated_method_count++;
1122 inflated_methods_size += sizeof (MonoMethodInflated);
1124 sig = mono_method_signature (method);
1126 char *name = mono_type_get_full_name (method->klass);
1127 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1133 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1135 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1138 result = (MonoMethod *) iresult;
1139 result->is_inflated = TRUE;
1140 result->is_generic = FALSE;
1141 result->sre_method = FALSE;
1142 result->signature = NULL;
1144 if (!context->method_inst) {
1145 /* Set the generic_container of the result to the generic_container of method */
1146 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1148 if (generic_container) {
1149 result->is_generic = 1;
1150 mono_method_set_generic_container (result, generic_container);
1154 if (!klass_hint || !klass_hint->generic_class ||
1155 klass_hint->generic_class->container_class != method->klass ||
1156 klass_hint->generic_class->context.class_inst != context->class_inst)
1159 if (method->klass->generic_container)
1160 result->klass = klass_hint;
1162 if (!result->klass) {
1163 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1164 if (!mono_error_ok (error))
1167 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1169 mono_metadata_free_type (inflated);
1173 * FIXME: This should hold, but it doesn't:
1175 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1176 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1177 * g_assert (result->is_generic);
1180 * Fixing this here causes other things to break, hence a very
1181 * ugly hack in mini-trampolines.c - see
1182 * is_generic_method_definition().
1186 mono_image_set_lock (set);
1187 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1189 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1190 iresult->owner = set;
1193 mono_image_set_unlock (set);
1195 return (MonoMethod*)cached;
1203 * mono_get_inflated_method:
1205 * Obsolete. We keep it around since it's mentioned in the public API.
1208 mono_get_inflated_method (MonoMethod *method)
1214 * mono_method_get_context_general:
1216 * @uninflated: handle uninflated methods?
1218 * Returns the generic context of a method or NULL if it doesn't have
1219 * one. For an inflated method that's the context stored in the
1220 * method. Otherwise it's in the method's generic container or in the
1221 * generic container of the method's class.
1224 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1226 if (method->is_inflated) {
1227 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1228 return &imethod->context;
1232 if (method->is_generic)
1233 return &(mono_method_get_generic_container (method)->context);
1234 if (method->klass->generic_container)
1235 return &method->klass->generic_container->context;
1240 * mono_method_get_context:
1243 * Returns the generic context for method if it's inflated, otherwise
1247 mono_method_get_context (MonoMethod *method)
1249 return mono_method_get_context_general (method, FALSE);
1253 * mono_method_get_generic_container:
1255 * Returns the generic container of METHOD, which should be a generic method definition.
1256 * Returns NULL if METHOD is not a generic method definition.
1257 * LOCKING: Acquires the loader lock.
1259 MonoGenericContainer*
1260 mono_method_get_generic_container (MonoMethod *method)
1262 MonoGenericContainer *container;
1264 if (!method->is_generic)
1267 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1268 g_assert (container);
1274 * mono_method_set_generic_container:
1276 * Sets the generic container of METHOD to CONTAINER.
1277 * LOCKING: Acquires the image lock.
1280 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1282 g_assert (method->is_generic);
1284 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1288 * mono_class_find_enum_basetype:
1289 * @class: The enum class
1291 * Determine the basetype of an enum by iterating through its fields. We do this
1292 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1295 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1297 MonoGenericContainer *container = NULL;
1298 MonoImage *m = klass->image;
1299 const int top = klass->field.count;
1302 g_assert (klass->enumtype);
1304 mono_error_init (error);
1306 if (klass->generic_container)
1307 container = klass->generic_container;
1308 else if (klass->generic_class) {
1309 MonoClass *gklass = klass->generic_class->container_class;
1311 container = gklass->generic_container;
1312 g_assert (container);
1316 * Fetch all the field information.
1318 for (i = 0; i < top; i++){
1320 guint32 cols [MONO_FIELD_SIZE];
1321 int idx = klass->field.first + i;
1324 /* klass->field.first and idx points into the fieldptr table */
1325 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1327 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1330 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1331 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1335 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1336 mono_metadata_decode_value (sig, &sig);
1337 /* FIELD signature == 0x06 */
1339 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1343 ftype = mono_metadata_parse_type_full (m, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1345 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1346 mono_error_set_from_loader_error (error);
1348 mono_error_set_bad_image (error, klass->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1351 if (klass->generic_class) {
1352 //FIXME do we leak here?
1353 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1354 if (!mono_error_ok (error))
1356 ftype->attrs = cols [MONO_FIELD_FLAGS];
1361 mono_error_set_type_load_class (error, klass, "Could not find base type");
1364 mono_loader_assert_no_error ();
1369 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1372 mono_type_has_exceptions (MonoType *type)
1374 switch (type->type) {
1375 case MONO_TYPE_CLASS:
1376 case MONO_TYPE_VALUETYPE:
1377 case MONO_TYPE_SZARRAY:
1378 return type->data.klass->exception_type;
1379 case MONO_TYPE_ARRAY:
1380 return type->data.array->eklass->exception_type;
1381 case MONO_TYPE_GENERICINST:
1382 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1391 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1395 mono_class_alloc (MonoClass *klass, int size)
1397 if (klass->generic_class)
1398 return mono_image_set_alloc (klass->generic_class->owner, size);
1400 return mono_image_alloc (klass->image, size);
1404 mono_class_alloc0 (MonoClass *klass, int size)
1408 res = mono_class_alloc (klass, size);
1409 memset (res, 0, size);
1413 #define mono_class_new0(klass,struct_type, n_structs) \
1414 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1417 * mono_class_setup_basic_field_info:
1418 * @class: The class to initialize
1420 * Initializes the klass->fields.
1421 * LOCKING: Assumes the loader lock is held.
1424 mono_class_setup_basic_field_info (MonoClass *klass)
1426 MonoClassField *field;
1434 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1435 image = klass->image;
1436 top = klass->field.count;
1438 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1440 * This happens when a generic instance of an unfinished generic typebuilder
1441 * is used as an element type for creating an array type. We can't initialize
1442 * the fields of this class using the fields of gklass, since gklass is not
1443 * finished yet, fields could be added to it later.
1449 mono_class_setup_basic_field_info (gtd);
1451 top = gtd->field.count;
1452 klass->field.first = gtd->field.first;
1453 klass->field.count = gtd->field.count;
1456 klass->fields = mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1459 * Fetch all the field information.
1461 for (i = 0; i < top; i++){
1462 field = &klass->fields [i];
1463 field->parent = klass;
1466 field->name = mono_field_get_name (>d->fields [i]);
1468 int idx = klass->field.first + i;
1469 /* klass->field.first and idx points into the fieldptr table */
1470 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1471 /* The name is needed for fieldrefs */
1472 field->name = mono_metadata_string_heap (image, name_idx);
1478 * mono_class_setup_fields:
1479 * @class: The class to initialize
1481 * Initializes the klass->fields.
1482 * LOCKING: Assumes the loader lock is held.
1485 mono_class_setup_fields (MonoClass *klass)
1488 MonoImage *m = klass->image;
1490 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1491 int i, blittable = TRUE;
1492 guint32 real_size = 0;
1493 guint32 packing_size = 0;
1494 gboolean explicit_size;
1495 MonoClassField *field;
1496 MonoGenericContainer *container = NULL;
1497 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1500 * FIXME: We have a race condition here. It's possible that this function returns
1501 * to its caller with `instance_size` set to `0` instead of the actual size. This
1502 * is not a problem when the function is called recursively on the same class,
1503 * because the size will be initialized by the outer invocation. What follows is a
1504 * description of how it can occur in other cases, too. There it is a problem,
1505 * because it can lead to the GC being asked to allocate an object of size `0`,
1506 * which SGen chokes on. The race condition is triggered infrequently by
1507 * `tests/sgen-suspend.cs`.
1509 * This function is called for a class whenever one of its subclasses is inited.
1510 * For example, it's called for every subclass of Object. What it does is this:
1512 * if (klass->setup_fields_called)
1515 * klass->instance_size = 0;
1517 * klass->setup_fields_called = 1;
1518 * ... critical point
1519 * klass->instance_size = actual_instance_size;
1521 * The last two steps are sometimes reversed, but that only changes the way in which
1522 * the race condition works.
1524 * Assume thread A goes through this function and makes it to the critical point.
1525 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1526 * immediately, but `instance_size` is incorrect.
1528 * The other case looks like this:
1530 * if (klass->setup_fields_called)
1532 * ... critical point X
1533 * klass->instance_size = 0;
1534 * ... critical point Y
1535 * klass->instance_size = actual_instance_size;
1537 * klass->setup_fields_called = 1;
1539 * Assume thread A goes through the function and makes it to critical point X. Now
1540 * thread B runs through the whole of the function, returning, assuming
1541 * `instance_size` is set. At that point thread A gets to run and makes it to
1542 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1545 if (klass->setup_fields_called)
1548 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1550 * This happens when a generic instance of an unfinished generic typebuilder
1551 * is used as an element type for creating an array type. We can't initialize
1552 * the fields of this class using the fields of gklass, since gklass is not
1553 * finished yet, fields could be added to it later.
1558 mono_class_setup_basic_field_info (klass);
1559 top = klass->field.count;
1562 mono_class_setup_fields (gtd);
1563 if (gtd->exception_type) {
1564 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1569 klass->instance_size = 0;
1571 klass->sizes.class_size = 0;
1573 if (klass->parent) {
1574 /* For generic instances, klass->parent might not have been initialized */
1575 mono_class_init (klass->parent);
1576 if (!klass->parent->size_inited) {
1577 mono_class_setup_fields (klass->parent);
1578 if (klass->parent->exception_type) {
1579 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1583 klass->instance_size += klass->parent->instance_size;
1584 klass->min_align = klass->parent->min_align;
1585 /* we use |= since it may have been set already */
1586 klass->has_references |= klass->parent->has_references;
1587 blittable = klass->parent->blittable;
1589 klass->instance_size = sizeof (MonoObject);
1590 klass->min_align = 1;
1593 /* We can't really enable 16 bytes alignment until the GC supports it.
1594 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1595 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1596 Bug #506144 is an example of this issue.
1598 if (klass->simd_type)
1599 klass->min_align = 16;
1601 /* Get the real size */
1602 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1604 if (explicit_size) {
1605 if ((packing_size & 0xffffff00) != 0) {
1606 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1607 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1610 klass->packing_size = packing_size;
1611 real_size += klass->instance_size;
1615 if (explicit_size && real_size) {
1616 klass->instance_size = MAX (real_size, klass->instance_size);
1618 klass->blittable = blittable;
1619 mono_memory_barrier ();
1620 klass->size_inited = 1;
1621 klass->fields_inited = 1;
1622 klass->setup_fields_called = 1;
1626 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1629 /* Prevent infinite loops if the class references itself */
1630 klass->setup_fields_called = 1;
1632 if (klass->generic_container) {
1633 container = klass->generic_container;
1635 container = gtd->generic_container;
1636 g_assert (container);
1640 * Fetch all the field information.
1642 for (i = 0; i < top; i++){
1643 int idx = klass->field.first + i;
1644 field = &klass->fields [i];
1646 field->parent = klass;
1649 mono_field_resolve_type (field, &error);
1650 if (!mono_error_ok (&error)) {
1651 /*mono_field_resolve_type already failed class*/
1652 mono_error_cleanup (&error);
1656 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1657 g_assert (field->type);
1660 if (mono_field_is_deleted (field))
1663 MonoClassField *gfield = >d->fields [i];
1664 field->offset = gfield->offset;
1666 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1668 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1669 field->offset = offset;
1671 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1672 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1675 if (field->offset < -1) { /*-1 is used to encode special static fields */
1676 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1679 if (klass->generic_container) {
1680 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1686 /* Only do these checks if we still think this type is blittable */
1687 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1688 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1691 MonoClass *field_class = mono_class_from_mono_type (field->type);
1693 mono_class_setup_fields (field_class);
1694 if (field_class->exception_type) {
1695 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1699 if (!field_class || !field_class->blittable)
1704 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1705 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1706 blittable = klass->element_class->blittable;
1709 if (mono_type_has_exceptions (field->type)) {
1710 char *class_name = mono_type_get_full_name (klass);
1711 char *type_name = mono_type_full_name (field->type);
1713 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1714 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1715 g_free (class_name);
1719 /* The def_value of fields is compute lazily during vtable creation */
1722 if (klass == mono_defaults.string_class)
1725 klass->blittable = blittable;
1727 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1728 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1731 if (explicit_size && real_size) {
1732 klass->instance_size = MAX (real_size, klass->instance_size);
1735 if (klass->exception_type)
1737 mono_class_layout_fields (klass);
1739 /*valuetypes can't be neither bigger than 1Mb or empty. */
1740 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1741 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1743 mono_memory_barrier ();
1744 klass->fields_inited = 1;
1748 * mono_class_setup_fields_locking:
1749 * @class: The class to initialize
1751 * Initializes the klass->fields array of fields.
1752 * Aquires the loader lock.
1755 mono_class_setup_fields_locking (MonoClass *klass)
1757 /* This can be checked without locks */
1758 if (klass->fields_inited)
1760 mono_loader_lock ();
1761 mono_class_setup_fields (klass);
1762 mono_loader_unlock ();
1766 * mono_class_has_references:
1768 * Returns whenever @klass->has_references is set, initializing it if needed.
1769 * Aquires the loader lock.
1772 mono_class_has_references (MonoClass *klass)
1774 if (klass->init_pending) {
1775 /* Be conservative */
1778 mono_class_init (klass);
1780 return klass->has_references;
1785 * mono_type_get_basic_type_from_generic:
1788 * Returns a closed type corresponding to the possibly open type
1792 mono_type_get_basic_type_from_generic (MonoType *type)
1794 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1795 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1796 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1797 return &mono_defaults.object_class->byval_arg;
1802 type_has_references (MonoClass *klass, MonoType *ftype)
1804 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1806 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1807 MonoGenericParam *gparam = ftype->data.generic_param;
1809 if (gparam->gshared_constraint)
1810 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1816 * mono_class_layout_fields:
1819 * Compute the placement of fields inside an object or struct, according to
1820 * the layout rules and set the following fields in @class:
1821 * - has_references (if the class contains instance references firled or structs that contain references)
1822 * - has_static_refs (same, but for static fields)
1823 * - instance_size (size of the object in memory)
1824 * - class_size (size needed for the static fields)
1825 * - size_inited (flag set when the instance_size is set)
1827 * LOCKING: this is supposed to be called with the loader lock held.
1830 mono_class_layout_fields (MonoClass *klass)
1833 const int top = klass->field.count;
1834 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1835 guint32 pass, passes, real_size;
1836 gboolean gc_aware_layout = FALSE;
1837 gboolean has_static_fields = FALSE;
1838 MonoClassField *field;
1841 * When we do generic sharing we need to have layout
1842 * information for open generic classes (either with a generic
1843 * context containing type variables or with a generic
1844 * container), so we don't return in that case anymore.
1848 * Enable GC aware auto layout: in this mode, reference
1849 * fields are grouped together inside objects, increasing collector
1851 * Requires that all classes whose layout is known to native code be annotated
1852 * with [StructLayout (LayoutKind.Sequential)]
1853 * Value types have gc_aware_layout disabled by default, as per
1854 * what the default is for other runtimes.
1856 /* corlib is missing [StructLayout] directives in many places */
1857 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1858 if (!klass->valuetype)
1859 gc_aware_layout = TRUE;
1862 /* Compute klass->has_references */
1864 * Process non-static fields first, since static fields might recursively
1865 * refer to the class itself.
1867 for (i = 0; i < top; i++) {
1870 field = &klass->fields [i];
1872 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1873 ftype = mono_type_get_underlying_type (field->type);
1874 ftype = mono_type_get_basic_type_from_generic (ftype);
1875 if (type_has_references (klass, ftype))
1876 klass->has_references = TRUE;
1880 for (i = 0; i < top; i++) {
1883 field = &klass->fields [i];
1885 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1886 ftype = mono_type_get_underlying_type (field->type);
1887 ftype = mono_type_get_basic_type_from_generic (ftype);
1888 if (type_has_references (klass, ftype))
1889 klass->has_static_refs = TRUE;
1893 for (i = 0; i < top; i++) {
1896 field = &klass->fields [i];
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 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1902 klass->has_static_refs = TRUE;
1904 klass->has_references = TRUE;
1909 * Compute field layout and total size (not considering static fields)
1913 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1914 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1916 if (gc_aware_layout)
1921 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1924 if (klass->parent) {
1925 mono_class_setup_fields (klass->parent);
1926 if (klass->parent->exception_type) {
1927 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1930 real_size = klass->parent->instance_size;
1932 real_size = sizeof (MonoObject);
1935 for (pass = 0; pass < passes; ++pass) {
1936 for (i = 0; i < top; i++){
1941 field = &klass->fields [i];
1943 if (mono_field_is_deleted (field))
1945 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1948 ftype = mono_type_get_underlying_type (field->type);
1949 ftype = mono_type_get_basic_type_from_generic (ftype);
1950 if (gc_aware_layout) {
1951 if (type_has_references (klass, ftype)) {
1960 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1961 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1962 /* This field is a hack inserted by MCS to empty structures */
1966 size = mono_type_size (field->type, &align);
1968 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1969 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1970 /* if the field has managed references, we need to force-align it
1973 if (type_has_references (klass, ftype))
1974 align = MAX (align, sizeof (gpointer));
1976 klass->min_align = MAX (align, klass->min_align);
1977 field->offset = real_size;
1979 field->offset += align - 1;
1980 field->offset &= ~(align - 1);
1982 /*TypeBuilders produce all sort of weird things*/
1983 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1984 real_size = field->offset + size;
1987 klass->instance_size = MAX (real_size, klass->instance_size);
1989 if (klass->instance_size & (klass->min_align - 1)) {
1990 klass->instance_size += klass->min_align - 1;
1991 klass->instance_size &= ~(klass->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 = klass->packing_size ? MIN (klass->packing_size, align): align;
2017 klass->min_align = MAX (align, klass->min_align);
2020 * When we get here, field->offset is already set by the
2021 * loader (for either runtime fields or fields loaded from metadata).
2022 * The offset is from the start of the object: this works for both
2023 * classes and valuetypes.
2025 field->offset += sizeof (MonoObject);
2026 ftype = mono_type_get_underlying_type (field->type);
2027 ftype = mono_type_get_basic_type_from_generic (ftype);
2028 if (type_has_references (klass, ftype)) {
2029 if (field->offset % sizeof (gpointer)) {
2030 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2037 real_size = MAX (real_size, size + field->offset);
2040 if (klass->has_references) {
2041 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2043 /* Check for overlapping reference and non-reference fields */
2044 for (i = 0; i < top; i++) {
2047 field = &klass->fields [i];
2049 if (mono_field_is_deleted (field))
2051 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2053 ftype = mono_type_get_underlying_type (field->type);
2054 if (MONO_TYPE_IS_REFERENCE (ftype))
2055 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2057 for (i = 0; i < top; i++) {
2058 field = &klass->fields [i];
2060 if (mono_field_is_deleted (field))
2062 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2065 // FIXME: Too much code does this
2067 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2068 char *err_msg = g_strdup_printf ("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->offset);
2069 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2073 g_free (ref_bitmap);
2076 klass->instance_size = MAX (real_size, klass->instance_size);
2077 if (klass->instance_size & (klass->min_align - 1)) {
2078 klass->instance_size += klass->min_align - 1;
2079 klass->instance_size &= ~(klass->min_align - 1);
2085 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2087 * This leads to all kinds of problems with nested structs, so only
2088 * enable it when a MONO_DEBUG property is set.
2090 * For small structs, set min_align to at least the struct size to improve
2091 * performance, and since the JIT memset/memcpy code assumes this and generates
2092 * unaligned accesses otherwise. See #78990 for a testcase.
2094 if (mono_align_small_structs) {
2095 if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2096 klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
2100 mono_memory_barrier ();
2101 klass->size_inited = 1;
2104 * Compute static field layout and size
2106 for (i = 0; i < top; i++){
2110 field = &klass->fields [i];
2112 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2114 if (mono_field_is_deleted (field))
2117 if (mono_type_has_exceptions (field->type)) {
2118 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2122 has_static_fields = TRUE;
2124 size = mono_type_size (field->type, &align);
2125 field->offset = klass->sizes.class_size;
2126 /*align is always non-zero here*/
2127 field->offset += align - 1;
2128 field->offset &= ~(align - 1);
2129 klass->sizes.class_size = field->offset + size;
2132 if (has_static_fields && klass->sizes.class_size == 0)
2133 /* Simplify code which depends on class_size != 0 if the class has static fields */
2134 klass->sizes.class_size = 8;
2138 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2142 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2143 method->klass = klass;
2144 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2145 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2146 method->signature = sig;
2147 method->name = name;
2150 if (name [0] == '.') {
2151 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2153 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2159 * mono_class_setup_methods:
2162 * Initializes the 'methods' array in CLASS.
2163 * Calling this method should be avoided if possible since it allocates a lot
2164 * of long-living MonoMethod structures.
2165 * Methods belonging to an interface are assigned a sequential slot starting
2168 * On failure this function sets klass->exception_type
2171 mono_class_setup_methods (MonoClass *klass)
2174 MonoMethod **methods;
2179 if (klass->generic_class) {
2181 MonoClass *gklass = klass->generic_class->container_class;
2183 mono_class_init (gklass);
2184 if (!gklass->exception_type)
2185 mono_class_setup_methods (gklass);
2186 if (gklass->exception_type) {
2187 /* FIXME make exception_data less opaque so it's possible to dup it here */
2188 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2192 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2193 count = gklass->method.count;
2194 methods = mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2196 for (i = 0; i < count; i++) {
2197 methods [i] = mono_class_inflate_generic_method_full_checked (
2198 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2199 if (!mono_error_ok (&error)) {
2200 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2201 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2204 mono_error_cleanup (&error);
2208 } else if (klass->rank) {
2210 MonoMethod *amethod;
2211 MonoMethodSignature *sig;
2212 int count_generic = 0, first_generic = 0;
2214 gboolean jagged_ctor = FALSE;
2216 count = 3 + (klass->rank > 1? 2: 1);
2218 mono_class_setup_interfaces (klass, &error);
2219 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2221 if (klass->rank == 1 && klass->element_class->rank) {
2223 klass->method.count ++;
2226 if (klass->interface_count) {
2227 count_generic = generic_array_methods (klass);
2228 first_generic = count;
2229 count += klass->interface_count * count_generic;
2232 methods = mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2234 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2235 sig->ret = &mono_defaults.void_class->byval_arg;
2236 sig->pinvoke = TRUE;
2237 sig->hasthis = TRUE;
2238 for (i = 0; i < klass->rank; ++i)
2239 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2241 amethod = create_array_method (klass, ".ctor", sig);
2242 methods [method_num++] = amethod;
2243 if (klass->rank > 1) {
2244 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2245 sig->ret = &mono_defaults.void_class->byval_arg;
2246 sig->pinvoke = TRUE;
2247 sig->hasthis = TRUE;
2248 for (i = 0; i < klass->rank * 2; ++i)
2249 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2251 amethod = create_array_method (klass, ".ctor", sig);
2252 methods [method_num++] = amethod;
2256 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2257 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2258 sig->ret = &mono_defaults.void_class->byval_arg;
2259 sig->pinvoke = TRUE;
2260 sig->hasthis = TRUE;
2261 for (i = 0; i < klass->rank + 1; ++i)
2262 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2263 amethod = create_array_method (klass, ".ctor", sig);
2264 methods [method_num++] = amethod;
2267 /* element Get (idx11, [idx2, ...]) */
2268 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2269 sig->ret = &klass->element_class->byval_arg;
2270 sig->pinvoke = TRUE;
2271 sig->hasthis = TRUE;
2272 for (i = 0; i < klass->rank; ++i)
2273 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2274 amethod = create_array_method (klass, "Get", sig);
2275 methods [method_num++] = amethod;
2276 /* element& Address (idx11, [idx2, ...]) */
2277 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2278 sig->ret = &klass->element_class->this_arg;
2279 sig->pinvoke = TRUE;
2280 sig->hasthis = TRUE;
2281 for (i = 0; i < klass->rank; ++i)
2282 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2283 amethod = create_array_method (klass, "Address", sig);
2284 methods [method_num++] = amethod;
2285 /* void Set (idx11, [idx2, ...], element) */
2286 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2287 sig->ret = &mono_defaults.void_class->byval_arg;
2288 sig->pinvoke = TRUE;
2289 sig->hasthis = TRUE;
2290 for (i = 0; i < klass->rank; ++i)
2291 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2292 sig->params [i] = &klass->element_class->byval_arg;
2293 amethod = create_array_method (klass, "Set", sig);
2294 methods [method_num++] = amethod;
2296 for (i = 0; i < klass->interface_count; i++)
2297 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2301 count = klass->method.count;
2302 methods = mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2303 for (i = 0; i < count; ++i) {
2304 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2305 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2307 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2308 mono_error_cleanup (&error);
2313 if (MONO_CLASS_IS_INTERFACE (klass)) {
2315 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2316 for (i = 0; i < count; ++i) {
2317 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2318 methods [i]->slot = slot++;
2322 mono_image_lock (klass->image);
2324 if (!klass->methods) {
2325 klass->method.count = count;
2327 /* Needed because of the double-checking locking pattern */
2328 mono_memory_barrier ();
2330 klass->methods = methods;
2333 mono_image_unlock (klass->image);
2337 * mono_class_get_method_by_index:
2339 * Returns klass->methods [index], initializing klass->methods if neccesary.
2341 * LOCKING: Acquires the loader lock.
2344 mono_class_get_method_by_index (MonoClass *klass, int index)
2347 /* Avoid calling setup_methods () if possible */
2348 if (klass->generic_class && !klass->methods) {
2349 MonoClass *gklass = klass->generic_class->container_class;
2352 m = mono_class_inflate_generic_method_full_checked (
2353 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2354 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2356 * If setup_methods () is called later for this class, no duplicates are created,
2357 * since inflate_generic_method guarantees that only one instance of a method
2358 * is created for each context.
2361 mono_class_setup_methods (klass);
2362 g_assert (m == klass->methods [index]);
2366 mono_class_setup_methods (klass);
2367 if (klass->exception_type) /*FIXME do proper error handling*/
2369 g_assert (index >= 0 && index < klass->method.count);
2370 return klass->methods [index];
2375 * mono_class_get_inflated_method:
2377 * Given an inflated class CLASS and a method METHOD which should be a method of
2378 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2381 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2383 MonoClass *gklass = klass->generic_class->container_class;
2386 g_assert (method->klass == gklass);
2388 mono_class_setup_methods (gklass);
2389 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2391 for (i = 0; i < gklass->method.count; ++i) {
2392 if (gklass->methods [i] == method) {
2393 if (klass->methods) {
2394 return klass->methods [i];
2397 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2398 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2408 * mono_class_get_vtable_entry:
2410 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2411 * LOCKING: Acquires the loader lock.
2414 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2418 if (klass->rank == 1) {
2420 * szarrays do not overwrite any methods of Array, so we can avoid
2421 * initializing their vtables in some cases.
2423 mono_class_setup_vtable (klass->parent);
2424 if (offset < klass->parent->vtable_size)
2425 return klass->parent->vtable [offset];
2428 if (klass->generic_class) {
2430 MonoClass *gklass = klass->generic_class->container_class;
2431 mono_class_setup_vtable (gklass);
2432 m = gklass->vtable [offset];
2434 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2435 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2437 mono_class_setup_vtable (klass);
2438 if (klass->exception_type)
2440 m = klass->vtable [offset];
2447 * mono_class_get_vtable_size:
2449 * Return the vtable size for KLASS.
2452 mono_class_get_vtable_size (MonoClass *klass)
2454 mono_class_setup_vtable (klass);
2456 return klass->vtable_size;
2460 * mono_class_setup_properties:
2462 * Initialize klass->ext.property and klass->ext.properties.
2464 * This method can fail the class.
2467 mono_class_setup_properties (MonoClass *klass)
2469 guint startm, endm, i, j;
2470 guint32 cols [MONO_PROPERTY_SIZE];
2471 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2472 MonoProperty *properties;
2476 if (klass->ext && klass->ext->properties)
2479 if (klass->generic_class) {
2480 MonoClass *gklass = klass->generic_class->container_class;
2482 mono_class_init (gklass);
2483 mono_class_setup_properties (gklass);
2484 if (gklass->exception_type) {
2485 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2489 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2491 for (i = 0; i < gklass->ext->property.count; i++) {
2493 MonoProperty *prop = &properties [i];
2495 *prop = gklass->ext->properties [i];
2498 prop->get = mono_class_inflate_generic_method_full_checked (
2499 prop->get, klass, mono_class_get_context (klass), &error);
2501 prop->set = mono_class_inflate_generic_method_full_checked (
2502 prop->set, klass, mono_class_get_context (klass), &error);
2504 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2505 prop->parent = klass;
2508 first = gklass->ext->property.first;
2509 count = gklass->ext->property.count;
2511 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2512 count = last - first;
2515 mono_class_setup_methods (klass);
2516 if (klass->exception_type)
2520 properties = mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2521 for (i = first; i < last; ++i) {
2522 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2523 properties [i - first].parent = klass;
2524 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2525 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2527 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2528 for (j = startm; j < endm; ++j) {
2531 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2533 if (klass->image->uncompressed_metadata) {
2535 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2536 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2537 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2539 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2542 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2543 case METHOD_SEMANTIC_SETTER:
2544 properties [i - first].set = method;
2546 case METHOD_SEMANTIC_GETTER:
2547 properties [i - first].get = method;
2556 mono_class_alloc_ext (klass);
2558 mono_image_lock (klass->image);
2560 if (klass->ext->properties) {
2561 /* We leak 'properties' which was allocated from the image mempool */
2562 mono_image_unlock (klass->image);
2566 klass->ext->property.first = first;
2567 klass->ext->property.count = count;
2569 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2570 mono_memory_barrier ();
2572 /* Leave this assignment as the last op in the function */
2573 klass->ext->properties = properties;
2575 mono_image_unlock (klass->image);
2579 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2581 MonoMethod **om, **retval;
2584 for (om = methods, count = 0; *om; ++om, ++count)
2587 retval = g_new0 (MonoMethod*, count + 1);
2589 for (om = methods, count = 0; *om; ++om, ++count) {
2591 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2592 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2598 /*This method can fail the class.*/
2600 mono_class_setup_events (MonoClass *klass)
2603 guint startm, endm, i, j;
2604 guint32 cols [MONO_EVENT_SIZE];
2605 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2609 if (klass->ext && klass->ext->events)
2612 if (klass->generic_class) {
2613 MonoClass *gklass = klass->generic_class->container_class;
2614 MonoGenericContext *context = NULL;
2616 mono_class_setup_events (gklass);
2617 if (gklass->exception_type) {
2618 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2622 first = gklass->ext->event.first;
2623 count = gklass->ext->event.count;
2625 events = mono_class_new0 (klass, MonoEvent, count);
2628 context = mono_class_get_context (klass);
2630 for (i = 0; i < count; i++) {
2632 MonoEvent *event = &events [i];
2633 MonoEvent *gevent = &gklass->ext->events [i];
2635 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2637 event->parent = klass;
2638 event->name = gevent->name;
2639 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2640 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2641 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2642 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2643 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2644 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2646 #ifndef MONO_SMALL_CONFIG
2647 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2649 event->attrs = gevent->attrs;
2652 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2653 count = last - first;
2656 mono_class_setup_methods (klass);
2657 if (klass->exception_type) {
2658 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2663 events = mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2664 for (i = first; i < last; ++i) {
2665 MonoEvent *event = &events [i - first];
2667 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2668 event->parent = klass;
2669 event->attrs = cols [MONO_EVENT_FLAGS];
2670 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2672 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2673 for (j = startm; j < endm; ++j) {
2676 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2678 if (klass->image->uncompressed_metadata) {
2680 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2681 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2682 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2684 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2687 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2688 case METHOD_SEMANTIC_ADD_ON:
2689 event->add = method;
2691 case METHOD_SEMANTIC_REMOVE_ON:
2692 event->remove = method;
2694 case METHOD_SEMANTIC_FIRE:
2695 event->raise = method;
2697 case METHOD_SEMANTIC_OTHER: {
2698 #ifndef MONO_SMALL_CONFIG
2701 if (event->other == NULL) {
2702 event->other = g_new0 (MonoMethod*, 2);
2704 while (event->other [n])
2706 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2708 event->other [n] = method;
2709 /* NULL terminated */
2710 event->other [n + 1] = NULL;
2721 mono_class_alloc_ext (klass);
2723 mono_image_lock (klass->image);
2725 if (klass->ext->events) {
2726 mono_image_unlock (klass->image);
2730 klass->ext->event.first = first;
2731 klass->ext->event.count = count;
2733 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2734 mono_memory_barrier ();
2736 /* Leave this assignment as the last op in the function */
2737 klass->ext->events = events;
2739 mono_image_unlock (klass->image);
2743 * Global pool of interface IDs, represented as a bitset.
2744 * LOCKING: Protected by the classes lock.
2746 static MonoBitSet *global_interface_bitset = NULL;
2749 * mono_unload_interface_ids:
2750 * @bitset: bit set of interface IDs
2752 * When an image is unloaded, the interface IDs associated with
2753 * the image are put back in the global pool of IDs so the numbers
2757 mono_unload_interface_ids (MonoBitSet *bitset)
2760 mono_bitset_sub (global_interface_bitset, bitset);
2765 mono_unload_interface_id (MonoClass *klass)
2767 if (global_interface_bitset && klass->interface_id) {
2769 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2775 * mono_get_unique_iid:
2778 * Assign a unique integer ID to the interface represented by @class.
2779 * The ID will positive and as small as possible.
2780 * LOCKING: Acquires the classes lock.
2781 * Returns: the new ID.
2784 mono_get_unique_iid (MonoClass *klass)
2788 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2792 if (!global_interface_bitset) {
2793 global_interface_bitset = mono_bitset_new (128, 0);
2796 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2798 int old_size = mono_bitset_size (global_interface_bitset);
2799 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2800 mono_bitset_free (global_interface_bitset);
2801 global_interface_bitset = new_set;
2804 mono_bitset_set (global_interface_bitset, iid);
2805 /* set the bit also in the per-image set */
2806 if (!klass->generic_class) {
2807 if (klass->image->interface_bitset) {
2808 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2809 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2810 mono_bitset_free (klass->image->interface_bitset);
2811 klass->image->interface_bitset = new_set;
2814 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2816 mono_bitset_set (klass->image->interface_bitset, iid);
2821 #ifndef MONO_SMALL_CONFIG
2822 if (mono_print_vtable) {
2824 char *type_name = mono_type_full_name (&klass->byval_arg);
2825 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2826 generic_id = klass->generic_class->context.class_inst->id;
2827 g_assert (generic_id != 0);
2831 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2836 g_assert (iid <= 65535);
2841 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2846 mono_class_setup_interfaces (klass, error);
2847 if (!mono_error_ok (error))
2850 for (i = 0; i < klass->interface_count; i++) {
2851 ic = klass->interfaces [i];
2854 *res = g_ptr_array_new ();
2855 g_ptr_array_add (*res, ic);
2856 mono_class_init (ic);
2857 if (ic->exception_type) {
2858 mono_error_set_type_load_class (error, ic, "Error Loading class");
2862 collect_implemented_interfaces_aux (ic, res, error);
2863 if (!mono_error_ok (error))
2869 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2871 GPtrArray *res = NULL;
2873 collect_implemented_interfaces_aux (klass, &res, error);
2874 if (!mono_error_ok (error)) {
2876 g_ptr_array_free (res, TRUE);
2883 compare_interface_ids (const void *p_key, const void *p_element) {
2884 const MonoClass *key = p_key;
2885 const MonoClass *element = *(MonoClass**) p_element;
2887 return (key->interface_id - element->interface_id);
2890 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2892 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2893 MonoClass **result = mono_binary_search (
2895 klass->interfaces_packed,
2896 klass->interface_offsets_count,
2897 sizeof (MonoClass *),
2898 compare_interface_ids);
2900 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2907 * mono_class_interface_offset_with_variance:
2909 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2910 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2912 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2914 * FIXME figure out MS disambiguation rules and fix this function.
2917 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2918 int i = mono_class_interface_offset (klass, itf);
2919 *non_exact_match = FALSE;
2923 if (!mono_class_has_variant_generic_params (itf))
2926 for (i = 0; i < klass->interface_offsets_count; i++) {
2927 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2928 *non_exact_match = TRUE;
2929 return klass->interface_offsets_packed [i];
2937 print_implemented_interfaces (MonoClass *klass) {
2940 GPtrArray *ifaces = NULL;
2942 int ancestor_level = 0;
2944 name = mono_type_get_full_name (klass);
2945 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2948 for (i = 0; i < klass->interface_offsets_count; i++)
2949 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2950 klass->interfaces_packed [i]->interface_id,
2951 klass->interface_offsets_packed [i],
2952 klass->interfaces_packed [i]->method.count,
2953 klass->interfaces_packed [i]->name_space,
2954 klass->interfaces_packed [i]->name );
2955 printf ("Interface flags: ");
2956 for (i = 0; i <= klass->max_interface_id; i++)
2957 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2958 printf ("(%d,T)", i);
2960 printf ("(%d,F)", i);
2962 printf ("Dump interface flags:");
2963 #ifdef COMPRESSED_INTERFACE_BITMAP
2965 const uint8_t* p = klass->interface_bitmap;
2966 i = klass->max_interface_id;
2968 printf (" %d x 00 %02X", p [0], p [1]);
2974 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2975 printf (" %02X", klass->interface_bitmap [i]);
2978 while (klass != NULL) {
2979 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2980 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2981 if (!mono_error_ok (&error)) {
2982 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2983 mono_error_cleanup (&error);
2984 } else if (ifaces) {
2985 for (i = 0; i < ifaces->len; i++) {
2986 MonoClass *ic = g_ptr_array_index (ifaces, i);
2987 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2988 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2990 mono_class_interface_offset (klass, ic),
2995 g_ptr_array_free (ifaces, TRUE);
2998 klass = klass->parent;
3003 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3006 args [0] = &arg0->byval_arg;
3008 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3012 array_class_get_if_rank (MonoClass *klass, guint rank)
3014 return rank ? mono_array_class_get (klass, rank) : klass;
3018 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3020 valuetype_types [0] = eclass;
3021 if (eclass == mono_defaults.int16_class)
3022 valuetype_types [1] = mono_defaults.uint16_class;
3023 else if (eclass == mono_defaults.uint16_class)
3024 valuetype_types [1] = mono_defaults.int16_class;
3025 else if (eclass == mono_defaults.int32_class)
3026 valuetype_types [1] = mono_defaults.uint32_class;
3027 else if (eclass == mono_defaults.uint32_class)
3028 valuetype_types [1] = mono_defaults.int32_class;
3029 else if (eclass == mono_defaults.int64_class)
3030 valuetype_types [1] = mono_defaults.uint64_class;
3031 else if (eclass == mono_defaults.uint64_class)
3032 valuetype_types [1] = mono_defaults.int64_class;
3033 else if (eclass == mono_defaults.byte_class)
3034 valuetype_types [1] = mono_defaults.sbyte_class;
3035 else if (eclass == mono_defaults.sbyte_class)
3036 valuetype_types [1] = mono_defaults.byte_class;
3037 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3038 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3041 /* this won't be needed once bug #325495 is completely fixed
3042 * though we'll need something similar to know which interfaces to allow
3043 * in arrays when they'll be lazyly created
3045 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3046 * MS returns diferrent types based on which instance is called. For example:
3047 * object obj = new byte[10][];
3048 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3049 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3052 * Fixing this should kill quite some code, save some bits and improve compatibility.
3055 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3057 MonoClass *eclass = klass->element_class;
3058 static MonoClass* generic_icollection_class = NULL;
3059 static MonoClass* generic_ienumerable_class = NULL;
3060 static MonoClass* generic_ienumerator_class = NULL;
3061 static MonoClass* generic_ireadonlylist_class = NULL;
3062 static MonoClass* generic_ireadonlycollection_class = NULL;
3063 MonoClass *valuetype_types[2] = { NULL, NULL };
3064 MonoClass **interfaces = NULL;
3065 int i, nifaces, interface_count, real_count, original_rank;
3067 gboolean internal_enumerator;
3068 gboolean eclass_is_valuetype;
3070 if (!mono_defaults.generic_ilist_class) {
3074 internal_enumerator = FALSE;
3075 eclass_is_valuetype = FALSE;
3076 original_rank = eclass->rank;
3077 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3078 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3080 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3082 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3083 original_rank = eclass->rank;
3085 eclass = eclass->element_class;
3086 internal_enumerator = TRUE;
3087 *is_enumerator = TRUE;
3095 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3096 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3098 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3100 if (!generic_icollection_class) {
3101 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3102 "System.Collections.Generic", "ICollection`1");
3103 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3104 "System.Collections.Generic", "IEnumerable`1");
3105 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3106 "System.Collections.Generic", "IEnumerator`1");
3107 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3108 "System.Collections.Generic", "IReadOnlyList`1");
3109 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3110 "System.Collections.Generic", "IReadOnlyCollection`1");
3113 mono_class_init (eclass);
3116 * Arrays in 2.0 need to implement a number of generic interfaces
3117 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3118 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3119 * We collect the types needed to build the
3120 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3121 * the generic interfaces needed to implement.
3123 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3124 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3126 if (eclass->valuetype) {
3127 nifaces = generic_ireadonlylist_class ? 5 : 3;
3128 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3130 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3131 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3132 if (internal_enumerator) {
3134 if (valuetype_types [1])
3138 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3139 interfaces [0] = valuetype_types [0];
3140 if (valuetype_types [1])
3141 interfaces [nifaces] = valuetype_types [1];
3143 eclass_is_valuetype = TRUE;
3146 int idepth = eclass->idepth;
3147 if (!internal_enumerator)
3149 nifaces = generic_ireadonlylist_class ? 2 : 3;
3151 // FIXME: This doesn't seem to work/required for generic params
3152 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3153 mono_class_setup_interface_offsets (eclass);
3155 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3156 /* we add object for interfaces and the supertypes for the other
3157 * types. The last of the supertypes is the element class itself which we
3158 * already created the explicit interfaces for (so we include it for IEnumerator
3159 * and exclude it for arrays).
3161 if (MONO_CLASS_IS_INTERFACE (eclass))
3164 interface_count += idepth;
3165 if (eclass->rank && eclass->element_class->valuetype) {
3166 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3167 if (valuetype_types [1])
3170 /* IList, ICollection, IEnumerable, IReadOnlyList */
3171 interface_count *= nifaces;
3172 real_count = interface_count;
3173 if (internal_enumerator) {
3174 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3175 if (valuetype_types [1])
3178 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3179 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3180 interfaces [0] = mono_defaults.object_class;
3184 for (i = 0; i < idepth; i++) {
3185 mono_class_init (eclass->supertypes [i]);
3186 interfaces [j] = eclass->supertypes [i];
3190 if (all_interfaces) {
3191 for (i = 0; i < eclass->interface_offsets_count; i++) {
3192 interfaces [j] = eclass->interfaces_packed [i];
3196 for (i = 0; i < eclass->interface_count; i++) {
3197 interfaces [j] = eclass->interfaces [i];
3201 if (valuetype_types [1]) {
3202 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3207 /* instantiate the generic interfaces */
3208 for (i = 0; i < interface_count; i += nifaces) {
3209 MonoClass *iface = interfaces [i];
3211 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3212 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3214 if (eclass->valuetype) {
3215 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3216 if (generic_ireadonlylist_class) {
3217 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3218 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3221 if (!generic_ireadonlylist_class)
3222 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3225 if (internal_enumerator) {
3227 /* instantiate IEnumerator<iface> */
3228 for (i = 0; i < interface_count; i++) {
3229 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3231 j = interface_count;
3232 if (!eclass_is_valuetype) {
3233 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3234 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3237 for (i = 0; i < eclass->idepth; i++) {
3238 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3242 for (i = 0; i < eclass->interface_offsets_count; i++) {
3243 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3247 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3249 if (valuetype_types [1])
3250 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3254 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3255 for (i = 0; i < real_count; ++i) {
3256 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3257 g_print ("%s implements %s\n", type_name, name);
3268 find_array_interface (MonoClass *klass, const char *name)
3271 for (i = 0; i < klass->interface_count; ++i) {
3272 if (strcmp (klass->interfaces [i]->name, name) == 0)
3279 * Return the number of virtual methods.
3280 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3281 * Return -1 on failure.
3282 * FIXME It would be nice if this information could be cached somewhere.
3285 count_virtual_methods (MonoClass *klass)
3289 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3291 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3292 mono_class_setup_methods (klass);
3293 if (klass->exception_type)
3296 for (i = 0; i < klass->method.count; ++i) {
3297 flags = klass->methods [i]->flags;
3298 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3302 for (i = 0; i < klass->method.count; ++i) {
3303 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3305 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3313 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3321 m = (l + num_ifaces) / 2;
3322 if (interfaces_full [m] == ic)
3324 if (l == num_ifaces)
3326 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3335 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3337 int i = find_interface (num_ifaces, interfaces_full, ic);
3339 return interface_offsets_full [i];
3344 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3346 int i = find_interface (num_ifaces, interfaces_full, ic);
3350 interface_offsets_full [i] = offset;
3353 for (i = 0; i < num_ifaces; ++i) {
3354 if (interfaces_full [i]) {
3356 if (interfaces_full [i]->interface_id < ic->interface_id)
3359 while (end < num_ifaces && interfaces_full [end]) end++;
3360 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3361 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3363 interfaces_full [i] = ic;
3364 interface_offsets_full [i] = offset;
3370 #ifdef COMPRESSED_INTERFACE_BITMAP
3373 * Compressed interface bitmap design.
3375 * Interface bitmaps take a large amount of memory, because their size is
3376 * linear with the maximum interface id assigned in the process (each interface
3377 * is assigned a unique id as it is loaded). The number of interface classes
3378 * is high because of the many implicit interfaces implemented by arrays (we'll
3379 * need to lazy-load them in the future).
3380 * Most classes implement a very small number of interfaces, so the bitmap is
3381 * sparse. This bitmap needs to be checked by interface casts, so access to the
3382 * needed bit must be fast and doable with few jit instructions.
3384 * The current compression format is as follows:
3385 * *) it is a sequence of one or more two-byte elements
3386 * *) the first byte in the element is the count of empty bitmap bytes
3387 * at the current bitmap position
3388 * *) the second byte in the element is an actual bitmap byte at the current
3391 * As an example, the following compressed bitmap bytes:
3392 * 0x07 0x01 0x00 0x7
3393 * correspond to the following bitmap:
3394 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3396 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3397 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3398 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3402 * mono_compress_bitmap:
3403 * @dest: destination buffer
3404 * @bitmap: bitmap buffer
3405 * @size: size of @bitmap in bytes
3407 * This is a mono internal function.
3408 * The @bitmap data is compressed into a format that is small but
3409 * still searchable in few instructions by the JIT and runtime.
3410 * The compressed data is stored in the buffer pointed to by the
3411 * @dest array. Passing a #NULL value for @dest allows to just compute
3412 * the size of the buffer.
3413 * This compression algorithm assumes the bits set in the bitmap are
3414 * few and far between, like in interface bitmaps.
3415 * Returns: the size of the compressed bitmap in bytes.
3418 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3422 const uint8_t *end = bitmap + size;
3423 while (bitmap < end) {
3424 if (*bitmap || numz == 255) {
3448 * mono_class_interface_match:
3449 * @bitmap: a compressed bitmap buffer
3450 * @id: the index to check in the bitmap
3452 * This is a mono internal function.
3453 * Checks if a bit is set in a compressed interface bitmap. @id must
3454 * be already checked for being smaller than the maximum id encoded in the
3457 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3461 mono_class_interface_match (const uint8_t *bitmap, int id)
3464 id -= bitmap [0] * 8;
3468 return bitmap [1] & (1 << id);
3477 * LOCKING: this is supposed to be called with the loader lock held.
3478 * Return -1 on failure and set exception_type
3481 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3485 int i, j, max_iid, num_ifaces;
3486 MonoClass **interfaces_full = NULL;
3487 int *interface_offsets_full = NULL;
3489 GPtrArray **ifaces_array = NULL;
3490 int interface_offsets_count;
3491 MonoClass **array_interfaces = NULL;
3492 int num_array_interfaces;
3493 int is_enumerator = FALSE;
3495 mono_class_setup_supertypes (klass);
3497 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3498 * implicit interfaces have the property that they are assigned the same slot in the
3499 * vtables for compatible interfaces
3501 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3503 /* compute maximum number of slots and maximum interface id */
3505 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3506 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3507 for (j = 0; j < klass->idepth; j++) {
3508 k = klass->supertypes [j];
3509 num_ifaces += k->interface_count;
3510 for (i = 0; i < k->interface_count; i++) {
3511 ic = k->interfaces [i];
3514 mono_class_init (ic);
3516 if (max_iid < ic->interface_id)
3517 max_iid = ic->interface_id;
3519 ifaces = mono_class_get_implemented_interfaces (k, &error);
3520 if (!mono_error_ok (&error)) {
3521 char *name = mono_type_get_full_name (k);
3522 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3524 mono_error_cleanup (&error);
3529 num_ifaces += ifaces->len;
3530 for (i = 0; i < ifaces->len; ++i) {
3531 ic = g_ptr_array_index (ifaces, i);
3532 if (max_iid < ic->interface_id)
3533 max_iid = ic->interface_id;
3535 ifaces_array [j] = ifaces;
3539 for (i = 0; i < num_array_interfaces; ++i) {
3540 ic = array_interfaces [i];
3541 mono_class_init (ic);
3542 if (max_iid < ic->interface_id)
3543 max_iid = ic->interface_id;
3546 if (MONO_CLASS_IS_INTERFACE (klass)) {
3548 if (max_iid < klass->interface_id)
3549 max_iid = klass->interface_id;
3551 klass->max_interface_id = max_iid;
3552 /* compute vtable offset for interfaces */
3553 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3554 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3556 for (i = 0; i < num_ifaces; i++) {
3557 interface_offsets_full [i] = -1;
3560 /* skip the current class */
3561 for (j = 0; j < klass->idepth - 1; j++) {
3562 k = klass->supertypes [j];
3563 ifaces = ifaces_array [j];
3566 for (i = 0; i < ifaces->len; ++i) {
3568 ic = g_ptr_array_index (ifaces, i);
3570 /*Force the sharing of interface offsets between parent and subtypes.*/
3571 io = mono_class_interface_offset (k, ic);
3573 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3578 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3579 ifaces = ifaces_array [klass->idepth - 1];
3581 for (i = 0; i < ifaces->len; ++i) {
3583 ic = g_ptr_array_index (ifaces, i);
3584 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3586 count = count_virtual_methods (ic);
3588 char *name = mono_type_get_full_name (ic);
3589 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3598 if (MONO_CLASS_IS_INTERFACE (klass))
3599 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3601 if (num_array_interfaces) {
3602 if (is_enumerator) {
3603 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3604 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3605 g_assert (ienumerator_offset >= 0);
3606 for (i = 0; i < num_array_interfaces; ++i) {
3607 ic = array_interfaces [i];
3608 if (strcmp (ic->name, "IEnumerator`1") == 0)
3609 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3611 g_assert_not_reached ();
3612 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, interface_offsets_full [ic->interface_id], klass->interfaces [0]->name);*/
3615 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3616 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3617 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3618 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3619 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3620 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3621 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3622 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3623 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3624 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3625 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3626 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3627 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3628 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3629 for (i = 0; i < num_array_interfaces; ++i) {
3631 ic = array_interfaces [i];
3632 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3633 offset = ilist_offset;
3634 else if (strcmp (ic->name, "ICollection`1") == 0)
3635 offset = icollection_offset;
3636 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3637 offset = ienumerable_offset;
3638 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3639 offset = ireadonlylist_offset;
3640 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3641 offset = ireadonlycollection_offset;
3643 g_assert_not_reached ();
3644 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3645 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3650 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3651 if (interface_offsets_full [i] != -1) {
3652 interface_offsets_count ++;
3657 * We might get called multiple times:
3658 * - mono_class_init ()
3659 * - mono_class_setup_vtable ().
3660 * - mono_class_setup_interface_offsets ().
3661 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3662 * means we have to overwrite those when called from other places (#4440).
3664 if (klass->interfaces_packed) {
3666 g_assert (klass->interface_offsets_count == interface_offsets_count);
3670 klass->interface_offsets_count = interface_offsets_count;
3671 klass->interfaces_packed = mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3672 klass->interface_offsets_packed = mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3673 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3674 #ifdef COMPRESSED_INTERFACE_BITMAP
3675 bitmap = g_malloc0 (bsize);
3677 bitmap = mono_class_alloc0 (klass, bsize);
3679 for (i = 0; i < interface_offsets_count; i++) {
3680 int id = interfaces_full [i]->interface_id;
3681 bitmap [id >> 3] |= (1 << (id & 7));
3682 klass->interfaces_packed [i] = interfaces_full [i];
3683 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3684 /*if (num_array_interfaces)
3685 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&klass->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3687 #ifdef COMPRESSED_INTERFACE_BITMAP
3688 i = mono_compress_bitmap (NULL, bitmap, bsize);
3689 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3690 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3693 klass->interface_bitmap = bitmap;
3698 g_free (interfaces_full);
3699 g_free (interface_offsets_full);
3700 g_free (array_interfaces);
3701 for (i = 0; i < klass->idepth; i++) {
3702 ifaces = ifaces_array [i];
3704 g_ptr_array_free (ifaces, TRUE);
3706 g_free (ifaces_array);
3708 //printf ("JUST DONE: ");
3709 //print_implemented_interfaces (klass);
3715 * Setup interface offsets for interfaces.
3717 * - klass->max_interface_id
3718 * - klass->interface_offsets_count
3719 * - klass->interfaces_packed
3720 * - klass->interface_offsets_packed
3721 * - klass->interface_bitmap
3723 * This function can fail @class.
3726 mono_class_setup_interface_offsets (MonoClass *klass)
3728 mono_loader_lock ();
3730 setup_interface_offsets (klass, 0, FALSE);
3732 mono_loader_unlock ();
3735 /*Checks if @klass has @parent as one of it's parents type gtd
3739 * Bar<T> : Foo<Bar<Bar<T>>>
3743 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3745 klass = mono_class_get_generic_type_definition (klass);
3746 parent = mono_class_get_generic_type_definition (parent);
3747 mono_class_setup_supertypes (klass);
3748 mono_class_setup_supertypes (parent);
3750 return klass->idepth >= parent->idepth &&
3751 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3755 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3757 MonoGenericInst *ginst;
3759 if (!klass->generic_class) {
3760 mono_class_setup_vtable_full (klass, in_setup);
3761 return klass->exception_type == 0;
3764 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3765 if (klass->generic_class->container_class->exception_type) {
3766 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3770 ginst = klass->generic_class->context.class_inst;
3771 for (i = 0; i < ginst->type_argc; ++i) {
3773 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3775 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3776 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3777 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3779 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3780 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3788 * mono_class_setup_vtable:
3790 * Creates the generic vtable of CLASS.
3791 * Initializes the following fields in MonoClass:
3794 * Plus all the fields initialized by setup_interface_offsets ().
3795 * If there is an error during vtable construction, klass->exception_type is set.
3797 * LOCKING: Acquires the loader lock.
3800 mono_class_setup_vtable (MonoClass *klass)
3802 mono_class_setup_vtable_full (klass, NULL);
3806 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3808 MonoMethod **overrides;
3809 MonoGenericContext *context;
3817 if (MONO_CLASS_IS_INTERFACE (klass)) {
3818 /* This sets method->slot for all methods if this is an interface */
3819 mono_class_setup_methods (klass);
3823 if (klass->exception_type)
3826 if (g_list_find (in_setup, klass))
3829 mono_loader_lock ();
3831 if (klass->vtable) {
3832 mono_loader_unlock ();
3836 mono_stats.generic_vtable_count ++;
3837 in_setup = g_list_prepend (in_setup, klass);
3839 if (klass->generic_class) {
3840 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3841 mono_loader_unlock ();
3842 g_list_remove (in_setup, klass);
3846 context = mono_class_get_context (klass);
3847 type_token = klass->generic_class->container_class->type_token;
3849 context = (MonoGenericContext *) klass->generic_container;
3850 type_token = klass->type_token;
3853 if (image_is_dynamic (klass->image)) {
3854 /* Generic instances can have zero method overrides without causing any harm.
3855 * This is true since we don't do layout all over again for them, we simply inflate
3856 * the layout of the parent.
3858 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
3860 /* The following call fails if there are missing methods in the type */
3861 /* FIXME it's probably a good idea to avoid this for generic instances. */
3862 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3866 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3868 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3872 mono_loader_unlock ();
3873 g_list_remove (in_setup, klass);
3878 #define DEBUG_INTERFACE_VTABLE_CODE 0
3879 #define TRACE_INTERFACE_VTABLE_CODE 0
3880 #define VERIFY_INTERFACE_VTABLE_CODE 0
3881 #define VTABLE_SELECTOR (1)
3883 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3884 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3885 if (!(VTABLE_SELECTOR)) break; \
3889 #define DEBUG_INTERFACE_VTABLE(stmt)
3892 #if TRACE_INTERFACE_VTABLE_CODE
3893 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3894 if (!(VTABLE_SELECTOR)) break; \
3898 #define TRACE_INTERFACE_VTABLE(stmt)
3901 #if VERIFY_INTERFACE_VTABLE_CODE
3902 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3903 if (!(VTABLE_SELECTOR)) break; \
3907 #define VERIFY_INTERFACE_VTABLE(stmt)
3911 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3913 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3917 GString *res = g_string_new ("");
3919 g_string_append_c (res, '(');
3920 for (i = 0; i < sig->param_count; ++i) {
3922 g_string_append_c (res, ',');
3923 mono_type_get_desc (res, sig->params [i], include_namespace);
3925 g_string_append (res, ")=>");
3926 if (sig->ret != NULL) {
3927 mono_type_get_desc (res, sig->ret, include_namespace);
3929 g_string_append (res, "NULL");
3932 g_string_free (res, FALSE);
3936 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3937 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3938 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3939 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3947 is_wcf_hack_disabled (void)
3949 static gboolean disabled;
3950 static gboolean inited = FALSE;
3952 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3959 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3961 MonoMethodSignature *cmsig, *imsig;
3962 if (strcmp (im->name, cm->name) == 0) {
3963 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3964 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3967 if (! slot_is_empty) {
3968 if (require_newslot) {
3969 if (! interface_is_explicitly_implemented_by_class) {
3970 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3973 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3974 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3978 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3981 cmsig = mono_method_signature (cm);
3982 imsig = mono_method_signature (im);
3983 if (!cmsig || !imsig) {
3984 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3988 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3989 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3990 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3991 TRACE_INTERFACE_VTABLE (printf ("]"));
3994 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3995 if (mono_security_core_clr_enabled ())
3996 mono_security_core_clr_check_override (klass, cm, im);
3998 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3999 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4000 char *body_name = mono_method_full_name (cm, TRUE);
4001 char *decl_name = mono_method_full_name (im, TRUE);
4002 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4010 MonoClass *ic = im->klass;
4011 const char *ic_name_space = ic->name_space;
4012 const char *ic_name = ic->name;
4015 if (! require_newslot) {
4016 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4019 if (cm->klass->rank == 0) {
4020 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4023 cmsig = mono_method_signature (cm);
4024 imsig = mono_method_signature (im);
4025 if (!cmsig || !imsig) {
4026 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4030 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4031 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4032 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4033 TRACE_INTERFACE_VTABLE (printf ("]"));
4036 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4037 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4040 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4041 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4044 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))) {
4045 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4049 subname = strstr (cm->name, ic_name_space);
4050 if (subname != cm->name) {
4051 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4054 subname += strlen (ic_name_space);
4055 if (subname [0] != '.') {
4056 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4060 if (strstr (subname, ic_name) != subname) {
4061 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4064 subname += strlen (ic_name);
4065 if (subname [0] != '.') {
4066 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4070 if (strcmp (subname, im->name) != 0) {
4071 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4075 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4076 if (mono_security_core_clr_enabled ())
4077 mono_security_core_clr_check_override (klass, cm, im);
4079 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4080 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4081 char *body_name = mono_method_full_name (cm, TRUE);
4082 char *decl_name = mono_method_full_name (im, TRUE);
4083 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4093 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4095 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4096 MonoMethod *method = key;
4097 MonoMethod *override = value;
4098 MonoClass *method_class = mono_method_get_class (method);
4099 MonoClass *override_class = mono_method_get_class (override);
4101 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4102 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4103 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4106 print_overrides (GHashTable *override_map, const char *message) {
4108 printf ("Override map \"%s\" START:\n", message);
4109 g_hash_table_foreach (override_map, foreach_override, NULL);
4110 printf ("Override map \"%s\" END.\n", message);
4112 printf ("Override map \"%s\" EMPTY.\n", message);
4116 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4117 char *full_name = mono_type_full_name (&klass->byval_arg);
4121 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4123 if (print_interfaces) {
4124 print_implemented_interfaces (klass);
4125 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4128 if (klass->parent) {
4129 parent_size = klass->parent->vtable_size;
4133 for (i = 0; i < size; ++i) {
4134 MonoMethod *cm = vtable [i];
4135 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4136 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4138 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4146 #if VERIFY_INTERFACE_VTABLE_CODE
4148 mono_method_try_get_vtable_index (MonoMethod *method)
4150 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4151 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4152 if (imethod->declaring->is_generic)
4153 return imethod->declaring->slot;
4155 return method->slot;
4159 mono_class_verify_vtable (MonoClass *klass)
4162 char *full_name = mono_type_full_name (&klass->byval_arg);
4164 printf ("*** Verifying VTable of class '%s' \n", full_name);
4168 if (!klass->methods)
4171 for (i = 0; i < klass->method.count; ++i) {
4172 MonoMethod *cm = klass->methods [i];
4175 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4179 full_name = mono_method_full_name (cm, TRUE);
4181 slot = mono_method_try_get_vtable_index (cm);
4183 if (slot >= klass->vtable_size) {
4184 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4188 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4189 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4190 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4191 g_free (other_name);
4194 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4201 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4203 char *method_signature;
4206 for (index = 0; index < onum; ++index) {
4207 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4208 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4210 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4211 type_name = mono_type_full_name (&klass->byval_arg);
4212 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4213 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4214 g_free (method_signature);
4216 mono_class_setup_methods (klass);
4217 if (klass->exception_type) {
4218 char *name = mono_type_get_full_name (klass);
4219 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4223 for (index = 0; index < klass->method.count; ++index) {
4224 MonoMethod *cm = klass->methods [index];
4225 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4227 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4228 g_free (method_signature);
4233 mono_method_get_method_definition (MonoMethod *method)
4235 while (method->is_inflated)
4236 method = ((MonoMethodInflated*)method)->declaring;
4241 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4245 for (i = 0; i < onum; ++i) {
4246 MonoMethod *decl = overrides [i * 2];
4247 MonoMethod *body = overrides [i * 2 + 1];
4249 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4250 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4254 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4255 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4256 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4258 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4262 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4263 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4264 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4266 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4270 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4271 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4275 body = mono_method_get_method_definition (body);
4276 decl = mono_method_get_method_definition (decl);
4278 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4279 char *body_name = mono_method_full_name (body, TRUE);
4280 char *decl_name = mono_method_full_name (decl, TRUE);
4281 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4291 mono_class_need_stelemref_method (MonoClass *klass)
4293 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4297 * LOCKING: this is supposed to be called with the loader lock held.
4300 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4304 MonoMethod **vtable;
4305 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4306 GPtrArray *ifaces = NULL;
4307 GHashTable *override_map = NULL;
4309 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4310 int first_non_interface_slot;
4312 GSList *virt_methods = NULL, *l;
4313 int stelemref_slot = 0;
4318 if (overrides && !verify_class_overrides (klass, overrides, onum))
4321 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4322 if (!mono_error_ok (&error)) {
4323 char *name = mono_type_get_full_name (klass);
4324 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4326 mono_error_cleanup (&error);
4328 } else if (ifaces) {
4329 for (i = 0; i < ifaces->len; i++) {
4330 MonoClass *ic = g_ptr_array_index (ifaces, i);
4331 max_vtsize += ic->method.count;
4333 g_ptr_array_free (ifaces, TRUE);
4337 if (klass->parent) {
4338 mono_class_init (klass->parent);
4339 mono_class_setup_vtable_full (klass->parent, in_setup);
4341 if (klass->parent->exception_type) {
4342 char *name = mono_type_get_full_name (klass->parent);
4343 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4348 max_vtsize += klass->parent->vtable_size;
4349 cur_slot = klass->parent->vtable_size;
4352 max_vtsize += klass->method.count;
4354 /*Array have a slot for stelemref*/
4355 if (mono_class_need_stelemref_method (klass)) {
4356 stelemref_slot = cur_slot;
4361 vtable = alloca (sizeof (gpointer) * max_vtsize);
4362 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4364 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4366 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4367 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4370 max_iid = klass->max_interface_id;
4371 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4373 /* Optimized version for generic instances */
4374 if (klass->generic_class) {
4376 MonoClass *gklass = klass->generic_class->container_class;
4379 mono_class_setup_vtable_full (gklass, in_setup);
4380 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4381 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4385 tmp = mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4386 klass->vtable_size = gklass->vtable_size;
4387 for (i = 0; i < gklass->vtable_size; ++i)
4388 if (gklass->vtable [i]) {
4389 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4390 if (!mono_error_ok (&error)) {
4391 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4392 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4394 mono_error_cleanup (&error);
4398 tmp [i]->slot = gklass->vtable [i]->slot;
4400 mono_memory_barrier ();
4401 klass->vtable = tmp;
4403 /* Have to set method->slot for abstract virtual methods */
4404 if (klass->methods && gklass->methods) {
4405 for (i = 0; i < klass->method.count; ++i)
4406 if (klass->methods [i]->slot == -1)
4407 klass->methods [i]->slot = gklass->methods [i]->slot;
4413 if (klass->parent && klass->parent->vtable_size) {
4414 MonoClass *parent = klass->parent;
4417 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4419 // Also inherit parent interface vtables, just as a starting point.
4420 // This is needed otherwise bug-77127.exe fails when the property methods
4421 // have different names in the iterface and the class, because for child
4422 // classes the ".override" information is not used anymore.
4423 for (i = 0; i < parent->interface_offsets_count; i++) {
4424 MonoClass *parent_interface = parent->interfaces_packed [i];
4425 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4426 /*FIXME this is now dead code as this condition will never hold true.
4427 Since interface offsets are inherited then the offset of an interface implemented
4428 by a parent will never be the out of it's vtable boundary.
4430 if (interface_offset >= parent->vtable_size) {
4431 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4434 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4435 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4436 for (j = 0; j < parent_interface->method.count && !klass->exception_type; j++) {
4437 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4438 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4439 parent_interface_offset + j, parent_interface_offset, j,
4440 interface_offset + j, interface_offset, j));
4447 /*Array have a slot for stelemref*/
4448 if (mono_class_need_stelemref_method (klass)) {
4449 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4451 method->slot = stelemref_slot;
4453 g_assert (method->slot == stelemref_slot);
4455 vtable [stelemref_slot] = method;
4458 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4459 /* override interface methods */
4460 for (i = 0; i < onum; i++) {
4461 MonoMethod *decl = overrides [i*2];
4462 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4464 dslot = mono_method_get_vtable_slot (decl);
4466 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4470 dslot += mono_class_interface_offset (klass, decl->klass);
4471 vtable [dslot] = overrides [i*2 + 1];
4472 vtable [dslot]->slot = dslot;
4474 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4476 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4478 if (mono_security_core_clr_enabled ())
4479 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4482 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4483 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4486 * Create a list of virtual methods to avoid calling
4487 * mono_class_get_virtual_methods () which is slow because of the metadata
4491 gpointer iter = NULL;
4494 virt_methods = NULL;
4495 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4496 virt_methods = g_slist_prepend (virt_methods, cm);
4498 if (klass->exception_type)
4502 // Loop on all implemented interfaces...
4503 for (i = 0; i < klass->interface_offsets_count; i++) {
4504 MonoClass *parent = klass->parent;
4506 gboolean interface_is_explicitly_implemented_by_class;
4509 ic = klass->interfaces_packed [i];
4510 ic_offset = mono_class_interface_offset (klass, ic);
4512 mono_class_setup_methods (ic);
4513 if (ic->exception_type)
4516 // Check if this interface is explicitly implemented (instead of just inherited)
4517 if (parent != NULL) {
4518 int implemented_interfaces_index;
4519 interface_is_explicitly_implemented_by_class = FALSE;
4520 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4521 if (ic == klass->interfaces [implemented_interfaces_index]) {
4522 interface_is_explicitly_implemented_by_class = TRUE;
4527 interface_is_explicitly_implemented_by_class = TRUE;
4530 // Loop on all interface methods...
4531 for (im_index = 0; im_index < ic->method.count; im_index++) {
4532 MonoMethod *im = ic->methods [im_index];
4533 int im_slot = ic_offset + im->slot;
4534 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4536 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4539 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4541 // If there is an explicit implementation, just use it right away,
4542 // otherwise look for a matching method
4543 if (override_im == NULL) {
4547 // First look for a suitable method among the class methods
4548 for (l = virt_methods; l; l = l->next) {
4550 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)));
4551 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4552 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4553 vtable [im_slot] = cm;
4554 /* Why do we need this? */
4559 TRACE_INTERFACE_VTABLE (printf ("\n"));
4560 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4564 // If the slot is still empty, look in all the inherited virtual methods...
4565 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4566 MonoClass *parent = klass->parent;
4567 // Reverse order, so that last added methods are preferred
4568 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4569 MonoMethod *cm = parent->vtable [cm_index];
4571 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));
4572 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4573 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4574 vtable [im_slot] = cm;
4575 /* Why do we need this? */
4581 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4583 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4587 g_assert (vtable [im_slot] == override_im);
4592 // If the class is not abstract, check that all its interface slots are full.
4593 // The check is done here and not directly at the end of the loop above because
4594 // it can happen (for injected generic array interfaces) that the same slot is
4595 // processed multiple times (those interfaces have overlapping slots), and it
4596 // will not always be the first pass the one that fills the slot.
4597 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4598 for (i = 0; i < klass->interface_offsets_count; i++) {
4602 ic = klass->interfaces_packed [i];
4603 ic_offset = mono_class_interface_offset (klass, ic);
4605 for (im_index = 0; im_index < ic->method.count; im_index++) {
4606 MonoMethod *im = ic->methods [im_index];
4607 int im_slot = ic_offset + im->slot;
4609 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4612 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4613 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4614 if (vtable [im_slot] == NULL) {
4615 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4622 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4623 for (l = virt_methods; l; l = l->next) {
4626 * If the method is REUSE_SLOT, we must check in the
4627 * base class for a method to override.
4629 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4631 for (k = klass->parent; k ; k = k->parent) {
4636 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4637 MonoMethodSignature *cmsig, *m1sig;
4639 cmsig = mono_method_signature (cm);
4640 m1sig = mono_method_signature (m1);
4642 if (!cmsig || !m1sig) {
4643 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4647 if (!strcmp(cm->name, m1->name) &&
4648 mono_metadata_signature_equal (cmsig, m1sig)) {
4650 if (mono_security_core_clr_enabled ())
4651 mono_security_core_clr_check_override (klass, cm, m1);
4653 slot = mono_method_get_vtable_slot (m1);
4657 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4658 char *body_name = mono_method_full_name (cm, TRUE);
4659 char *decl_name = mono_method_full_name (m1, TRUE);
4660 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4666 g_assert (cm->slot < max_vtsize);
4668 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4669 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4670 mono_method_full_name (m1, 1), m1,
4671 mono_method_full_name (cm, 1), cm));
4672 g_hash_table_insert (override_map, m1, cm);
4676 if (k->exception_type)
4686 /*Non final newslot methods must be given a non-interface vtable slot*/
4687 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4691 cm->slot = cur_slot++;
4693 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4694 vtable [cm->slot] = cm;
4697 /* override non interface methods */
4698 for (i = 0; i < onum; i++) {
4699 MonoMethod *decl = overrides [i*2];
4700 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4701 g_assert (decl->slot != -1);
4702 vtable [decl->slot] = overrides [i*2 + 1];
4703 overrides [i * 2 + 1]->slot = decl->slot;
4705 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4706 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4707 mono_method_full_name (decl, 1), decl,
4708 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4709 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4711 if (mono_security_core_clr_enabled ())
4712 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4717 * If a method occupies more than one place in the vtable, and it is
4718 * overriden, then change the other occurances too.
4723 for (i = 0; i < max_vtsize; ++i)
4725 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4727 cm = g_hash_table_lookup (override_map, vtable [i]);
4732 g_hash_table_destroy (override_map);
4733 override_map = NULL;
4736 g_slist_free (virt_methods);
4737 virt_methods = NULL;
4739 /* Ensure that all vtable slots are filled with concrete instance methods */
4740 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4741 for (i = 0; i < cur_slot; ++i) {
4742 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4743 char *type_name = mono_type_get_full_name (klass);
4744 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4745 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4747 g_free (method_name);
4753 if (klass->generic_class) {
4754 MonoClass *gklass = klass->generic_class->container_class;
4756 mono_class_init (gklass);
4758 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4760 /* Check that the vtable_size value computed in mono_class_init () is correct */
4761 if (klass->vtable_size)
4762 g_assert (cur_slot == klass->vtable_size);
4763 klass->vtable_size = cur_slot;
4766 /* Try to share the vtable with our parent. */
4767 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4768 mono_memory_barrier ();
4769 klass->vtable = klass->parent->vtable;
4771 MonoMethod **tmp = mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4772 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4773 mono_memory_barrier ();
4774 klass->vtable = tmp;
4777 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4778 if (mono_print_vtable) {
4781 print_implemented_interfaces (klass);
4783 for (i = 0; i <= max_iid; i++)
4784 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4787 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4788 klass->vtable_size, icount);
4790 for (i = 0; i < cur_slot; ++i) {
4795 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4796 mono_method_full_name (cm, TRUE));
4802 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4803 klass->name, max_iid);
4805 for (i = 0; i < klass->interface_count; i++) {
4806 ic = klass->interfaces [i];
4807 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4808 mono_class_interface_offset (klass, ic),
4809 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4812 for (k = klass->parent; k ; k = k->parent) {
4813 for (i = 0; i < k->interface_count; i++) {
4814 ic = k->interfaces [i];
4815 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4816 mono_class_interface_offset (klass, ic),
4817 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4823 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4828 char *name = mono_type_get_full_name (klass);
4829 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4832 g_hash_table_destroy (override_map);
4834 g_slist_free (virt_methods);
4839 * mono_method_get_vtable_slot:
4841 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4842 * LOCKING: Acquires the loader lock.
4844 * FIXME Use proper MonoError machinery here.
4847 mono_method_get_vtable_slot (MonoMethod *method)
4849 if (method->slot == -1) {
4850 mono_class_setup_vtable (method->klass);
4851 if (method->klass->exception_type)
4853 if (method->slot == -1) {
4857 if (!method->klass->generic_class) {
4858 g_assert (method->is_inflated);
4859 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4862 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4863 g_assert (method->klass->generic_class);
4864 gklass = method->klass->generic_class->container_class;
4865 mono_class_setup_methods (method->klass);
4866 g_assert (method->klass->methods);
4867 for (i = 0; i < method->klass->method.count; ++i) {
4868 if (method->klass->methods [i] == method)
4871 g_assert (i < method->klass->method.count);
4872 g_assert (gklass->methods);
4873 method->slot = gklass->methods [i]->slot;
4875 g_assert (method->slot != -1);
4877 return method->slot;
4881 * mono_method_get_vtable_index:
4884 * Returns the index into the runtime vtable to access the method or,
4885 * in the case of a virtual generic method, the virtual generic method
4886 * thunk. Returns -1 on failure.
4888 * FIXME Use proper MonoError machinery here.
4891 mono_method_get_vtable_index (MonoMethod *method)
4893 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4894 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4895 if (imethod->declaring->is_generic)
4896 return mono_method_get_vtable_slot (imethod->declaring);
4898 return mono_method_get_vtable_slot (method);
4901 static MonoMethod *default_ghc = NULL;
4902 static MonoMethod *default_finalize = NULL;
4903 static int finalize_slot = -1;
4904 static int ghc_slot = -1;
4907 initialize_object_slots (MonoClass *klass)
4912 if (klass == mono_defaults.object_class) {
4913 mono_class_setup_vtable (klass);
4914 for (i = 0; i < klass->vtable_size; ++i) {
4915 MonoMethod *cm = klass->vtable [i];
4917 if (!strcmp (cm->name, "GetHashCode"))
4919 else if (!strcmp (cm->name, "Finalize"))
4923 g_assert (ghc_slot > 0);
4924 default_ghc = klass->vtable [ghc_slot];
4926 g_assert (finalize_slot > 0);
4927 default_finalize = klass->vtable [finalize_slot];
4932 MonoMethod *array_method;
4934 } GenericArrayMethodInfo;
4936 static int generic_array_method_num = 0;
4937 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4940 generic_array_methods (MonoClass *klass)
4942 int i, count_generic = 0;
4943 GList *list = NULL, *tmp;
4944 if (generic_array_method_num)
4945 return generic_array_method_num;
4946 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4947 g_assert (!klass->parent->exception_type); /*So hitting this assert is a huge problem*/
4948 for (i = 0; i < klass->parent->method.count; i++) {
4949 MonoMethod *m = klass->parent->methods [i];
4950 if (!strncmp (m->name, "InternalArray__", 15)) {
4952 list = g_list_prepend (list, m);
4955 list = g_list_reverse (list);
4956 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4958 for (tmp = list; tmp; tmp = tmp->next) {
4959 const char *mname, *iname;
4961 MonoMethod *m = tmp->data;
4962 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4963 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4965 generic_array_method_info [i].array_method = m;
4966 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4967 iname = "System.Collections.Generic.ICollection`1.";
4968 mname = m->name + 27;
4969 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4970 iname = "System.Collections.Generic.IEnumerable`1.";
4971 mname = m->name + 27;
4972 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4973 iname = "System.Collections.Generic.IReadOnlyList`1.";
4974 mname = m->name + strlen (ireadonlylist_prefix);
4975 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4976 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4977 mname = m->name + strlen (ireadonlycollection_prefix);
4978 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4979 iname = "System.Collections.Generic.IList`1.";
4980 mname = m->name + 15;
4982 g_assert_not_reached ();
4985 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4986 strcpy (name, iname);
4987 strcpy (name + strlen (iname), mname);
4988 generic_array_method_info [i].name = name;
4991 /*g_print ("array generic methods: %d\n", count_generic);*/
4993 generic_array_method_num = count_generic;
4995 return generic_array_method_num;
4999 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5001 MonoGenericContext tmp_context;
5004 tmp_context.class_inst = NULL;
5005 tmp_context.method_inst = iface->generic_class->context.class_inst;
5006 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5008 for (i = 0; i < generic_array_method_num; i++) {
5010 MonoMethod *m = generic_array_method_info [i].array_method;
5011 MonoMethod *inflated;
5013 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5014 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5015 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5020 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5022 int null_length = strlen ("(null)");
5023 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5024 char *s = mono_image_alloc (image, len);
5027 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5028 g_assert (result == len - 1);
5034 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5036 gpointer exception_data = NULL;
5038 switch (error->exception_type) {
5039 case MONO_EXCEPTION_TYPE_LOAD:
5040 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5043 case MONO_EXCEPTION_MISSING_METHOD:
5044 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5047 case MONO_EXCEPTION_MISSING_FIELD: {
5048 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5049 const char *class_name;
5052 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5054 class_name = error->klass->name;
5056 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5059 g_free ((void*)class_name);
5063 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5066 if (error->ref_only)
5067 msg = "Cannot resolve dependency to assembly '%s' because it has not been preloaded. When using the ReflectionOnly APIs, dependent assemblies must be pre-loaded or loaded on demand through the ReflectionOnlyAssemblyResolve event.";
5069 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5071 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5075 case MONO_EXCEPTION_BAD_IMAGE:
5076 exception_data = error->msg;
5080 g_assert_not_reached ();
5083 mono_class_set_failure (klass, error->exception_type, exception_data);
5088 * @class: the class to initialize
5090 * Compute the instance_size, class_size and other infos that cannot be
5091 * computed at mono_class_get() time. Also compute vtable_size if possible.
5092 * Returns TRUE on success or FALSE if there was a problem in loading
5093 * the type (incorrect assemblies, missing assemblies, methods, etc).
5095 * LOCKING: Acquires the loader lock.
5098 mono_class_init (MonoClass *klass)
5101 MonoCachedClassInfo cached_info;
5102 gboolean has_cached_info;
5106 /* Double-checking locking pattern */
5107 if (klass->inited || klass->exception_type)
5108 return klass->exception_type == MONO_EXCEPTION_NONE;
5110 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5112 /* We do everything inside the lock to prevent races */
5113 mono_loader_lock ();
5115 if (klass->inited || klass->exception_type) {
5116 mono_loader_unlock ();
5117 /* Somebody might have gotten in before us */
5118 return klass->exception_type == MONO_EXCEPTION_NONE;
5121 if (klass->init_pending) {
5122 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5126 klass->init_pending = 1;
5128 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5129 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5134 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5135 MonoClass *element_class = klass->element_class;
5136 if (!element_class->inited)
5137 mono_class_init (element_class);
5138 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5139 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5144 mono_stats.initialized_class_count++;
5146 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5147 MonoClass *gklass = klass->generic_class->container_class;
5149 mono_stats.generic_class_count++;
5151 klass->method = gklass->method;
5152 klass->field = gklass->field;
5154 mono_class_init (gklass);
5155 // FIXME: Why is this needed ?
5156 if (!gklass->exception_type)
5157 mono_class_setup_methods (gklass);
5158 if (gklass->exception_type) {
5159 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5163 if (MONO_CLASS_IS_INTERFACE (klass))
5164 klass->interface_id = mono_get_unique_iid (klass);
5167 if (klass->parent && !klass->parent->inited)
5168 mono_class_init (klass->parent);
5170 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5172 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5173 klass->nested_classes_inited = TRUE;
5176 * Computes the size used by the fields, and their locations
5178 if (has_cached_info) {
5179 klass->instance_size = cached_info.instance_size;
5180 klass->sizes.class_size = cached_info.class_size;
5181 klass->packing_size = cached_info.packing_size;
5182 klass->min_align = cached_info.min_align;
5183 klass->blittable = cached_info.blittable;
5184 klass->has_references = cached_info.has_references;
5185 klass->has_static_refs = cached_info.has_static_refs;
5186 klass->no_special_static_fields = cached_info.no_special_static_fields;
5189 if (!klass->size_inited){
5190 mono_class_setup_fields (klass);
5191 if (klass->exception_type || mono_loader_get_last_error ())
5195 /* Initialize arrays */
5197 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5199 if (klass->interface_count) {
5200 int count_generic = generic_array_methods (klass);
5201 klass->method.count += klass->interface_count * count_generic;
5205 mono_class_setup_supertypes (klass);
5208 initialize_object_slots (klass);
5211 * Initialize the rest of the data without creating a generic vtable if possible.
5212 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5213 * also avoid computing a generic vtable.
5215 if (has_cached_info) {
5217 klass->vtable_size = cached_info.vtable_size;
5218 klass->has_finalize = cached_info.has_finalize;
5219 klass->has_finalize_inited = TRUE;
5220 klass->ghcimpl = cached_info.ghcimpl;
5221 klass->has_cctor = cached_info.has_cctor;
5222 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5223 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5224 * The first slot if for array with.
5226 static int szarray_vtable_size[2] = { 0 };
5228 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5231 if (!szarray_vtable_size [slot]) {
5232 mono_class_setup_vtable (klass);
5233 szarray_vtable_size [slot] = klass->vtable_size;
5235 klass->vtable_size = szarray_vtable_size[slot];
5237 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5238 MonoClass *gklass = klass->generic_class->container_class;
5240 /* Generic instance case */
5241 klass->ghcimpl = gklass->ghcimpl;
5242 klass->has_cctor = gklass->has_cctor;
5244 mono_class_setup_vtable (gklass);
5245 if (gklass->exception_type) {
5246 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5250 klass->vtable_size = gklass->vtable_size;
5254 /* ghcimpl is not currently used
5256 if (klass->parent) {
5257 MonoMethod *cmethod = klass->vtable [ghc_slot];
5258 if (cmethod->is_inflated)
5259 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5260 if (cmethod == default_ghc) {
5266 /* C# doesn't allow interfaces to have cctors */
5267 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5268 MonoMethod *cmethod = NULL;
5270 if (klass->type_token && !image_is_dynamic(klass->image)) {
5271 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5272 /* The find_method function ignores the 'flags' argument */
5273 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5274 klass->has_cctor = 1;
5276 mono_class_setup_methods (klass);
5277 if (klass->exception_type)
5280 for (i = 0; i < klass->method.count; ++i) {
5281 MonoMethod *method = klass->methods [i];
5282 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5283 (strcmp (".cctor", method->name) == 0)) {
5284 klass->has_cctor = 1;
5292 if (klass->parent) {
5293 int first_iface_slot;
5294 /* This will compute klass->parent->vtable_size for some classes */
5295 mono_class_init (klass->parent);
5296 if (klass->parent->exception_type) {
5297 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5300 if (mono_loader_get_last_error ())
5302 if (!klass->parent->vtable_size) {
5303 /* FIXME: Get rid of this somehow */
5304 mono_class_setup_vtable (klass->parent);
5305 if (klass->parent->exception_type) {
5306 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5309 if (mono_loader_get_last_error ())
5312 first_iface_slot = klass->parent->vtable_size;
5313 if (mono_class_need_stelemref_method (klass))
5315 setup_interface_offsets (klass, first_iface_slot, TRUE);
5317 setup_interface_offsets (klass, 0, TRUE);
5320 if (mono_security_core_clr_enabled ())
5321 mono_security_core_clr_check_inheritance (klass);
5323 if (mono_loader_get_last_error ()) {
5324 if (klass->exception_type == MONO_EXCEPTION_NONE) {
5325 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5327 mono_loader_clear_error ();
5330 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5331 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5336 /* Because of the double-checking locking pattern */
5337 mono_memory_barrier ();
5339 klass->init_pending = 0;
5341 mono_loader_unlock ();
5343 return klass->exception_type == MONO_EXCEPTION_NONE;
5347 * mono_class_has_finalizer:
5349 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5353 mono_class_has_finalizer (MonoClass *klass)
5355 gboolean has_finalize = FALSE;
5357 if (klass->has_finalize_inited)
5358 return klass->has_finalize;
5360 /* Interfaces and valuetypes are not supposed to have finalizers */
5361 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5362 MonoMethod *cmethod = NULL;
5364 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5365 } else if (klass->generic_class) {
5366 MonoClass *gklass = klass->generic_class->container_class;
5368 has_finalize = mono_class_has_finalizer (gklass);
5369 } else if (klass->parent && klass->parent->has_finalize) {
5370 has_finalize = TRUE;
5372 if (klass->parent) {
5374 * Can't search in metadata for a method named Finalize, because that
5375 * ignores overrides.
5377 mono_class_setup_vtable (klass);
5378 if (klass->exception_type || mono_loader_get_last_error ())
5381 cmethod = klass->vtable [finalize_slot];
5385 g_assert (klass->vtable_size > finalize_slot);
5387 if (klass->parent) {
5388 if (cmethod->is_inflated)
5389 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5390 if (cmethod != default_finalize)
5391 has_finalize = TRUE;
5397 mono_image_lock (klass->image);
5399 if (!klass->has_finalize_inited) {
5400 klass->has_finalize = has_finalize ? 1 : 0;
5402 mono_memory_barrier ();
5403 klass->has_finalize_inited = TRUE;
5406 mono_image_unlock (klass->image);
5408 return klass->has_finalize;
5412 mono_is_corlib_image (MonoImage *image)
5414 /* FIXME: allow the dynamic case for our compilers and with full trust */
5415 if (image_is_dynamic (image))
5416 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5418 return image == mono_defaults.corlib;
5422 * LOCKING: this assumes the loader lock is held
5425 mono_class_setup_mono_type (MonoClass *klass)
5427 const char *name = klass->name;
5428 const char *nspace = klass->name_space;
5429 gboolean is_corlib = mono_is_corlib_image (klass->image);
5431 klass->this_arg.byref = 1;
5432 klass->this_arg.data.klass = klass;
5433 klass->this_arg.type = MONO_TYPE_CLASS;
5434 klass->byval_arg.data.klass = klass;
5435 klass->byval_arg.type = MONO_TYPE_CLASS;
5437 if (is_corlib && !strcmp (nspace, "System")) {
5438 if (!strcmp (name, "ValueType")) {
5440 * do not set the valuetype bit for System.ValueType.
5441 * klass->valuetype = 1;
5443 klass->blittable = TRUE;
5444 } else if (!strcmp (name, "Enum")) {
5446 * do not set the valuetype bit for System.Enum.
5447 * klass->valuetype = 1;
5449 klass->valuetype = 0;
5450 klass->enumtype = 0;
5451 } else if (!strcmp (name, "Object")) {
5452 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_OBJECT;
5453 } else if (!strcmp (name, "String")) {
5454 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_STRING;
5455 } else if (!strcmp (name, "TypedReference")) {
5456 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5460 if (klass->valuetype) {
5461 int t = MONO_TYPE_VALUETYPE;
5463 if (is_corlib && !strcmp (nspace, "System")) {
5466 if (!strcmp (name, "Boolean")) {
5467 t = MONO_TYPE_BOOLEAN;
5468 } else if (!strcmp(name, "Byte")) {
5470 klass->blittable = TRUE;
5474 if (!strcmp (name, "Char")) {
5479 if (!strcmp (name, "Double")) {
5481 klass->blittable = TRUE;
5485 if (!strcmp (name, "Int32")) {
5487 klass->blittable = TRUE;
5488 } else if (!strcmp(name, "Int16")) {
5490 klass->blittable = TRUE;
5491 } else if (!strcmp(name, "Int64")) {
5493 klass->blittable = TRUE;
5494 } else if (!strcmp(name, "IntPtr")) {
5496 klass->blittable = TRUE;
5500 if (!strcmp (name, "Single")) {
5502 klass->blittable = TRUE;
5503 } else if (!strcmp(name, "SByte")) {
5505 klass->blittable = TRUE;
5509 if (!strcmp (name, "UInt32")) {
5511 klass->blittable = TRUE;
5512 } else if (!strcmp(name, "UInt16")) {
5514 klass->blittable = TRUE;
5515 } else if (!strcmp(name, "UInt64")) {
5517 klass->blittable = TRUE;
5518 } else if (!strcmp(name, "UIntPtr")) {
5520 klass->blittable = TRUE;
5524 if (!strcmp (name, "TypedReference")) {
5525 t = MONO_TYPE_TYPEDBYREF;
5526 klass->blittable = TRUE;
5530 if (!strcmp (name, "Void")) {
5538 klass->this_arg.type = klass->byval_arg.type = t;
5541 if (MONO_CLASS_IS_INTERFACE (klass))
5542 klass->interface_id = mono_get_unique_iid (klass);
5548 * COM initialization is delayed until needed.
5549 * However when a [ComImport] attribute is present on a type it will trigger
5550 * the initialization. This is not a problem unless the BCL being executed
5551 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5554 init_com_from_comimport (MonoClass *klass)
5556 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5557 if (mono_security_core_clr_enabled ()) {
5558 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5559 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5560 /* but it can not be made available for application (i.e. user code) since all COM calls
5561 * are considered native calls. In this case we fail with a TypeLoadException (just like
5562 * Silverlight 2 does */
5563 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5568 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5570 #endif /*DISABLE_COM*/
5573 * LOCKING: this assumes the loader lock is held
5576 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5578 gboolean system_namespace;
5579 gboolean is_corlib = mono_is_corlib_image (klass->image);
5581 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5583 /* if root of the hierarchy */
5584 if (system_namespace && !strcmp (klass->name, "Object")) {
5585 klass->parent = NULL;
5586 klass->instance_size = sizeof (MonoObject);
5589 if (!strcmp (klass->name, "<Module>")) {
5590 klass->parent = NULL;
5591 klass->instance_size = 0;
5595 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5596 /* Imported COM Objects always derive from __ComObject. */
5598 if (MONO_CLASS_IS_IMPORT (klass)) {
5599 init_com_from_comimport (klass);
5600 if (parent == mono_defaults.object_class)
5601 parent = mono_class_get_com_object_class ();
5605 /* set the parent to something useful and safe, but mark the type as broken */
5606 parent = mono_defaults.object_class;
5607 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5610 klass->parent = parent;
5612 if (parent->generic_class && !parent->name) {
5614 * If the parent is a generic instance, we may get
5615 * called before it is fully initialized, especially
5616 * before it has its name.
5621 #ifndef DISABLE_REMOTING
5622 klass->marshalbyref = parent->marshalbyref;
5623 klass->contextbound = parent->contextbound;
5626 klass->delegate = parent->delegate;
5628 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5629 mono_class_set_is_com_object (klass);
5631 if (system_namespace) {
5632 #ifndef DISABLE_REMOTING
5633 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5634 klass->marshalbyref = 1;
5636 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5637 klass->contextbound = 1;
5639 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5640 klass->delegate = 1;
5643 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5644 (strcmp (klass->parent->name_space, "System") == 0)))
5645 klass->valuetype = 1;
5646 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5647 klass->valuetype = klass->enumtype = 1;
5649 /*klass->enumtype = klass->parent->enumtype; */
5651 /* initialize com types if COM interfaces are present */
5653 if (MONO_CLASS_IS_IMPORT (klass))
5654 init_com_from_comimport (klass);
5656 klass->parent = NULL;
5662 * mono_class_setup_supertypes:
5665 * Build the data structure needed to make fast type checks work.
5666 * This currently sets two fields in @class:
5667 * - idepth: distance between @class and System.Object in the type
5669 * - supertypes: array of classes: each element has a class in the hierarchy
5670 * starting from @class up to System.Object
5672 * LOCKING: This function is atomic, in case of contention we waste memory.
5675 mono_class_setup_supertypes (MonoClass *klass)
5678 MonoClass **supertypes;
5680 mono_atomic_load_acquire (supertypes, void*, &klass->supertypes);
5684 if (klass->parent && !klass->parent->supertypes)
5685 mono_class_setup_supertypes (klass->parent);
5687 klass->idepth = klass->parent->idepth + 1;
5691 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5692 supertypes = mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5694 if (klass->parent) {
5695 supertypes [klass->idepth - 1] = klass;
5696 memcpy (supertypes, klass->parent->supertypes, klass->parent->idepth * sizeof (gpointer));
5698 supertypes [0] = klass;
5701 mono_atomic_store_release (&klass->supertypes, supertypes);
5705 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5707 MonoClass *gtd = (MonoClass*)user_data;
5708 /* Only try to fix generic instances of @gtd */
5709 if (gclass->generic_class->container_class != gtd)
5712 /* Check if the generic instance has no parent. */
5713 if (gtd->parent && !gclass->parent)
5714 mono_generic_class_setup_parent (gclass, gtd);
5720 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5722 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5723 mono_error_set_type_load_class (error, klass, msg);
5727 mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
5729 MonoLoaderError *lerror = mono_loader_get_last_error ();
5732 set_failure_from_loader_error (klass, lerror);
5733 mono_error_set_from_loader_error (error);
5737 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
5738 mono_error_set_type_load_class (error, klass, msg);
5743 * mono_class_create_from_typedef:
5744 * @image: image where the token is valid
5745 * @type_token: typedef token
5746 * @error: used to return any error found while creating the type
5748 * Create the MonoClass* representing the specified type token.
5749 * @type_token must be a TypeDef token.
5751 * FIXME: don't return NULL on failure, just the the caller figure it out.
5754 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5756 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5757 MonoClass *klass, *parent = NULL;
5758 guint32 cols [MONO_TYPEDEF_SIZE];
5759 guint32 cols_next [MONO_TYPEDEF_SIZE];
5760 guint tidx = mono_metadata_token_index (type_token);
5761 MonoGenericContext *context = NULL;
5762 const char *name, *nspace;
5764 MonoClass **interfaces;
5765 guint32 field_last, method_last;
5766 guint32 nesting_tokeen;
5768 mono_error_init (error);
5770 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5771 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5772 mono_loader_assert_no_error ();
5776 mono_loader_lock ();
5778 if ((klass = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5779 mono_loader_unlock ();
5780 mono_loader_assert_no_error ();
5784 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5786 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5787 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5789 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5792 klass->name_space = nspace;
5794 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5796 klass->image = image;
5797 klass->type_token = type_token;
5798 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5800 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5802 classes_size += sizeof (MonoClass);
5805 * Check whether we're a generic type definition.
5807 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5808 if (klass->generic_container) {
5809 klass->is_generic = 1;
5810 klass->generic_container->owner.klass = klass;
5811 context = &klass->generic_container->context;
5814 if (klass->generic_container)
5815 enable_gclass_recording ();
5817 if (cols [MONO_TYPEDEF_EXTENDS]) {
5819 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5821 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5822 /*WARNING: this must satisfy mono_metadata_type_hash*/
5823 klass->this_arg.byref = 1;
5824 klass->this_arg.data.klass = klass;
5825 klass->this_arg.type = MONO_TYPE_CLASS;
5826 klass->byval_arg.data.klass = klass;
5827 klass->byval_arg.type = MONO_TYPE_CLASS;
5829 parent = mono_class_get_checked (image, parent_token, error);
5830 if (parent && context) /* Always inflate */
5831 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5833 if (parent == NULL) {
5834 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5835 goto parent_failure;
5838 for (tmp = parent; tmp; tmp = tmp->parent) {
5840 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5841 goto parent_failure;
5843 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5844 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5845 goto parent_failure;
5850 mono_class_setup_parent (klass, parent);
5852 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5853 mono_class_setup_mono_type (klass);
5855 if (klass->generic_container)
5856 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5859 * This might access klass->byval_arg for recursion generated by generic constraints,
5860 * so it has to come after setup_mono_type ().
5862 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5863 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5864 if (!mono_error_ok (error)) {
5865 /*FIXME implement a mono_class_set_failure_from_mono_error */
5866 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5867 mono_loader_unlock ();
5868 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5869 mono_loader_assert_no_error ();
5874 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5878 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5882 klass->cast_class = klass->element_class = klass;
5884 if (!klass->enumtype) {
5885 if (!mono_metadata_interfaces_from_typedef_full (
5886 image, type_token, &interfaces, &icount, FALSE, context, error)){
5888 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5889 mono_loader_unlock ();
5890 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5894 klass->interfaces = interfaces;
5895 klass->interface_count = icount;
5896 klass->interfaces_inited = 1;
5899 /*g_print ("Load class %s\n", name);*/
5902 * Compute the field and method lists
5904 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5905 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5907 if (tt->rows > tidx){
5908 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5909 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5910 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5912 field_last = image->tables [MONO_TABLE_FIELD].rows;
5913 method_last = image->tables [MONO_TABLE_METHOD].rows;
5916 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5917 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5918 klass->field.count = field_last - klass->field.first;
5920 klass->field.count = 0;
5922 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5923 klass->method.count = method_last - klass->method.first;
5925 klass->method.count = 0;
5927 /* reserve space to store vector pointer in arrays */
5928 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5929 klass->instance_size += 2 * sizeof (gpointer);
5930 g_assert (klass->field.count == 0);
5933 if (klass->enumtype) {
5934 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5935 if (!enum_basetype) {
5936 /*set it to a default value as the whole runtime can't handle this to be null*/
5937 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5938 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5939 mono_loader_unlock ();
5940 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5941 mono_loader_assert_no_error ();
5944 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5948 * If we're a generic type definition, load the constraints.
5949 * We must do this after the class has been constructed to make certain recursive scenarios
5952 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5953 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5954 mono_loader_unlock ();
5955 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5956 mono_loader_assert_no_error ();
5960 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5961 if (!strncmp (name, "Vector", 6))
5962 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");
5965 mono_loader_unlock ();
5967 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5968 mono_loader_assert_no_error ();
5973 mono_class_setup_mono_type (klass);
5974 mono_loader_unlock ();
5975 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5976 mono_loader_assert_no_error ();
5980 /** is klass Nullable<T>? */
5982 mono_class_is_nullable (MonoClass *klass)
5984 return klass->generic_class != NULL &&
5985 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5989 /** if klass is T? return T */
5991 mono_class_get_nullable_param (MonoClass *klass)
5993 g_assert (mono_class_is_nullable (klass));
5994 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5998 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6002 MonoGenericClass *gclass = klass->generic_class;
6004 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6005 if (!mono_error_ok (&error)) {
6006 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6007 klass->parent = mono_defaults.object_class;
6008 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6009 mono_error_cleanup (&error);
6013 mono_class_setup_parent (klass, klass->parent);
6015 if (klass->enumtype) {
6016 klass->cast_class = gtd->cast_class;
6017 klass->element_class = gtd->element_class;
6023 * Create the `MonoClass' for an instantiation of a generic type.
6024 * We only do this if we actually need it.
6027 mono_generic_class_get_class (MonoGenericClass *gclass)
6029 MonoClass *klass, *gklass;
6031 if (gclass->cached_class)
6032 return gclass->cached_class;
6034 mono_loader_lock ();
6035 if (gclass->cached_class) {
6036 mono_loader_unlock ();
6037 return gclass->cached_class;
6040 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6042 gklass = gclass->container_class;
6044 if (record_gclass_instantiation > 0)
6045 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6047 if (gklass->nested_in) {
6048 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6049 klass->nested_in = gklass->nested_in;
6052 klass->name = gklass->name;
6053 klass->name_space = gklass->name_space;
6055 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6057 klass->image = gklass->image;
6058 klass->flags = gklass->flags;
6059 klass->type_token = gklass->type_token;
6060 klass->field.count = gklass->field.count;
6062 klass->is_inflated = 1;
6063 klass->generic_class = gclass;
6065 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6066 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6067 klass->this_arg.byref = TRUE;
6068 klass->enumtype = gklass->enumtype;
6069 klass->valuetype = gklass->valuetype;
6071 klass->cast_class = klass->element_class = klass;
6073 if (mono_class_is_nullable (klass))
6074 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6077 * We're not interested in the nested classes of a generic instance.
6078 * We use the generic type definition to look for nested classes.
6081 mono_generic_class_setup_parent (klass, gklass);
6083 if (gclass->is_dynamic) {
6085 * 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.
6086 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6087 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6089 if (!gklass->wastypebuilder)
6092 mono_class_setup_supertypes (klass);
6094 if (klass->enumtype) {
6096 * For enums, gklass->fields might not been set, but instance_size etc. is
6097 * already set in mono_reflection_create_internal_class (). For non-enums,
6098 * these will be computed normally in mono_class_layout_fields ().
6100 klass->instance_size = gklass->instance_size;
6101 klass->sizes.class_size = gklass->sizes.class_size;
6102 mono_memory_barrier ();
6103 klass->size_inited = 1;
6107 mono_memory_barrier ();
6108 gclass->cached_class = klass;
6110 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6112 inflated_classes ++;
6113 inflated_classes_size += sizeof (MonoClass);
6115 mono_loader_unlock ();
6121 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6123 MonoClass *klass, **ptr;
6125 MonoGenericContainer *container = mono_generic_param_owner (param);
6129 image = mono_defaults.corlib;
6131 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6132 classes_size += sizeof (MonoClass);
6135 klass->name = pinfo->name;
6137 int n = mono_generic_param_num (param);
6138 klass->name = mono_image_alloc0 (image, 16);
6139 sprintf ((char*)klass->name, "%d", n);
6144 MonoMethod *omethod = container->owner.method;
6145 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6147 MonoClass *oklass = container->owner.klass;
6148 klass->name_space = oklass ? oklass->name_space : "";
6151 klass->name_space = "";
6154 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6158 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6162 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6163 klass->parent = pinfo->constraints [0];
6165 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6166 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6168 klass->parent = mono_defaults.object_class;
6171 if (count - pos > 0) {
6172 klass->interface_count = count - pos;
6173 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6174 klass->interfaces_inited = TRUE;
6175 for (i = pos; i < count; i++)
6176 klass->interfaces [i - pos] = pinfo->constraints [i];
6179 klass->image = image;
6181 klass->inited = TRUE;
6182 klass->cast_class = klass->element_class = klass;
6183 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6185 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6186 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6187 klass->this_arg.byref = TRUE;
6189 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6190 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6192 /*Init these fields to sane values*/
6193 klass->min_align = 1;
6195 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6196 * constrained to, the JIT depends on this.
6198 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6199 mono_memory_barrier ();
6200 klass->size_inited = 1;
6201 klass->setup_fields_called = 1;
6203 mono_class_setup_supertypes (klass);
6205 if (count - pos > 0) {
6206 mono_class_setup_vtable (klass->parent);
6207 if (klass->parent->exception_type)
6208 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6210 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6216 #define FAST_CACHE_SIZE 16
6219 * LOCKING: Takes the image lock depending on @take_lock.
6222 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6224 int n = mono_generic_param_num (param);
6225 MonoImage *image = param->image;
6226 MonoClass *klass = NULL;
6231 if (param->gshared_constraint) {
6232 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6235 mono_image_lock (image);
6236 klass = g_hash_table_lookup (ht, param);
6238 mono_image_unlock (image);
6243 if (n < FAST_CACHE_SIZE) {
6245 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6247 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6249 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6252 mono_image_lock (image);
6253 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6255 mono_image_unlock (image);
6262 * LOCKING: Image lock (param->image) must be held
6265 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6267 int n = mono_generic_param_num (param);
6268 MonoImage *image = param->image;
6272 if (param->gshared_constraint) {
6273 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6275 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6276 mono_memory_barrier ();
6278 image->mvar_cache_constrained = ht;
6280 image->var_cache_constrained = ht;
6282 g_hash_table_insert (ht, param, klass);
6283 } else if (n < FAST_CACHE_SIZE) {
6285 /* Requires locking to avoid droping an already published class */
6286 if (!image->mvar_cache_fast)
6287 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6288 image->mvar_cache_fast [n] = klass;
6290 if (!image->var_cache_fast)
6291 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6292 image->var_cache_fast [n] = klass;
6295 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6297 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6299 ht = g_hash_table_new (NULL, NULL);
6300 mono_memory_barrier ();
6302 image->mvar_cache_slow = ht;
6304 image->var_cache_slow = ht;
6307 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6312 * LOCKING: Acquires the image lock (@image).
6315 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6317 MonoGenericContainer *container = mono_generic_param_owner (param);
6318 MonoGenericParamInfo *pinfo = NULL;
6319 MonoClass *klass, *klass2;
6322 pinfo = mono_generic_param_info (param);
6323 klass = pinfo->pklass;
6326 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6331 if (!image && container) {
6333 MonoMethod *method = container->owner.method;
6334 image = (method && method->klass) ? method->klass->image : NULL;
6336 MonoClass *klass = container->owner.klass;
6337 // FIXME: 'klass' should not be null
6338 // But, monodis creates GenericContainers without associating a owner to it
6339 image = klass ? klass->image : NULL;
6343 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6345 mono_memory_barrier ();
6347 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6348 image = mono_defaults.corlib;
6350 mono_image_lock (image);
6352 klass2 = pinfo->pklass;
6354 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6360 pinfo->pklass = klass;
6362 set_anon_gparam_class (param, is_mvar, klass);
6364 mono_image_unlock (image);
6366 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6368 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6370 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6376 mono_ptr_class_get (MonoType *type)
6379 MonoClass *el_class;
6383 el_class = mono_class_from_mono_type (type);
6384 image = el_class->image;
6386 mono_image_lock (image);
6387 if (image->ptr_cache) {
6388 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6389 mono_image_unlock (image);
6393 mono_image_unlock (image);
6395 result = mono_image_alloc0 (image, sizeof (MonoClass));
6397 classes_size += sizeof (MonoClass);
6399 result->parent = NULL; /* no parent for PTR types */
6400 result->name_space = el_class->name_space;
6401 name = g_strdup_printf ("%s*", el_class->name);
6402 result->name = mono_image_strdup (image, name);
6405 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6407 result->image = el_class->image;
6408 result->inited = TRUE;
6409 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6410 /* Can pointers get boxed? */
6411 result->instance_size = sizeof (gpointer);
6412 result->cast_class = result->element_class = el_class;
6413 result->blittable = TRUE;
6415 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6416 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6417 result->this_arg.byref = TRUE;
6419 mono_class_setup_supertypes (result);
6421 mono_image_lock (image);
6422 if (image->ptr_cache) {
6424 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6425 mono_image_unlock (image);
6426 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6430 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6432 g_hash_table_insert (image->ptr_cache, el_class, result);
6433 mono_image_unlock (image);
6435 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6441 mono_fnptr_class_get (MonoMethodSignature *sig)
6444 static GHashTable *ptr_hash = NULL;
6446 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6448 mono_loader_lock ();
6451 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6453 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6454 mono_loader_unlock ();
6457 result = g_new0 (MonoClass, 1);
6459 result->parent = NULL; /* no parent for PTR types */
6460 result->name_space = "System";
6461 result->name = "MonoFNPtrFakeClass";
6463 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6465 result->image = mono_defaults.corlib; /* need to fix... */
6466 result->inited = TRUE;
6467 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6468 /* Can pointers get boxed? */
6469 result->instance_size = sizeof (gpointer);
6470 result->cast_class = result->element_class = result;
6471 result->blittable = TRUE;
6473 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6474 result->this_arg.data.method = result->byval_arg.data.method = sig;
6475 result->this_arg.byref = TRUE;
6476 result->blittable = TRUE;
6478 mono_class_setup_supertypes (result);
6480 g_hash_table_insert (ptr_hash, sig, result);
6482 mono_loader_unlock ();
6484 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6490 mono_class_from_mono_type (MonoType *type)
6492 switch (type->type) {
6493 case MONO_TYPE_OBJECT:
6494 return type->data.klass? type->data.klass: mono_defaults.object_class;
6495 case MONO_TYPE_VOID:
6496 return type->data.klass? type->data.klass: mono_defaults.void_class;
6497 case MONO_TYPE_BOOLEAN:
6498 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6499 case MONO_TYPE_CHAR:
6500 return type->data.klass? type->data.klass: mono_defaults.char_class;
6502 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6504 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6506 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6508 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6510 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6512 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6514 return type->data.klass? type->data.klass: mono_defaults.int_class;
6516 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6518 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6520 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6522 return type->data.klass? type->data.klass: mono_defaults.single_class;
6524 return type->data.klass? type->data.klass: mono_defaults.double_class;
6525 case MONO_TYPE_STRING:
6526 return type->data.klass? type->data.klass: mono_defaults.string_class;
6527 case MONO_TYPE_TYPEDBYREF:
6528 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6529 case MONO_TYPE_ARRAY:
6530 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6532 return mono_ptr_class_get (type->data.type);
6533 case MONO_TYPE_FNPTR:
6534 return mono_fnptr_class_get (type->data.method);
6535 case MONO_TYPE_SZARRAY:
6536 return mono_array_class_get (type->data.klass, 1);
6537 case MONO_TYPE_CLASS:
6538 case MONO_TYPE_VALUETYPE:
6539 return type->data.klass;
6540 case MONO_TYPE_GENERICINST:
6541 return mono_generic_class_get_class (type->data.generic_class);
6543 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6544 case MONO_TYPE_MVAR:
6545 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6547 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6548 g_assert_not_reached ();
6555 * mono_type_retrieve_from_typespec
6556 * @image: context where the image is created
6557 * @type_spec: typespec token
6558 * @context: the generic context used to evaluate generic instantiations in
6561 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6563 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6565 *did_inflate = FALSE;
6570 if (context && (context->class_inst || context->method_inst)) {
6571 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6573 if (!mono_error_ok (error)) {
6574 mono_loader_assert_no_error ();
6580 *did_inflate = TRUE;
6587 * mono_class_create_from_typespec
6588 * @image: context where the image is created
6589 * @type_spec: typespec token
6590 * @context: the generic context used to evaluate generic instantiations in
6593 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6596 gboolean inflated = FALSE;
6597 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6598 if (!mono_error_ok (error))
6600 ret = mono_class_from_mono_type (t);
6602 mono_metadata_free_type (t);
6607 * mono_bounded_array_class_get:
6608 * @element_class: element class
6609 * @rank: the dimension of the array class
6610 * @bounded: whenever the array has non-zero bounds
6612 * Returns: a class object describing the array with element type @element_type and
6616 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6620 MonoClass *parent = NULL;
6621 GSList *list, *rootlist = NULL;
6624 gboolean corlib_type = FALSE;
6626 g_assert (rank <= 255);
6629 /* bounded only matters for one-dimensional arrays */
6632 image = eclass->image;
6634 if (rank == 1 && !bounded) {
6636 * This case is very frequent not just during compilation because of calls
6637 * from mono_class_from_mono_type (), mono_array_new (),
6638 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6640 mono_os_mutex_lock (&image->szarray_cache_lock);
6641 if (!image->szarray_cache)
6642 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6643 klass = g_hash_table_lookup (image->szarray_cache, eclass);
6644 mono_os_mutex_unlock (&image->szarray_cache_lock);
6648 mono_loader_lock ();
6650 mono_loader_lock ();
6652 if (!image->array_cache)
6653 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6655 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6656 for (; list; list = list->next) {
6658 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6659 mono_loader_unlock ();
6666 /* for the building corlib use System.Array from it */
6667 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6668 parent = mono_class_from_name (image, "System", "Array");
6671 parent = mono_defaults.array_class;
6672 if (!parent->inited)
6673 mono_class_init (parent);
6676 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6678 klass->image = image;
6679 klass->name_space = eclass->name_space;
6680 nsize = strlen (eclass->name);
6681 name = g_malloc (nsize + 2 + rank + 1);
6682 memcpy (name, eclass->name, nsize);
6685 memset (name + nsize + 1, ',', rank - 1);
6687 name [nsize + rank] = '*';
6688 name [nsize + rank + bounded] = ']';
6689 name [nsize + rank + bounded + 1] = 0;
6690 klass->name = mono_image_strdup (image, name);
6693 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6695 classes_size += sizeof (MonoClass);
6697 klass->type_token = 0;
6698 /* all arrays are marked serializable and sealed, bug #42779 */
6699 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6700 klass->parent = parent;
6701 klass->instance_size = mono_class_instance_size (klass->parent);
6703 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6704 /*Arrays of those two types are invalid.*/
6705 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6706 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6707 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6708 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6709 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6711 /* element_size -1 is ok as this is not an instantitable type*/
6712 klass->sizes.element_size = -1;
6714 klass->sizes.element_size = mono_class_array_element_size (eclass);
6716 mono_class_setup_supertypes (klass);
6718 if (eclass->generic_class)
6719 mono_class_init (eclass);
6720 if (!eclass->size_inited)
6721 mono_class_setup_fields (eclass);
6722 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6723 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6725 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6729 if (eclass->enumtype)
6730 klass->cast_class = eclass->element_class;
6732 klass->cast_class = eclass;
6734 switch (klass->cast_class->byval_arg.type) {
6736 klass->cast_class = mono_defaults.byte_class;
6739 klass->cast_class = mono_defaults.int16_class;
6742 #if SIZEOF_VOID_P == 4
6746 klass->cast_class = mono_defaults.int32_class;
6749 #if SIZEOF_VOID_P == 8
6753 klass->cast_class = mono_defaults.int64_class;
6759 klass->element_class = eclass;
6761 if ((rank > 1) || bounded) {
6762 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6763 klass->byval_arg.type = MONO_TYPE_ARRAY;
6764 klass->byval_arg.data.array = at;
6765 at->eklass = eclass;
6767 /* FIXME: complete.... */
6769 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6770 klass->byval_arg.data.klass = eclass;
6772 klass->this_arg = klass->byval_arg;
6773 klass->this_arg.byref = 1;
6778 klass->generic_container = eclass->generic_container;
6780 if (rank == 1 && !bounded) {
6781 MonoClass *prev_class;
6783 mono_os_mutex_lock (&image->szarray_cache_lock);
6784 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6786 /* Someone got in before us */
6789 g_hash_table_insert (image->szarray_cache, eclass, klass);
6790 mono_os_mutex_unlock (&image->szarray_cache_lock);
6792 list = g_slist_append (rootlist, klass);
6793 g_hash_table_insert (image->array_cache, eclass, list);
6796 mono_loader_unlock ();
6798 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6804 * mono_array_class_get:
6805 * @element_class: element class
6806 * @rank: the dimension of the array class
6808 * Returns: a class object describing the array with element type @element_type and
6812 mono_array_class_get (MonoClass *eclass, guint32 rank)
6814 return mono_bounded_array_class_get (eclass, rank, FALSE);
6818 * mono_class_instance_size:
6821 * Returns: the size of an object instance
6824 mono_class_instance_size (MonoClass *klass)
6826 if (!klass->size_inited)
6827 mono_class_init (klass);
6829 return klass->instance_size;
6833 * mono_class_min_align:
6836 * Returns: minimm alignment requirements
6839 mono_class_min_align (MonoClass *klass)
6841 if (!klass->size_inited)
6842 mono_class_init (klass);
6844 return klass->min_align;
6848 * mono_class_value_size:
6851 * This function is used for value types, and return the
6852 * space and the alignment to store that kind of value object.
6854 * Returns: the size of a value of kind @klass
6857 mono_class_value_size (MonoClass *klass, guint32 *align)
6861 /* fixme: check disable, because we still have external revereces to
6862 * mscorlib and Dummy Objects
6864 /*g_assert (klass->valuetype);*/
6866 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6869 *align = klass->min_align;
6875 * mono_class_data_size:
6878 * Returns: the size of the static class data
6881 mono_class_data_size (MonoClass *klass)
6884 mono_class_init (klass);
6885 /* This can happen with dynamically created types */
6886 if (!klass->fields_inited)
6887 mono_class_setup_fields_locking (klass);
6889 /* in arrays, sizes.class_size is unioned with element_size
6890 * and arrays have no static fields
6894 return klass->sizes.class_size;
6898 * Auxiliary routine to mono_class_get_field
6900 * Takes a field index instead of a field token.
6902 static MonoClassField *
6903 mono_class_get_field_idx (MonoClass *klass, int idx)
6905 mono_class_setup_fields_locking (klass);
6906 if (klass->exception_type)
6910 if (klass->image->uncompressed_metadata) {
6912 * klass->field.first points to the FieldPtr table, while idx points into the
6913 * Field table, so we have to do a search.
6915 /*FIXME this is broken for types with multiple fields with the same name.*/
6916 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6919 for (i = 0; i < klass->field.count; ++i)
6920 if (mono_field_get_name (&klass->fields [i]) == name)
6921 return &klass->fields [i];
6922 g_assert_not_reached ();
6924 if (klass->field.count) {
6925 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6926 return &klass->fields [idx - klass->field.first];
6930 klass = klass->parent;
6936 * mono_class_get_field:
6937 * @class: the class to lookup the field.
6938 * @field_token: the field token
6940 * Returns: A MonoClassField representing the type and offset of
6941 * the field, or a NULL value if the field does not belong to this
6945 mono_class_get_field (MonoClass *klass, guint32 field_token)
6947 int idx = mono_metadata_token_index (field_token);
6949 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6951 return mono_class_get_field_idx (klass, idx - 1);
6955 * mono_class_get_field_from_name:
6956 * @klass: the class to lookup the field.
6957 * @name: the field name
6959 * Search the class @klass and it's parents for a field with the name @name.
6961 * Returns: the MonoClassField pointer of the named field or NULL
6964 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6966 return mono_class_get_field_from_name_full (klass, name, NULL);
6970 * mono_class_get_field_from_name_full:
6971 * @klass: the class to lookup the field.
6972 * @name: the field name
6973 * @type: the type of the fields. This optional.
6975 * Search the class @klass and it's parents for a field with the name @name and type @type.
6977 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6978 * of its generic type definition.
6980 * Returns: the MonoClassField pointer of the named field or NULL
6983 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6987 mono_class_setup_fields_locking (klass);
6988 if (klass->exception_type)
6992 for (i = 0; i < klass->field.count; ++i) {
6993 MonoClassField *field = &klass->fields [i];
6995 if (strcmp (name, mono_field_get_name (field)) != 0)
6999 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7000 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7005 klass = klass->parent;
7011 * mono_class_get_field_token:
7012 * @field: the field we need the token of
7014 * Get the token of a field. Note that the tokesn is only valid for the image
7015 * the field was loaded from. Don't use this function for fields in dynamic types.
7017 * Returns: the token representing the field in the image it was loaded from.
7020 mono_class_get_field_token (MonoClassField *field)
7022 MonoClass *klass = field->parent;
7025 mono_class_setup_fields_locking (klass);
7030 for (i = 0; i < klass->field.count; ++i) {
7031 if (&klass->fields [i] == field) {
7032 int idx = klass->field.first + i + 1;
7034 if (klass->image->uncompressed_metadata)
7035 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7036 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7039 klass = klass->parent;
7042 g_assert_not_reached ();
7047 mono_field_get_index (MonoClassField *field)
7049 int index = field - field->parent->fields;
7051 g_assert (index >= 0 && index < field->parent->field.count);
7057 * mono_class_get_field_default_value:
7059 * Return the default value of the field as a pointer into the metadata blob.
7062 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7065 guint32 constant_cols [MONO_CONSTANT_SIZE];
7067 MonoClass *klass = field->parent;
7069 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7071 if (!klass->ext || !klass->ext->field_def_values) {
7072 MonoFieldDefaultValue *def_values;
7074 mono_class_alloc_ext (klass);
7076 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7078 mono_image_lock (klass->image);
7079 mono_memory_barrier ();
7080 if (!klass->ext->field_def_values)
7081 klass->ext->field_def_values = def_values;
7082 mono_image_unlock (klass->image);
7085 field_index = mono_field_get_index (field);
7087 if (!klass->ext->field_def_values [field_index].data) {
7088 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7092 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7094 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7095 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7096 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7099 *def_type = klass->ext->field_def_values [field_index].def_type;
7100 return klass->ext->field_def_values [field_index].data;
7104 mono_property_get_index (MonoProperty *prop)
7106 int index = prop - prop->parent->ext->properties;
7108 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7114 * mono_class_get_property_default_value:
7116 * Return the default value of the field as a pointer into the metadata blob.
7119 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7122 guint32 constant_cols [MONO_CONSTANT_SIZE];
7123 MonoClass *klass = property->parent;
7125 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7127 * We don't cache here because it is not used by C# so it's quite rare, but
7128 * we still do the lookup in klass->ext because that is where the data
7129 * is stored for dynamic assemblies.
7132 if (image_is_dynamic (klass->image)) {
7133 int prop_index = mono_property_get_index (property);
7134 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7135 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7136 return klass->ext->prop_def_values [prop_index].data;
7140 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7144 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7145 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7146 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7150 mono_class_get_event_token (MonoEvent *event)
7152 MonoClass *klass = event->parent;
7157 for (i = 0; i < klass->ext->event.count; ++i) {
7158 if (&klass->ext->events [i] == event)
7159 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7162 klass = klass->parent;
7165 g_assert_not_reached ();
7170 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7174 gpointer iter = NULL;
7175 while ((p = mono_class_get_properties (klass, &iter))) {
7176 if (! strcmp (name, p->name))
7179 klass = klass->parent;
7185 mono_class_get_property_token (MonoProperty *prop)
7187 MonoClass *klass = prop->parent;
7191 gpointer iter = NULL;
7192 while ((p = mono_class_get_properties (klass, &iter))) {
7193 if (&klass->ext->properties [i] == prop)
7194 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7198 klass = klass->parent;
7201 g_assert_not_reached ();
7206 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7208 const char *name, *nspace;
7209 if (image_is_dynamic (image))
7210 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7212 switch (type_token & 0xff000000){
7213 case MONO_TOKEN_TYPE_DEF: {
7214 guint32 cols [MONO_TYPEDEF_SIZE];
7215 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7216 guint tidx = mono_metadata_token_index (type_token);
7218 if (tidx > tt->rows)
7219 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7221 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7222 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7223 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7224 if (strlen (nspace) == 0)
7225 return g_strdup_printf ("%s", name);
7227 return g_strdup_printf ("%s.%s", nspace, name);
7230 case MONO_TOKEN_TYPE_REF: {
7232 guint32 cols [MONO_TYPEREF_SIZE];
7233 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7234 guint tidx = mono_metadata_token_index (type_token);
7237 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7239 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7240 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7241 mono_error_cleanup (&error);
7245 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7246 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7247 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7248 if (strlen (nspace) == 0)
7249 return g_strdup_printf ("%s", name);
7251 return g_strdup_printf ("%s.%s", nspace, name);
7254 case MONO_TOKEN_TYPE_SPEC:
7255 return g_strdup_printf ("Typespec 0x%08x", type_token);
7257 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7262 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7264 if (image_is_dynamic (image))
7265 return g_strdup_printf ("DynamicAssembly %s", image->name);
7267 switch (type_token & 0xff000000){
7268 case MONO_TOKEN_TYPE_DEF:
7269 if (image->assembly)
7270 return mono_stringify_assembly_name (&image->assembly->aname);
7271 else if (image->assembly_name)
7272 return g_strdup (image->assembly_name);
7273 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7274 case MONO_TOKEN_TYPE_REF: {
7276 MonoAssemblyName aname;
7277 guint32 cols [MONO_TYPEREF_SIZE];
7278 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7279 guint32 idx = mono_metadata_token_index (type_token);
7282 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7284 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7285 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7286 mono_error_cleanup (&error);
7289 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7291 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7292 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7293 case MONO_RESOLUTION_SCOPE_MODULE:
7295 return g_strdup ("");
7296 case MONO_RESOLUTION_SCOPE_MODULEREF:
7298 return g_strdup ("");
7299 case MONO_RESOLUTION_SCOPE_TYPEREF:
7301 return g_strdup ("");
7302 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7303 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7304 return mono_stringify_assembly_name (&aname);
7306 g_assert_not_reached ();
7310 case MONO_TOKEN_TYPE_SPEC:
7312 return g_strdup ("");
7314 g_assert_not_reached ();
7321 * mono_class_get_full:
7322 * @image: the image where the class resides
7323 * @type_token: the token for the class
7324 * @context: the generic context used to evaluate generic instantiations in
7325 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7327 * Returns: the MonoClass that represents @type_token in @image
7330 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7334 klass = mono_class_get_checked (image, type_token, &error);
7336 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7337 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7339 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7345 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7349 mono_error_init (error);
7350 klass = mono_class_get_checked (image, type_token, error);
7352 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7353 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7358 * mono_class_get_checked:
7359 * @image: the image where the class resides
7360 * @type_token: the token for the class
7361 * @error: error object to return any error
7363 * Returns: the MonoClass that represents @type_token in @image
7366 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7368 MonoClass *klass = NULL;
7370 mono_error_init (error);
7372 if (image_is_dynamic (image)) {
7373 int table = mono_metadata_token_table (type_token);
7375 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7376 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7379 klass = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7383 switch (type_token & 0xff000000){
7384 case MONO_TOKEN_TYPE_DEF:
7385 klass = mono_class_create_from_typedef (image, type_token, error);
7387 case MONO_TOKEN_TYPE_REF:
7388 klass = mono_class_from_typeref_checked (image, type_token, error);
7390 case MONO_TOKEN_TYPE_SPEC:
7391 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7394 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7398 /* Generic case, should be avoided for when a better error is possible. */
7399 if (!klass && mono_error_ok (error)) {
7400 char *name = mono_class_name_from_token (image, type_token);
7401 char *assembly = mono_assembly_name_from_token (image, type_token);
7402 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7410 * mono_type_get_checked:
7411 * @image: the image where the type resides
7412 * @type_token: the token for the type
7413 * @context: the generic context used to evaluate generic instantiations in
7414 * @error: Error handling context
7416 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7418 * Returns: the MonoType that represents @type_token in @image
7421 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7423 MonoType *type = NULL;
7424 gboolean inflated = FALSE;
7426 mono_error_init (error);
7428 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7429 if (image_is_dynamic (image))
7430 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7432 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7433 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7436 mono_loader_assert_no_error ();
7441 return mono_class_get_type (klass);
7444 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7447 mono_loader_assert_no_error ();
7452 MonoType *tmp = type;
7453 type = mono_class_get_type (mono_class_from_mono_type (type));
7454 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7455 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7456 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7458 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7460 if (type->type != tmp->type)
7463 mono_metadata_free_type (tmp);
7470 mono_class_get (MonoImage *image, guint32 type_token)
7472 return mono_class_get_full (image, type_token, NULL);
7476 * mono_image_init_name_cache:
7478 * Initializes the class name cache stored in image->name_cache.
7480 * LOCKING: Acquires the corresponding image lock.
7483 mono_image_init_name_cache (MonoImage *image)
7485 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7486 guint32 cols [MONO_TYPEDEF_SIZE];
7489 guint32 i, visib, nspace_index;
7490 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7492 if (image->name_cache)
7495 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7497 if (image_is_dynamic (image)) {
7498 mono_image_lock (image);
7499 if (image->name_cache) {
7500 /* Somebody initialized it before us */
7501 g_hash_table_destroy (the_name_cache);
7503 mono_atomic_store_release (&image->name_cache, the_name_cache);
7505 mono_image_unlock (image);
7509 /* Temporary hash table to avoid lookups in the nspace_table */
7510 name_cache2 = g_hash_table_new (NULL, NULL);
7512 for (i = 1; i <= t->rows; ++i) {
7513 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7514 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7516 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7517 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7519 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7521 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7522 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7524 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7525 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7526 if (!nspace_table) {
7527 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7528 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7529 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7532 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7535 /* Load type names from EXPORTEDTYPES table */
7537 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7538 guint32 cols [MONO_EXP_TYPE_SIZE];
7541 for (i = 0; i < t->rows; ++i) {
7542 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7544 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7545 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7549 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7550 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7552 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7553 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7554 if (!nspace_table) {
7555 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7556 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7557 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7560 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7564 g_hash_table_destroy (name_cache2);
7566 mono_image_lock (image);
7567 if (image->name_cache) {
7568 /* Somebody initialized it before us */
7569 g_hash_table_destroy (the_name_cache);
7571 mono_atomic_store_release (&image->name_cache, the_name_cache);
7573 mono_image_unlock (image);
7576 /*FIXME Only dynamic assemblies should allow this operation.*/
7578 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7579 const char *name, guint32 index)
7581 GHashTable *nspace_table;
7582 GHashTable *name_cache;
7585 mono_image_init_name_cache (image);
7586 mono_image_lock (image);
7588 name_cache = image->name_cache;
7589 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7590 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7591 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7594 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7595 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7597 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7599 mono_image_unlock (image);
7608 find_nocase (gpointer key, gpointer value, gpointer user_data)
7610 char *name = (char*)key;
7611 FindUserData *data = (FindUserData*)user_data;
7613 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7614 data->value = value;
7618 * mono_class_from_name_case:
7619 * @image: The MonoImage where the type is looked up in
7620 * @name_space: the type namespace
7621 * @name: the type short name.
7622 * @deprecated: use the _checked variant
7624 * Obtains a MonoClass with a given namespace and a given name which
7625 * is located in the given MonoImage. The namespace and name
7626 * lookups are case insensitive.
7629 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7632 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7633 g_assert (!mono_error_ok (&error));
7638 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7640 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7641 guint32 cols [MONO_TYPEDEF_SIZE];
7646 mono_error_init (error);
7648 if (image_is_dynamic (image)) {
7650 FindUserData user_data;
7652 mono_image_init_name_cache (image);
7653 mono_image_lock (image);
7655 user_data.key = name_space;
7656 user_data.value = NULL;
7657 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7659 if (user_data.value) {
7660 GHashTable *nspace_table = (GHashTable*)user_data.value;
7662 user_data.key = name;
7663 user_data.value = NULL;
7665 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7667 if (user_data.value)
7668 token = GPOINTER_TO_UINT (user_data.value);
7671 mono_image_unlock (image);
7674 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7680 /* add a cache if needed */
7681 for (i = 1; i <= t->rows; ++i) {
7682 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7683 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7685 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7686 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7688 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7690 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7691 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7692 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7693 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7699 return_nested_in (MonoClass *klass, char *nested)
7702 char *s = strchr (nested, '/');
7703 gpointer iter = NULL;
7710 while ((found = mono_class_get_nested_types (klass, &iter))) {
7711 if (strcmp (found->name, nested) == 0) {
7713 return return_nested_in (found, s);
7721 search_modules (MonoImage *image, const char *name_space, const char *name)
7723 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7724 MonoImage *file_image;
7729 * The EXPORTEDTYPES table only contains public types, so have to search the
7731 * Note: image->modules contains the contents of the MODULEREF table, while
7732 * the real module list is in the FILE table.
7734 for (i = 0; i < file_table->rows; i++) {
7735 guint32 cols [MONO_FILE_SIZE];
7736 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7737 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7740 file_image = mono_image_load_file_for_image (image, i + 1);
7742 klass = mono_class_from_name (file_image, name_space, name);
7752 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7754 GHashTable *nspace_table;
7755 MonoImage *loaded_image;
7762 mono_error_init (error);
7764 // Checking visited images avoids stack overflows when cyclic references exist.
7765 if (g_hash_table_lookup (visited_images, image))
7768 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7770 if ((nested = strchr (name, '/'))) {
7771 int pos = nested - name;
7772 int len = strlen (name);
7775 memcpy (buf, name, len + 1);
7777 nested = buf + pos + 1;
7781 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7782 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7783 gboolean res = get_class_from_name (image, name_space, name, &klass);
7786 klass = search_modules (image, name_space, name);
7788 return klass ? return_nested_in (klass, nested) : NULL;
7794 mono_image_init_name_cache (image);
7795 mono_image_lock (image);
7797 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7800 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7802 mono_image_unlock (image);
7804 if (!token && image_is_dynamic (image) && image->modules) {
7805 /* Search modules as well */
7806 for (i = 0; i < image->module_count; ++i) {
7807 MonoImage *module = image->modules [i];
7809 klass = mono_class_from_name (module, name_space, name);
7816 klass = search_modules (image, name_space, name);
7824 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7825 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7826 guint32 cols [MONO_EXP_TYPE_SIZE];
7829 idx = mono_metadata_token_index (token);
7831 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7833 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7834 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7835 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7838 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7840 return klass ? return_nested_in (klass, nested) : NULL;
7842 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7843 guint32 assembly_idx;
7845 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7847 mono_assembly_load_reference (image, assembly_idx - 1);
7848 g_assert (image->references [assembly_idx - 1]);
7849 if (image->references [assembly_idx - 1] == (gpointer)-1)
7851 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7853 return return_nested_in (klass, nested);
7856 g_assert_not_reached ();
7860 token = MONO_TOKEN_TYPE_DEF | token;
7862 klass = mono_class_get_checked (image, token, error);
7864 return return_nested_in (klass, nested);
7869 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7872 GHashTable *visited_images;
7874 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7876 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
7878 g_hash_table_destroy (visited_images);
7884 * mono_class_from_name:
7885 * @image: The MonoImage where the type is looked up in
7886 * @name_space: the type namespace
7887 * @name: the type short name.
7889 * Obtains a MonoClass with a given namespace and a given name which
7890 * is located in the given MonoImage.
7892 * To reference nested classes, use the "/" character as a separator.
7893 * For example use "Foo/Bar" to reference the class Bar that is nested
7894 * inside Foo, like this: "class Foo { class Bar {} }".
7897 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7902 klass = mono_class_from_name_checked (image, name_space, name, &error);
7903 if (!mono_error_ok (&error)) {
7904 mono_loader_set_error_from_mono_error (&error);
7905 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7911 * mono_class_is_subclass_of:
7912 * @klass: class to probe if it is a subclass of another one
7913 * @klassc: the class we suspect is the base class
7914 * @check_interfaces: whether we should perform interface checks
7916 * This method determines whether @klass is a subclass of @klassc.
7918 * If the @check_interfaces flag is set, then if @klassc is an interface
7919 * this method return true if the @klass implements the interface or
7920 * if @klass is an interface, if one of its base classes is @klass.
7922 * If @check_interfaces is false then, then if @klass is not an interface
7923 * then it returns true if the @klass is a subclass of @klassc.
7925 * if @klass is an interface and @klassc is System.Object, then this function
7930 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7931 gboolean check_interfaces)
7933 /*FIXME test for interfaces with variant generic arguments*/
7935 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7936 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7938 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7941 for (i = 0; i < klass->interface_count; i ++) {
7942 MonoClass *ic = klass->interfaces [i];
7947 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7952 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7955 if (klassc == mono_defaults.object_class)
7962 mono_type_is_generic_argument (MonoType *type)
7964 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7968 mono_class_has_variant_generic_params (MonoClass *klass)
7971 MonoGenericContainer *container;
7973 if (!klass->generic_class)
7976 container = klass->generic_class->container_class->generic_container;
7978 for (i = 0; i < container->type_argc; ++i)
7979 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7986 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7988 if (target == candidate)
7991 if (check_for_reference_conv &&
7992 mono_type_is_generic_argument (&target->byval_arg) &&
7993 mono_type_is_generic_argument (&candidate->byval_arg)) {
7994 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7995 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7997 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8000 if (!mono_class_is_assignable_from (target, candidate))
8006 * @container the generic container from the GTD
8007 * @klass: the class to be assigned to
8008 * @oklass: the source class
8010 * Both klass and oklass must be instances of the same generic interface.
8011 * Return true if @klass can be assigned to a @klass variable
8014 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8017 MonoType **klass_argv, **oklass_argv;
8018 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8019 MonoGenericContainer *container = klass_gtd->generic_container;
8021 if (klass == oklass)
8024 /*Viable candidates are instances of the same generic interface*/
8025 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8028 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8029 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8031 for (j = 0; j < container->type_argc; ++j) {
8032 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8033 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8035 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8039 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8040 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8042 if (param1_class != param2_class) {
8043 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8044 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8046 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8047 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8057 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8059 MonoGenericParam *gparam, *ogparam;
8060 MonoGenericParamInfo *tinfo, *cinfo;
8061 MonoClass **candidate_class;
8062 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8065 if (target == candidate)
8067 if (target->byval_arg.type != candidate->byval_arg.type)
8070 gparam = target->byval_arg.data.generic_param;
8071 ogparam = candidate->byval_arg.data.generic_param;
8072 tinfo = mono_generic_param_info (gparam);
8073 cinfo = mono_generic_param_info (ogparam);
8075 class_constraint_satisfied = FALSE;
8076 valuetype_constraint_satisfied = FALSE;
8078 /*candidate must have a super set of target's special constraints*/
8079 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8080 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8082 if (cinfo->constraints) {
8083 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8084 MonoClass *cc = *candidate_class;
8086 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8087 class_constraint_satisfied = TRUE;
8088 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8089 valuetype_constraint_satisfied = TRUE;
8092 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8093 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8095 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8097 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8099 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8100 valuetype_constraint_satisfied)) {
8105 /*candidate type constraints must be a superset of target's*/
8106 if (tinfo->constraints) {
8107 MonoClass **target_class;
8108 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8109 MonoClass *tc = *target_class;
8112 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8113 * check it's constraints since it satisfy the constraint by itself.
8115 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8118 if (!cinfo->constraints)
8121 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8122 MonoClass *cc = *candidate_class;
8124 if (mono_class_is_assignable_from (tc, cc))
8128 * This happens when we have the following:
8130 * Bar<K> where K : IFace
8131 * Foo<T, U> where T : U where U : IFace
8133 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8136 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8137 if (mono_gparam_is_assignable_from (target, cc))
8141 if (!*candidate_class)
8146 /*candidate itself must have a constraint that satisfy target*/
8147 if (cinfo->constraints) {
8148 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8149 MonoClass *cc = *candidate_class;
8150 if (mono_class_is_assignable_from (target, cc))
8158 * mono_class_is_assignable_from:
8159 * @klass: the class to be assigned to
8160 * @oklass: the source class
8162 * Return: true if an instance of object oklass can be assigned to an
8163 * instance of object @klass
8166 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8168 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8170 mono_class_init (klass);
8172 if (!oklass->inited)
8173 mono_class_init (oklass);
8175 if (klass->exception_type || oklass->exception_type)
8178 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8179 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8181 return mono_gparam_is_assignable_from (klass, oklass);
8184 if (MONO_CLASS_IS_INTERFACE (klass)) {
8185 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8186 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8187 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8191 for (i = 0; constraints [i]; ++i) {
8192 if (mono_class_is_assignable_from (klass, constraints [i]))
8200 /* interface_offsets might not be set for dynamic classes */
8201 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8203 * oklass might be a generic type parameter but they have
8204 * interface_offsets set.
8206 return mono_reflection_call_is_assignable_to (oklass, klass);
8207 if (!oklass->interface_bitmap)
8208 /* Happens with generic instances of not-yet created dynamic types */
8210 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8213 if (mono_class_has_variant_generic_params (klass)) {
8216 mono_class_setup_interfaces (oklass, &error);
8217 if (!mono_error_ok (&error)) {
8218 mono_error_cleanup (&error);
8222 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8223 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8224 MonoClass *iface = oklass->interfaces_packed [i];
8226 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8231 } else if (klass->delegate) {
8232 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8234 }else if (klass->rank) {
8235 MonoClass *eclass, *eoclass;
8237 if (oklass->rank != klass->rank)
8240 /* vectors vs. one dimensional arrays */
8241 if (oklass->byval_arg.type != klass->byval_arg.type)
8244 eclass = klass->cast_class;
8245 eoclass = oklass->cast_class;
8248 * a is b does not imply a[] is b[] when a is a valuetype, and
8249 * b is a reference type.
8252 if (eoclass->valuetype) {
8253 if ((eclass == mono_defaults.enum_class) ||
8254 (eclass == mono_defaults.enum_class->parent) ||
8255 (eclass == mono_defaults.object_class))
8259 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8260 } else if (mono_class_is_nullable (klass)) {
8261 if (mono_class_is_nullable (oklass))
8262 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8264 return mono_class_is_assignable_from (klass->cast_class, oklass);
8265 } else if (klass == mono_defaults.object_class)
8268 return mono_class_has_parent (oklass, klass);
8271 /*Check if @oklass is variant compatible with @klass.*/
8273 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8276 MonoType **klass_argv, **oklass_argv;
8277 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8278 MonoGenericContainer *container = klass_gtd->generic_container;
8280 /*Viable candidates are instances of the same generic interface*/
8281 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8284 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8285 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8287 for (j = 0; j < container->type_argc; ++j) {
8288 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8289 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8291 if (param1_class->valuetype != param2_class->valuetype)
8295 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8296 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8298 if (param1_class != param2_class) {
8299 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8300 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8302 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8303 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8311 /*Check if @candidate implements the interface @target*/
8313 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8317 gboolean is_variant = mono_class_has_variant_generic_params (target);
8319 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8320 if (mono_class_is_variant_compatible_slow (target, candidate))
8325 if (candidate == target)
8328 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8329 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8330 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8332 if (tb && tb->interfaces) {
8333 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8334 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8335 MonoClass *iface_class;
8337 /* we can't realize the type here since it can do pretty much anything. */
8340 iface_class = mono_class_from_mono_type (iface->type);
8341 if (iface_class == target)
8343 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8345 if (mono_class_implement_interface_slow (target, iface_class))
8350 /*setup_interfaces don't mono_class_init anything*/
8351 /*FIXME this doesn't handle primitive type arrays.
8352 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8353 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8355 mono_class_setup_interfaces (candidate, &error);
8356 if (!mono_error_ok (&error)) {
8357 mono_error_cleanup (&error);
8361 for (i = 0; i < candidate->interface_count; ++i) {
8362 if (candidate->interfaces [i] == target)
8365 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8368 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8372 candidate = candidate->parent;
8373 } while (candidate);
8379 * Check if @oklass can be assigned to @klass.
8380 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8383 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8385 if (candidate == target)
8387 if (target == mono_defaults.object_class)
8390 if (mono_class_has_parent (candidate, target))
8393 /*If target is not an interface there is no need to check them.*/
8394 if (MONO_CLASS_IS_INTERFACE (target))
8395 return mono_class_implement_interface_slow (target, candidate);
8397 if (target->delegate && mono_class_has_variant_generic_params (target))
8398 return mono_class_is_variant_compatible (target, candidate, FALSE);
8401 MonoClass *eclass, *eoclass;
8403 if (target->rank != candidate->rank)
8406 /* vectors vs. one dimensional arrays */
8407 if (target->byval_arg.type != candidate->byval_arg.type)
8410 eclass = target->cast_class;
8411 eoclass = candidate->cast_class;
8414 * a is b does not imply a[] is b[] when a is a valuetype, and
8415 * b is a reference type.
8418 if (eoclass->valuetype) {
8419 if ((eclass == mono_defaults.enum_class) ||
8420 (eclass == mono_defaults.enum_class->parent) ||
8421 (eclass == mono_defaults.object_class))
8425 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8427 /*FIXME properly handle nullables */
8428 /*FIXME properly handle (M)VAR */
8433 * mono_class_get_cctor:
8434 * @klass: A MonoClass pointer
8436 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8439 mono_class_get_cctor (MonoClass *klass)
8441 MonoCachedClassInfo cached_info;
8443 if (image_is_dynamic (klass->image)) {
8445 * has_cctor is not set for these classes because mono_class_init () is
8448 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8451 if (!klass->has_cctor)
8454 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8456 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8457 if (!mono_error_ok (&error))
8458 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8462 if (klass->generic_class && !klass->methods)
8463 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8465 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8469 * mono_class_get_finalizer:
8470 * @klass: The MonoClass pointer
8472 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8475 mono_class_get_finalizer (MonoClass *klass)
8477 MonoCachedClassInfo cached_info;
8480 mono_class_init (klass);
8481 if (!mono_class_has_finalizer (klass))
8484 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8486 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8487 if (!mono_error_ok (&error))
8488 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8491 mono_class_setup_vtable (klass);
8492 return klass->vtable [finalize_slot];
8497 * mono_class_needs_cctor_run:
8498 * @klass: the MonoClass pointer
8499 * @caller: a MonoMethod describing the caller
8501 * Determines whenever the class has a static constructor and whenever it
8502 * needs to be called when executing CALLER.
8505 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8509 method = mono_class_get_cctor (klass);
8511 return (method == caller) ? FALSE : TRUE;
8517 * mono_class_array_element_size:
8520 * Returns: the number of bytes an element of type @klass
8521 * uses when stored into an array.
8524 mono_class_array_element_size (MonoClass *klass)
8526 MonoType *type = &klass->byval_arg;
8529 switch (type->type) {
8532 case MONO_TYPE_BOOLEAN:
8536 case MONO_TYPE_CHAR:
8545 case MONO_TYPE_CLASS:
8546 case MONO_TYPE_STRING:
8547 case MONO_TYPE_OBJECT:
8548 case MONO_TYPE_SZARRAY:
8549 case MONO_TYPE_ARRAY:
8550 return sizeof (gpointer);
8555 case MONO_TYPE_VALUETYPE:
8556 if (type->data.klass->enumtype) {
8557 type = mono_class_enum_basetype (type->data.klass);
8558 klass = klass->element_class;
8561 return mono_class_instance_size (klass) - sizeof (MonoObject);
8562 case MONO_TYPE_GENERICINST:
8563 type = &type->data.generic_class->container_class->byval_arg;
8566 case MONO_TYPE_MVAR: {
8569 return mono_type_size (type, &align);
8571 case MONO_TYPE_VOID:
8575 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8581 * mono_array_element_size:
8582 * @ac: pointer to a #MonoArrayClass
8584 * Returns: the size of single array element.
8587 mono_array_element_size (MonoClass *ac)
8589 g_assert (ac->rank);
8590 return ac->sizes.element_size;
8594 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8595 MonoGenericContext *context)
8598 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8599 g_assert (mono_error_ok (&error));
8604 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8605 MonoGenericContext *context, MonoError *error)
8607 mono_error_init (error);
8609 if (image_is_dynamic (image)) {
8610 MonoClass *tmp_handle_class;
8611 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8613 g_assert (tmp_handle_class);
8615 *handle_class = tmp_handle_class;
8617 if (tmp_handle_class == mono_defaults.typehandle_class)
8618 return &((MonoClass*)obj)->byval_arg;
8623 switch (token & 0xff000000) {
8624 case MONO_TOKEN_TYPE_DEF:
8625 case MONO_TOKEN_TYPE_REF:
8626 case MONO_TOKEN_TYPE_SPEC: {
8629 *handle_class = mono_defaults.typehandle_class;
8630 type = mono_type_get_checked (image, token, context, error);
8634 mono_class_init (mono_class_from_mono_type (type));
8635 /* We return a MonoType* as handle */
8638 case MONO_TOKEN_FIELD_DEF: {
8640 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8642 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8646 *handle_class = mono_defaults.fieldhandle_class;
8647 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8651 mono_class_init (klass);
8652 return mono_class_get_field (klass, token);
8654 case MONO_TOKEN_METHOD_DEF:
8655 case MONO_TOKEN_METHOD_SPEC: {
8657 meth = mono_get_method_checked (image, token, NULL, context, error);
8659 *handle_class = mono_defaults.methodhandle_class;
8665 case MONO_TOKEN_MEMBER_REF: {
8666 guint32 cols [MONO_MEMBERREF_SIZE];
8668 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8669 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8670 mono_metadata_decode_blob_size (sig, &sig);
8671 if (*sig == 0x6) { /* it's a field */
8673 MonoClassField *field;
8674 field = mono_field_from_token_checked (image, token, &klass, context, error);
8676 *handle_class = mono_defaults.fieldhandle_class;
8680 meth = mono_get_method_checked (image, token, NULL, context, error);
8682 *handle_class = mono_defaults.methodhandle_class;
8687 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8693 * This function might need to call runtime functions so it can't be part
8694 * of the metadata library.
8696 static MonoLookupDynamicToken lookup_dynamic = NULL;
8699 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8701 lookup_dynamic = func;
8705 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8707 MonoClass *handle_class;
8709 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8713 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8715 return lookup_dynamic (image, token, valid_token, handle_class, context);
8718 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8721 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8723 get_cached_class_info = func;
8727 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8729 if (!get_cached_class_info)
8732 return get_cached_class_info (klass, res);
8736 mono_install_get_class_from_name (MonoGetClassFromName func)
8738 get_class_from_name = func;
8742 mono_class_get_image (MonoClass *klass)
8744 return klass->image;
8748 * mono_class_get_element_class:
8749 * @klass: the MonoClass to act on
8751 * Returns: the element class of an array or an enumeration.
8754 mono_class_get_element_class (MonoClass *klass)
8756 return klass->element_class;
8760 * mono_class_is_valuetype:
8761 * @klass: the MonoClass to act on
8763 * Returns: true if the MonoClass represents a ValueType.
8766 mono_class_is_valuetype (MonoClass *klass)
8768 return klass->valuetype;
8772 * mono_class_is_enum:
8773 * @klass: the MonoClass to act on
8775 * Returns: true if the MonoClass represents an enumeration.
8778 mono_class_is_enum (MonoClass *klass)
8780 return klass->enumtype;
8784 * mono_class_enum_basetype:
8785 * @klass: the MonoClass to act on
8787 * Returns: the underlying type representation for an enumeration.
8790 mono_class_enum_basetype (MonoClass *klass)
8792 if (klass->element_class == klass)
8793 /* SRE or broken types */
8796 return &klass->element_class->byval_arg;
8800 * mono_class_get_parent
8801 * @klass: the MonoClass to act on
8803 * Returns: the parent class for this class.
8806 mono_class_get_parent (MonoClass *klass)
8808 return klass->parent;
8812 * mono_class_get_nesting_type;
8813 * @klass: the MonoClass to act on
8815 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8818 mono_class_get_nesting_type (MonoClass *klass)
8820 return klass->nested_in;
8824 * mono_class_get_rank:
8825 * @klass: the MonoClass to act on
8827 * Returns: the rank for the array (the number of dimensions).
8830 mono_class_get_rank (MonoClass *klass)
8836 * mono_class_get_flags:
8837 * @klass: the MonoClass to act on
8839 * The type flags from the TypeDef table from the metadata.
8840 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8843 * Returns: the flags from the TypeDef table.
8846 mono_class_get_flags (MonoClass *klass)
8848 return klass->flags;
8852 * mono_class_get_name
8853 * @klass: the MonoClass to act on
8855 * Returns: the name of the class.
8858 mono_class_get_name (MonoClass *klass)
8864 * mono_class_get_namespace:
8865 * @klass: the MonoClass to act on
8867 * Returns: the namespace of the class.
8870 mono_class_get_namespace (MonoClass *klass)
8872 return klass->name_space;
8876 * mono_class_get_type:
8877 * @klass: the MonoClass to act on
8879 * This method returns the internal Type representation for the class.
8881 * Returns: the MonoType from the class.
8884 mono_class_get_type (MonoClass *klass)
8886 return &klass->byval_arg;
8890 * mono_class_get_type_token
8891 * @klass: the MonoClass to act on
8893 * This method returns type token for the class.
8895 * Returns: the type token for the class.
8898 mono_class_get_type_token (MonoClass *klass)
8900 return klass->type_token;
8904 * mono_class_get_byref_type:
8905 * @klass: the MonoClass to act on
8910 mono_class_get_byref_type (MonoClass *klass)
8912 return &klass->this_arg;
8916 * mono_class_num_fields:
8917 * @klass: the MonoClass to act on
8919 * Returns: the number of static and instance fields in the class.
8922 mono_class_num_fields (MonoClass *klass)
8924 return klass->field.count;
8928 * mono_class_num_methods:
8929 * @klass: the MonoClass to act on
8931 * Returns: the number of methods in the class.
8934 mono_class_num_methods (MonoClass *klass)
8936 return klass->method.count;
8940 * mono_class_num_properties
8941 * @klass: the MonoClass to act on
8943 * Returns: the number of properties in the class.
8946 mono_class_num_properties (MonoClass *klass)
8948 mono_class_setup_properties (klass);
8950 return klass->ext->property.count;
8954 * mono_class_num_events:
8955 * @klass: the MonoClass to act on
8957 * Returns: the number of events in the class.
8960 mono_class_num_events (MonoClass *klass)
8962 mono_class_setup_events (klass);
8964 return klass->ext->event.count;
8968 * mono_class_get_fields:
8969 * @klass: the MonoClass to act on
8971 * This routine is an iterator routine for retrieving the fields in a class.
8973 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8974 * iterate over all of the elements. When no more values are
8975 * available, the return value is NULL.
8977 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8980 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8982 MonoClassField* field;
8986 mono_class_setup_fields_locking (klass);
8987 if (klass->exception_type)
8989 /* start from the first */
8990 if (klass->field.count) {
8991 return *iter = &klass->fields [0];
8999 if (field < &klass->fields [klass->field.count]) {
9000 return *iter = field;
9006 * mono_class_get_methods
9007 * @klass: the MonoClass to act on
9009 * This routine is an iterator routine for retrieving the fields in a class.
9011 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9012 * iterate over all of the elements. When no more values are
9013 * available, the return value is NULL.
9015 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9018 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9020 MonoMethod** method;
9024 mono_class_setup_methods (klass);
9027 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9028 * FIXME we should better report this error to the caller
9030 if (!klass->methods)
9032 /* start from the first */
9033 if (klass->method.count) {
9034 *iter = &klass->methods [0];
9035 return klass->methods [0];
9043 if (method < &klass->methods [klass->method.count]) {
9051 * mono_class_get_virtual_methods:
9053 * Iterate over the virtual methods of KLASS.
9055 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9058 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9060 MonoMethod** method;
9063 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9065 mono_class_setup_methods (klass);
9067 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9068 * FIXME we should better report this error to the caller
9070 if (!klass->methods)
9072 /* start from the first */
9073 method = &klass->methods [0];
9078 while (method < &klass->methods [klass->method.count]) {
9079 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9083 if (method < &klass->methods [klass->method.count]) {
9090 /* Search directly in metadata to avoid calling setup_methods () */
9091 MonoMethod *res = NULL;
9097 start_index = GPOINTER_TO_UINT (*iter);
9100 for (i = start_index; i < klass->method.count; ++i) {
9103 /* klass->method.first points into the methodptr table */
9104 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9106 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9110 if (i < klass->method.count) {
9112 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9113 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9115 /* Add 1 here so the if (*iter) check fails */
9116 *iter = GUINT_TO_POINTER (i + 1);
9125 * mono_class_get_properties:
9126 * @klass: the MonoClass to act on
9128 * This routine is an iterator routine for retrieving the properties in a class.
9130 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9131 * iterate over all of the elements. When no more values are
9132 * available, the return value is NULL.
9134 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9137 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9139 MonoProperty* property;
9143 mono_class_setup_properties (klass);
9144 /* start from the first */
9145 if (klass->ext->property.count) {
9146 return *iter = &klass->ext->properties [0];
9154 if (property < &klass->ext->properties [klass->ext->property.count]) {
9155 return *iter = property;
9161 * mono_class_get_events:
9162 * @klass: the MonoClass to act on
9164 * This routine is an iterator routine for retrieving the properties in a class.
9166 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9167 * iterate over all of the elements. When no more values are
9168 * available, the return value is NULL.
9170 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9173 mono_class_get_events (MonoClass* klass, gpointer *iter)
9179 mono_class_setup_events (klass);
9180 /* start from the first */
9181 if (klass->ext->event.count) {
9182 return *iter = &klass->ext->events [0];
9190 if (event < &klass->ext->events [klass->ext->event.count]) {
9191 return *iter = event;
9197 * mono_class_get_interfaces
9198 * @klass: the MonoClass to act on
9200 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9202 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9203 * iterate over all of the elements. When no more values are
9204 * available, the return value is NULL.
9206 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9209 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9217 mono_class_init (klass);
9218 if (!klass->interfaces_inited) {
9219 mono_class_setup_interfaces (klass, &error);
9220 if (!mono_error_ok (&error)) {
9221 mono_error_cleanup (&error);
9225 /* start from the first */
9226 if (klass->interface_count) {
9227 *iter = &klass->interfaces [0];
9228 return klass->interfaces [0];
9236 if (iface < &klass->interfaces [klass->interface_count]) {
9244 setup_nested_types (MonoClass *klass)
9247 GList *classes, *nested_classes, *l;
9250 if (klass->nested_classes_inited)
9253 if (!klass->type_token)
9254 klass->nested_classes_inited = TRUE;
9256 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9260 guint32 cols [MONO_NESTED_CLASS_SIZE];
9261 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9262 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9263 if (!mono_error_ok (&error)) {
9264 /*FIXME don't swallow the error message*/
9265 mono_error_cleanup (&error);
9267 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9271 classes = g_list_prepend (classes, nclass);
9273 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9276 mono_class_alloc_ext (klass);
9278 nested_classes = NULL;
9279 for (l = classes; l; l = l->next)
9280 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9281 g_list_free (classes);
9283 mono_image_lock (klass->image);
9285 mono_memory_barrier ();
9286 if (!klass->nested_classes_inited) {
9287 klass->ext->nested_classes = nested_classes;
9288 mono_memory_barrier ();
9289 klass->nested_classes_inited = TRUE;
9292 mono_image_unlock (klass->image);
9296 * mono_class_get_nested_types
9297 * @klass: the MonoClass to act on
9299 * This routine is an iterator routine for retrieving the nested types of a class.
9300 * This works only if @klass is non-generic, or a generic type definition.
9302 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9303 * iterate over all of the elements. When no more values are
9304 * available, the return value is NULL.
9306 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9309 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9315 if (!klass->nested_classes_inited)
9316 setup_nested_types (klass);
9319 /* start from the first */
9320 if (klass->ext && klass->ext->nested_classes) {
9321 *iter = klass->ext->nested_classes;
9322 return klass->ext->nested_classes->data;
9324 /* no nested types */
9339 * mono_class_is_delegate
9340 * @klass: the MonoClass to act on
9342 * Returns: true if the MonoClass represents a System.Delegate.
9345 mono_class_is_delegate (MonoClass *klass)
9347 return klass->delegate;
9351 * mono_class_implements_interface
9352 * @klass: The MonoClass to act on
9353 * @interface: The interface to check if @klass implements.
9355 * Returns: true if @klass implements @interface.
9358 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9360 return mono_class_is_assignable_from (iface, klass);
9364 * mono_field_get_name:
9365 * @field: the MonoClassField to act on
9367 * Returns: the name of the field.
9370 mono_field_get_name (MonoClassField *field)
9376 * mono_field_get_type:
9377 * @field: the MonoClassField to act on
9379 * Returns: MonoType of the field.
9382 mono_field_get_type (MonoClassField *field)
9385 MonoType *type = mono_field_get_type_checked (field, &error);
9386 if (!mono_error_ok (&error)) {
9387 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9388 mono_error_cleanup (&error);
9395 * mono_field_get_type_checked:
9396 * @field: the MonoClassField to act on
9397 * @error: used to return any erro found while retrieving @field type
9399 * Returns: MonoType of the field.
9402 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9404 mono_error_init (error);
9406 mono_field_resolve_type (field, error);
9411 * mono_field_get_parent:
9412 * @field: the MonoClassField to act on
9414 * Returns: MonoClass where the field was defined.
9417 mono_field_get_parent (MonoClassField *field)
9419 return field->parent;
9423 * mono_field_get_flags;
9424 * @field: the MonoClassField to act on
9426 * The metadata flags for a field are encoded using the
9427 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9429 * Returns: the flags for the field.
9432 mono_field_get_flags (MonoClassField *field)
9435 return mono_field_resolve_flags (field);
9436 return field->type->attrs;
9440 * mono_field_get_offset;
9441 * @field: the MonoClassField to act on
9443 * Returns: the field offset.
9446 mono_field_get_offset (MonoClassField *field)
9448 return field->offset;
9452 mono_field_get_rva (MonoClassField *field)
9456 MonoClass *klass = field->parent;
9457 MonoFieldDefaultValue *field_def_values;
9459 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9461 if (!klass->ext || !klass->ext->field_def_values) {
9462 mono_class_alloc_ext (klass);
9464 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9466 mono_image_lock (klass->image);
9467 if (!klass->ext->field_def_values)
9468 klass->ext->field_def_values = field_def_values;
9469 mono_image_unlock (klass->image);
9472 field_index = mono_field_get_index (field);
9474 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9475 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9477 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9478 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9481 return klass->ext->field_def_values [field_index].data;
9485 * mono_field_get_data;
9486 * @field: the MonoClassField to act on
9488 * Returns: pointer to the metadata constant value or to the field
9489 * data if it has an RVA flag.
9492 mono_field_get_data (MonoClassField *field)
9494 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9495 MonoTypeEnum def_type;
9497 return mono_class_get_field_default_value (field, &def_type);
9498 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9499 return mono_field_get_rva (field);
9506 * mono_property_get_name:
9507 * @prop: the MonoProperty to act on
9509 * Returns: the name of the property
9512 mono_property_get_name (MonoProperty *prop)
9518 * mono_property_get_set_method
9519 * @prop: the MonoProperty to act on.
9521 * Returns: the setter method of the property (A MonoMethod)
9524 mono_property_get_set_method (MonoProperty *prop)
9530 * mono_property_get_get_method
9531 * @prop: the MonoProperty to act on.
9533 * Returns: the setter method of the property (A MonoMethod)
9536 mono_property_get_get_method (MonoProperty *prop)
9542 * mono_property_get_parent:
9543 * @prop: the MonoProperty to act on.
9545 * Returns: the MonoClass where the property was defined.
9548 mono_property_get_parent (MonoProperty *prop)
9550 return prop->parent;
9554 * mono_property_get_flags:
9555 * @prop: the MonoProperty to act on.
9557 * The metadata flags for a property are encoded using the
9558 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9560 * Returns: the flags for the property.
9563 mono_property_get_flags (MonoProperty *prop)
9569 * mono_event_get_name:
9570 * @event: the MonoEvent to act on
9572 * Returns: the name of the event.
9575 mono_event_get_name (MonoEvent *event)
9581 * mono_event_get_add_method:
9582 * @event: The MonoEvent to act on.
9584 * Returns: the @add' method for the event (a MonoMethod).
9587 mono_event_get_add_method (MonoEvent *event)
9593 * mono_event_get_remove_method:
9594 * @event: The MonoEvent to act on.
9596 * Returns: the @remove method for the event (a MonoMethod).
9599 mono_event_get_remove_method (MonoEvent *event)
9601 return event->remove;
9605 * mono_event_get_raise_method:
9606 * @event: The MonoEvent to act on.
9608 * Returns: the @raise method for the event (a MonoMethod).
9611 mono_event_get_raise_method (MonoEvent *event)
9613 return event->raise;
9617 * mono_event_get_parent:
9618 * @event: the MonoEvent to act on.
9620 * Returns: the MonoClass where the event is defined.
9623 mono_event_get_parent (MonoEvent *event)
9625 return event->parent;
9629 * mono_event_get_flags
9630 * @event: the MonoEvent to act on.
9632 * The metadata flags for an event are encoded using the
9633 * EVENT_* constants. See the tabledefs.h file for details.
9635 * Returns: the flags for the event.
9638 mono_event_get_flags (MonoEvent *event)
9640 return event->attrs;
9644 * mono_class_get_method_from_name:
9645 * @klass: where to look for the method
9646 * @name: name of the method
9647 * @param_count: number of parameters. -1 for any number.
9649 * Obtains a MonoMethod with a given name and number of parameters.
9650 * It only works if there are no multiple signatures for any given method name.
9653 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9655 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9659 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9661 MonoMethod *res = NULL;
9664 /* Search directly in the metadata to avoid calling setup_methods () */
9665 for (i = 0; i < klass->method.count; ++i) {
9667 guint32 cols [MONO_METHOD_SIZE];
9669 MonoMethodSignature *sig;
9671 /* klass->method.first points into the methodptr table */
9672 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9674 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9675 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9677 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9680 if (param_count == -1) {
9684 sig = mono_method_signature_checked (method, &error);
9686 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9689 if (sig->param_count == param_count) {
9700 * mono_class_get_method_from_name_flags:
9701 * @klass: where to look for the method
9702 * @name_space: name of the method
9703 * @param_count: number of parameters. -1 for any number.
9704 * @flags: flags which must be set in the method
9706 * Obtains a MonoMethod with a given name and number of parameters.
9707 * It only works if there are no multiple signatures for any given method name.
9710 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9712 MonoMethod *res = NULL;
9715 mono_class_init (klass);
9717 if (klass->generic_class && !klass->methods) {
9718 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9721 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9722 if (!mono_error_ok (&error))
9723 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9728 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9729 mono_class_setup_methods (klass);
9731 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9732 See mono/tests/array_load_exception.il
9733 FIXME we should better report this error to the caller
9735 if (!klass->methods)
9737 for (i = 0; i < klass->method.count; ++i) {
9738 MonoMethod *method = klass->methods [i];
9740 if (method->name[0] == name [0] &&
9741 !strcmp (name, method->name) &&
9742 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9743 ((method->flags & flags) == flags)) {
9750 res = find_method_in_metadata (klass, name, param_count, flags);
9757 * mono_class_set_failure:
9758 * @klass: class in which the failure was detected
9759 * @ex_type: the kind of exception/error to be thrown (later)
9760 * @ex_data: exception data (specific to each type of exception/error)
9762 * Keep a detected failure informations in the class for later processing.
9763 * Note that only the first failure is kept.
9765 * LOCKING: Acquires the loader lock.
9768 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9770 if (klass->exception_type)
9773 mono_loader_lock ();
9774 klass->exception_type = ex_type;
9776 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9777 mono_loader_unlock ();
9783 * mono_class_get_exception_data:
9785 * Return the exception_data property of KLASS.
9787 * LOCKING: Acquires the loader lock.
9790 mono_class_get_exception_data (MonoClass *klass)
9792 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9796 * mono_classes_init:
9798 * Initialize the resources used by this module.
9801 mono_classes_init (void)
9803 mono_os_mutex_init (&classes_mutex);
9805 mono_counters_register ("Inflated methods size",
9806 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9807 mono_counters_register ("Inflated classes",
9808 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9809 mono_counters_register ("Inflated classes size",
9810 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9811 mono_counters_register ("MonoClass size",
9812 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9813 mono_counters_register ("MonoClassExt size",
9814 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9818 * mono_classes_cleanup:
9820 * Free the resources used by this module.
9823 mono_classes_cleanup (void)
9825 if (global_interface_bitset)
9826 mono_bitset_free (global_interface_bitset);
9827 global_interface_bitset = NULL;
9828 mono_os_mutex_destroy (&classes_mutex);
9832 * mono_class_get_exception_for_failure:
9833 * @klass: class in which the failure was detected
9835 * Return a constructed MonoException than the caller can then throw
9836 * using mono_raise_exception - or NULL if no failure is present (or
9837 * doesn't result in an exception).
9840 mono_class_get_exception_for_failure (MonoClass *klass)
9842 gpointer exception_data = mono_class_get_exception_data (klass);
9844 switch (klass->exception_type) {
9845 case MONO_EXCEPTION_TYPE_LOAD: {
9848 char *str = mono_type_get_full_name (klass);
9849 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9850 name = mono_string_new (mono_domain_get (), str);
9852 ex = mono_get_exception_type_load (name, astr);
9856 case MONO_EXCEPTION_MISSING_METHOD: {
9857 char *class_name = exception_data;
9858 char *assembly_name = class_name + strlen (class_name) + 1;
9860 return mono_get_exception_missing_method (class_name, assembly_name);
9862 case MONO_EXCEPTION_MISSING_FIELD: {
9863 char *class_name = exception_data;
9864 char *member_name = class_name + strlen (class_name) + 1;
9866 return mono_get_exception_missing_field (class_name, member_name);
9868 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9869 char *msg_format = exception_data;
9870 char *assembly_name = msg_format + strlen (msg_format) + 1;
9871 char *msg = g_strdup_printf (msg_format, assembly_name);
9874 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9880 case MONO_EXCEPTION_BAD_IMAGE: {
9881 return mono_get_exception_bad_image_format (exception_data);
9884 MonoLoaderError *error;
9887 error = mono_loader_get_last_error ();
9889 ex = mono_loader_error_prepare_exception (error);
9893 /* TODO - handle other class related failures */
9900 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9902 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9903 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9905 if (outer_klass == inner_klass)
9907 inner_klass = inner_klass->nested_in;
9908 } while (inner_klass);
9913 mono_class_get_generic_type_definition (MonoClass *klass)
9915 return klass->generic_class ? klass->generic_class->container_class : klass;
9919 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9921 * Generic instantiations are ignored for all super types of @klass.
9923 * Visibility checks ignoring generic instantiations.
9926 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9929 klass = mono_class_get_generic_type_definition (klass);
9930 parent = mono_class_get_generic_type_definition (parent);
9931 mono_class_setup_supertypes (klass);
9933 for (i = 0; i < klass->idepth; ++i) {
9934 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9940 * Subtype can only access parent members with family protection if the site object
9941 * is subclass of Subtype. For example:
9942 * class A { protected int x; }
9944 * void valid_access () {
9948 * void invalid_access () {
9955 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9957 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9960 if (context_klass == NULL)
9962 /*if access_klass is not member_klass context_klass must be type compat*/
9963 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9969 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9972 if (accessing == accessed)
9974 if (!accessed || !accessing)
9977 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9978 * anywhere so untrusted friends are not safe to access platform's code internals */
9979 if (mono_security_core_clr_enabled ()) {
9980 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9984 mono_assembly_load_friends (accessed);
9985 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9986 MonoAssemblyName *friend = tmp->data;
9987 /* Be conservative with checks */
9990 if (strcmp (accessing->aname.name, friend->name))
9992 if (friend->public_key_token [0]) {
9993 if (!accessing->aname.public_key_token [0])
9995 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
10004 * If klass is a generic type or if it is derived from a generic type, return the
10005 * MonoClass of the generic definition
10006 * Returns NULL if not found
10009 get_generic_definition_class (MonoClass *klass)
10012 if (klass->generic_class && klass->generic_class->container_class)
10013 return klass->generic_class->container_class;
10014 klass = klass->parent;
10020 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10023 for (i = 0; i < ginst->type_argc; ++i) {
10024 MonoType *type = ginst->type_argv[i];
10025 switch (type->type) {
10026 case MONO_TYPE_SZARRAY:
10027 if (!can_access_type (access_klass, type->data.klass))
10030 case MONO_TYPE_ARRAY:
10031 if (!can_access_type (access_klass, type->data.array->eklass))
10034 case MONO_TYPE_PTR:
10035 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10038 case MONO_TYPE_CLASS:
10039 case MONO_TYPE_VALUETYPE:
10040 case MONO_TYPE_GENERICINST:
10041 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10051 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10055 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10058 if (access_klass->element_class && !access_klass->enumtype)
10059 access_klass = access_klass->element_class;
10061 if (member_klass->element_class && !member_klass->enumtype)
10062 member_klass = member_klass->element_class;
10064 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10066 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10069 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10072 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10075 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10078 /*Non nested type with nested visibility. We just fail it.*/
10079 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10082 switch (access_level) {
10083 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10084 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10086 case TYPE_ATTRIBUTE_PUBLIC:
10089 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10092 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10093 return is_nesting_type (member_klass, access_klass);
10095 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10096 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10098 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10099 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10101 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10102 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10103 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10105 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10106 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10107 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10112 /* FIXME: check visibility of type, too */
10114 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10116 MonoClass *member_generic_def;
10117 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10120 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10121 access_klass->generic_container) &&
10122 (member_generic_def = get_generic_definition_class (member_klass))) {
10123 MonoClass *access_container;
10125 if (access_klass->generic_container)
10126 access_container = access_klass;
10128 access_container = access_klass->generic_class->container_class;
10130 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10134 /* Partition I 8.5.3.2 */
10135 /* the access level values are the same for fields and methods */
10136 switch (access_level) {
10137 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10138 /* same compilation unit */
10139 return access_klass->image == member_klass->image;
10140 case FIELD_ATTRIBUTE_PRIVATE:
10141 return access_klass == member_klass;
10142 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10143 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10144 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10147 case FIELD_ATTRIBUTE_ASSEMBLY:
10148 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10149 case FIELD_ATTRIBUTE_FAMILY:
10150 if (is_valid_family_access (access_klass, member_klass, context_klass))
10153 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10154 if (is_valid_family_access (access_klass, member_klass, context_klass))
10156 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10157 case FIELD_ATTRIBUTE_PUBLIC:
10164 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10166 /* FIXME: check all overlapping fields */
10167 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10169 MonoClass *nested = method->klass->nested_in;
10171 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10174 nested = nested->nested_in;
10181 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10183 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10185 MonoClass *nested = method->klass->nested_in;
10187 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10190 nested = nested->nested_in;
10195 * with generics calls to explicit interface implementations can be expressed
10196 * directly: the method is private, but we must allow it. This may be opening
10197 * a hole or the generics code should handle this differently.
10198 * Maybe just ensure the interface type is public.
10200 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10206 * mono_method_can_access_method_full:
10207 * @method: The caller method
10208 * @called: The called method
10209 * @context_klass: The static type on stack of the owner @called object used
10211 * This function must be used with instance calls, as they have more strict family accessibility.
10212 * It can be used with static methods, but context_klass should be NULL.
10214 * Returns: TRUE if caller have proper visibility and acessibility to @called
10217 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10219 MonoClass *access_class = method->klass;
10220 MonoClass *member_class = called->klass;
10221 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10223 MonoClass *nested = access_class->nested_in;
10225 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10228 nested = nested->nested_in;
10235 can = can_access_type (access_class, member_class);
10237 MonoClass *nested = access_class->nested_in;
10239 can = can_access_type (nested, member_class);
10242 nested = nested->nested_in;
10249 if (called->is_inflated) {
10250 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10251 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10260 * mono_method_can_access_field_full:
10261 * @method: The caller method
10262 * @field: The accessed field
10263 * @context_klass: The static type on stack of the owner @field object used
10265 * This function must be used with instance fields, as they have more strict family accessibility.
10266 * It can be used with static fields, but context_klass should be NULL.
10268 * Returns: TRUE if caller have proper visibility and acessibility to @field
10271 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10273 MonoClass *access_class = method->klass;
10274 MonoClass *member_class = field->parent;
10275 /* FIXME: check all overlapping fields */
10276 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10278 MonoClass *nested = access_class->nested_in;
10280 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10283 nested = nested->nested_in;
10290 can = can_access_type (access_class, member_class);
10292 MonoClass *nested = access_class->nested_in;
10294 can = can_access_type (nested, member_class);
10297 nested = nested->nested_in;
10307 * mono_class_can_access_class:
10308 * @source_class: The source class
10309 * @target_class: The accessed class
10311 * This function returns is @target_class is visible to @source_class
10313 * Returns: TRUE if source have proper visibility and acessibility to target
10316 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10318 return can_access_type (source_class, target_class);
10322 * mono_type_is_valid_enum_basetype:
10323 * @type: The MonoType to check
10325 * Returns: TRUE if the type can be used as the basetype of an enum
10327 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10328 switch (type->type) {
10331 case MONO_TYPE_BOOLEAN:
10334 case MONO_TYPE_CHAR:
10348 * mono_class_is_valid_enum:
10349 * @klass: An enum class to be validated
10351 * This method verify the required properties an enum should have.
10353 * Returns: TRUE if the informed enum class is valid
10355 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10356 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10357 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10359 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10360 MonoClassField * field;
10361 gpointer iter = NULL;
10362 gboolean found_base_field = FALSE;
10364 g_assert (klass->enumtype);
10365 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10366 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10370 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10373 while ((field = mono_class_get_fields (klass, &iter))) {
10374 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10375 if (found_base_field)
10377 found_base_field = TRUE;
10378 if (!mono_type_is_valid_enum_basetype (field->type))
10383 if (!found_base_field)
10386 if (klass->method.count > 0)
10393 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10395 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10399 * mono_class_setup_interface_id:
10401 * Initializes MonoClass::interface_id if required.
10403 * LOCKING: Acquires the loader lock.
10406 mono_class_setup_interface_id (MonoClass *klass)
10408 mono_loader_lock ();
10409 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10410 klass->interface_id = mono_get_unique_iid (klass);
10411 mono_loader_unlock ();
10415 * mono_class_alloc_ext:
10417 * Allocate klass->ext if not already done.
10420 mono_class_alloc_ext (MonoClass *klass)
10427 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10428 mono_image_lock (klass->image);
10429 mono_memory_barrier ();
10432 class_ext_size += sizeof (MonoClassExt);
10433 mono_image_unlock (klass->image);
10437 * mono_class_setup_interfaces:
10439 * Initialize klass->interfaces/interfaces_count.
10440 * LOCKING: Acquires the loader lock.
10441 * This function can fail the type.
10444 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10446 int i, interface_count;
10447 MonoClass **interfaces;
10449 mono_error_init (error);
10451 if (klass->interfaces_inited)
10454 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10455 MonoType *args [1];
10457 /* generic IList, ICollection, IEnumerable */
10458 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10459 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10461 args [0] = &klass->element_class->byval_arg;
10462 interfaces [0] = mono_class_bind_generic_parameters (
10463 mono_defaults.generic_ilist_class, 1, args, FALSE);
10464 if (interface_count > 1)
10465 interfaces [1] = mono_class_bind_generic_parameters (
10466 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10467 } else if (klass->generic_class) {
10468 MonoClass *gklass = klass->generic_class->container_class;
10470 mono_class_setup_interfaces (gklass, error);
10471 if (!mono_error_ok (error)) {
10472 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10476 interface_count = gklass->interface_count;
10477 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10478 for (i = 0; i < interface_count; i++) {
10479 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10480 if (!mono_error_ok (error)) {
10481 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10486 interface_count = 0;
10490 mono_image_lock (klass->image);
10492 if (!klass->interfaces_inited) {
10493 klass->interface_count = interface_count;
10494 klass->interfaces = interfaces;
10496 mono_memory_barrier ();
10498 klass->interfaces_inited = TRUE;
10501 mono_image_unlock (klass->image);
10505 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10507 MonoClass *klass = field->parent;
10508 MonoImage *image = klass->image;
10509 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10510 int field_idx = field - klass->fields;
10512 mono_error_init (error);
10515 MonoClassField *gfield = >d->fields [field_idx];
10516 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10517 if (!mono_error_ok (error)) {
10518 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10519 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10523 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10524 if (!mono_error_ok (error)) {
10525 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10526 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10531 guint32 cols [MONO_FIELD_SIZE];
10532 MonoGenericContainer *container = NULL;
10533 int idx = klass->field.first + field_idx;
10535 /*FIXME, in theory we do not lazy load SRE fields*/
10536 g_assert (!image_is_dynamic (image));
10538 if (klass->generic_container) {
10539 container = klass->generic_container;
10541 container = gtd->generic_container;
10542 g_assert (container);
10545 /* klass->field.first and idx points into the fieldptr table */
10546 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10548 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10549 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);
10550 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10554 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10556 mono_metadata_decode_value (sig, &sig);
10557 /* FIELD signature == 0x06 */
10558 g_assert (*sig == 0x06);
10559 field->type = mono_metadata_parse_type_full (image, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10561 mono_class_set_failure_from_loader_error (klass, error, g_strdup_printf ("Could not load field %s type", field->name));
10566 mono_field_resolve_flags (MonoClassField *field)
10568 MonoClass *klass = field->parent;
10569 MonoImage *image = klass->image;
10570 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10571 int field_idx = field - klass->fields;
10575 MonoClassField *gfield = >d->fields [field_idx];
10576 return mono_field_get_flags (gfield);
10578 int idx = klass->field.first + field_idx;
10580 /*FIXME, in theory we do not lazy load SRE fields*/
10581 g_assert (!image_is_dynamic (image));
10583 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10588 * mono_class_setup_basic_field_info:
10589 * @class: The class to initialize
10591 * Initializes the klass->fields array of fields.
10592 * Aquires the loader lock.
10595 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10597 mono_loader_lock ();
10598 mono_class_setup_basic_field_info (klass);
10599 mono_loader_unlock ();
10603 * mono_class_get_fields_lazy:
10604 * @klass: the MonoClass to act on
10606 * This routine is an iterator routine for retrieving the fields in a class.
10607 * Only minimal information about fields are loaded. Accessors must be used
10608 * for all MonoClassField returned.
10610 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10611 * iterate over all of the elements. When no more values are
10612 * available, the return value is NULL.
10614 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10617 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10619 MonoClassField* field;
10623 mono_class_setup_basic_field_info_locking (klass);
10624 if (!klass->fields)
10626 /* start from the first */
10627 if (klass->field.count) {
10628 return *iter = &klass->fields [0];
10636 if (field < &klass->fields [klass->field.count]) {
10637 return *iter = field;
10643 mono_class_full_name (MonoClass *klass)
10645 return mono_type_full_name (&klass->byval_arg);