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-internal.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-internal.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 *class);
67 static void setup_generic_array_ifaces (MonoClass *class, 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 *class, 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_acquire (&classes_mutex, ClassesLock);
110 classes_unlock (void)
112 mono_locks_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 *class = 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 g_assert (!mono_loader_get_last_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_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
351 MonoTypeNameFormat format)
355 switch (type->type) {
356 case MONO_TYPE_ARRAY: {
357 int i, rank = type->data.array->rank;
358 MonoTypeNameFormat nested_format;
360 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
361 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
363 mono_type_get_name_recurse (
364 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
365 g_string_append_c (str, '[');
367 g_string_append_c (str, '*');
368 for (i = 1; i < rank; i++)
369 g_string_append_c (str, ',');
370 g_string_append_c (str, ']');
372 mono_type_name_check_byref (type, str);
374 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
375 _mono_type_get_assembly_name (type->data.array->eklass, str);
378 case MONO_TYPE_SZARRAY: {
379 MonoTypeNameFormat nested_format;
381 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
382 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
384 mono_type_get_name_recurse (
385 &type->data.klass->byval_arg, str, FALSE, nested_format);
386 g_string_append (str, "[]");
388 mono_type_name_check_byref (type, str);
390 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
391 _mono_type_get_assembly_name (type->data.klass, str);
394 case MONO_TYPE_PTR: {
395 MonoTypeNameFormat nested_format;
397 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
398 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
400 mono_type_get_name_recurse (
401 type->data.type, str, FALSE, nested_format);
402 g_string_append_c (str, '*');
404 mono_type_name_check_byref (type, str);
406 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
407 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
412 if (!mono_generic_param_info (type->data.generic_param))
413 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
415 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
417 mono_type_name_check_byref (type, str);
421 klass = mono_class_from_mono_type (type);
422 if (klass->nested_in) {
423 mono_type_get_name_recurse (
424 &klass->nested_in->byval_arg, str, TRUE, format);
425 if (format == MONO_TYPE_NAME_FORMAT_IL)
426 g_string_append_c (str, '.');
428 g_string_append_c (str, '+');
429 } else if (*klass->name_space) {
430 g_string_append (str, klass->name_space);
431 g_string_append_c (str, '.');
433 if (format == MONO_TYPE_NAME_FORMAT_IL) {
434 char *s = strchr (klass->name, '`');
435 int len = s ? s - klass->name : strlen (klass->name);
437 g_string_append_len (str, klass->name, len);
439 g_string_append (str, klass->name);
442 if (klass->generic_class) {
443 MonoGenericClass *gclass = klass->generic_class;
444 MonoGenericInst *inst = gclass->context.class_inst;
445 MonoTypeNameFormat nested_format;
448 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
449 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
451 if (format == MONO_TYPE_NAME_FORMAT_IL)
452 g_string_append_c (str, '<');
454 g_string_append_c (str, '[');
455 for (i = 0; i < inst->type_argc; i++) {
456 MonoType *t = inst->type_argv [i];
459 g_string_append_c (str, ',');
460 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
461 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
462 g_string_append_c (str, '[');
463 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
464 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
465 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
466 g_string_append_c (str, ']');
468 if (format == MONO_TYPE_NAME_FORMAT_IL)
469 g_string_append_c (str, '>');
471 g_string_append_c (str, ']');
472 } else if (klass->generic_container &&
473 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
474 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
477 if (format == MONO_TYPE_NAME_FORMAT_IL)
478 g_string_append_c (str, '<');
480 g_string_append_c (str, '[');
481 for (i = 0; i < klass->generic_container->type_argc; i++) {
483 g_string_append_c (str, ',');
484 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
486 if (format == MONO_TYPE_NAME_FORMAT_IL)
487 g_string_append_c (str, '>');
489 g_string_append_c (str, ']');
492 mono_type_name_check_byref (type, str);
494 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
495 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
496 _mono_type_get_assembly_name (klass, str);
502 * mono_type_get_name_full:
504 * @format: the format for the return string.
507 * Returns: the string representation in a number of formats:
509 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
510 * returned in the formatrequired by System.Reflection, this is the
511 * inverse of mono_reflection_parse_type ().
513 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
514 * be used by the IL assembler.
516 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
518 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
521 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
525 result = g_string_new ("");
527 mono_type_get_name_recurse (type, result, FALSE, format);
529 return g_string_free (result, FALSE);
533 * mono_type_get_full_name:
536 * Returns: the string representation for type as required by System.Reflection.
537 * The inverse of mono_reflection_parse_type ().
540 mono_type_get_full_name (MonoClass *class)
542 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
546 * mono_type_get_name:
549 * Returns: the string representation for type as it would be represented in IL code.
552 mono_type_get_name (MonoType *type)
554 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
558 * mono_type_get_underlying_type:
561 * Returns: the MonoType for the underlying integer type if @type
562 * is an enum and byref is false, otherwise the type itself.
565 mono_type_get_underlying_type (MonoType *type)
567 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.klass);
569 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
570 return mono_class_enum_basetype (type->data.generic_class->container_class);
575 * mono_class_is_open_constructed_type:
578 * Returns TRUE if type represents a generics open constructed type.
579 * IOW, not all type parameters required for the instantiation have
580 * been provided or it's a generic type definition.
582 * An open constructed type means it's a non realizable type. Not to
583 * be mixed up with an abstract type - we can't cast or dispatch to
584 * an open type, for example.
587 mono_class_is_open_constructed_type (MonoType *t)
593 case MONO_TYPE_SZARRAY:
594 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
595 case MONO_TYPE_ARRAY:
596 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
598 return mono_class_is_open_constructed_type (t->data.type);
599 case MONO_TYPE_GENERICINST:
600 return t->data.generic_class->context.class_inst->is_open;
601 case MONO_TYPE_CLASS:
602 case MONO_TYPE_VALUETYPE:
603 return t->data.klass->generic_container != NULL;
610 This is a simple function to catch the most common bad instances of generic types.
611 Specially those that might lead to further failures in the runtime.
614 is_valid_generic_argument (MonoType *type)
616 switch (type->type) {
618 //case MONO_TYPE_TYPEDBYREF:
626 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
628 mono_error_init (error);
630 switch (type->type) {
631 case MONO_TYPE_MVAR: {
633 int num = mono_type_get_generic_param_num (type);
634 MonoGenericInst *inst = context->method_inst;
635 if (!inst || !inst->type_argv)
637 if (num >= inst->type_argc) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
640 num, info ? info->name : "", inst->type_argc);
644 if (!is_valid_generic_argument (inst->type_argv [num])) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
647 num, info ? info->name : "", inst->type_argv [num]->type);
651 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
652 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
653 * ->byref and ->attrs from @type are propagated to the returned type.
655 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
656 nt->byref = type->byref;
657 nt->attrs = type->attrs;
660 case MONO_TYPE_VAR: {
662 int num = mono_type_get_generic_param_num (type);
663 MonoGenericInst *inst = context->class_inst;
666 if (num >= inst->type_argc) {
667 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
668 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
669 num, info ? info->name : "", inst->type_argc);
672 if (!is_valid_generic_argument (inst->type_argv [num])) {
673 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
674 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
675 num, info ? info->name : "", inst->type_argv [num]->type);
678 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
679 nt->byref = type->byref;
680 nt->attrs = type->attrs;
683 case MONO_TYPE_SZARRAY: {
684 MonoClass *eclass = type->data.klass;
685 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
686 if (!inflated || !mono_error_ok (error))
688 nt = mono_metadata_type_dup (image, type);
689 nt->data.klass = mono_class_from_mono_type (inflated);
690 mono_metadata_free_type (inflated);
693 case MONO_TYPE_ARRAY: {
694 MonoClass *eclass = type->data.array->eklass;
695 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
696 if (!inflated || !mono_error_ok (error))
698 nt = mono_metadata_type_dup (image, type);
699 nt->data.array->eklass = mono_class_from_mono_type (inflated);
700 mono_metadata_free_type (inflated);
703 case MONO_TYPE_GENERICINST: {
704 MonoGenericClass *gclass = type->data.generic_class;
705 MonoGenericInst *inst;
707 if (!gclass->context.class_inst->is_open)
710 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
711 if (!mono_error_ok (error))
713 if (inst != gclass->context.class_inst)
714 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
716 if (gclass == type->data.generic_class)
719 nt = mono_metadata_type_dup (image, type);
720 nt->data.generic_class = gclass;
723 case MONO_TYPE_CLASS:
724 case MONO_TYPE_VALUETYPE: {
725 MonoClass *klass = type->data.klass;
726 MonoGenericContainer *container = klass->generic_container;
727 MonoGenericInst *inst;
728 MonoGenericClass *gclass = NULL;
734 /* We can't use context->class_inst directly, since it can have more elements */
735 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
736 if (!mono_error_ok (error))
738 if (inst == container->context.class_inst)
741 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
743 nt = mono_metadata_type_dup (image, type);
744 nt->type = MONO_TYPE_GENERICINST;
745 nt->data.generic_class = gclass;
755 mono_generic_class_get_context (MonoGenericClass *gclass)
757 return &gclass->context;
761 mono_class_get_context (MonoClass *class)
763 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
767 * mono_class_get_generic_container:
769 * Return the generic container of KLASS which should be a generic type definition.
771 MonoGenericContainer*
772 mono_class_get_generic_container (MonoClass *klass)
774 g_assert (klass->is_generic);
776 return klass->generic_container;
780 * mono_class_get_generic_class:
782 * Return the MonoGenericClass of KLASS, which should be a generic instance.
785 mono_class_get_generic_class (MonoClass *klass)
787 g_assert (klass->is_inflated);
789 return klass->generic_class;
793 * mono_class_inflate_generic_type_with_mempool:
794 * @mempool: a mempool
796 * @context: a generics context
797 * @error: error context
799 * The same as mono_class_inflate_generic_type, but allocates the MonoType
800 * from mempool if it is non-NULL. If it is NULL, the MonoType is
801 * allocated on the heap and is owned by the caller.
802 * The returned type can potentially be the same as TYPE, so it should not be
803 * modified by the caller, and it should be freed using mono_metadata_free_type ().
806 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
808 MonoType *inflated = NULL;
809 mono_error_init (error);
812 inflated = inflate_generic_type (image, type, context, error);
813 if (!mono_error_ok (error))
817 MonoType *shared = mono_metadata_get_shared_type (type);
822 return mono_metadata_type_dup (image, type);
826 mono_stats.inflated_type_count++;
831 * mono_class_inflate_generic_type:
833 * @context: a generics context
835 * If @type is a generic type and @context is not NULL, instantiate it using the
836 * generics context @context.
838 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
839 * on the heap and is owned by the caller. Returns NULL on error.
841 * @deprecated Please use mono_class_inflate_generic_type_checked instead
844 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
848 result = mono_class_inflate_generic_type_checked (type, context, &error);
850 if (!mono_error_ok (&error)) {
851 mono_error_cleanup (&error);
858 * mono_class_inflate_generic_type:
860 * @context: a generics context
861 * @error: error context to use
863 * If @type is a generic type and @context is not NULL, instantiate it using the
864 * generics context @context.
866 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
867 * on the heap and is owned by the caller.
870 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
872 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
876 * mono_class_inflate_generic_type_no_copy:
878 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
882 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
884 MonoType *inflated = NULL;
886 mono_error_init (error);
888 inflated = inflate_generic_type (image, type, context, error);
889 if (!mono_error_ok (error))
896 mono_stats.inflated_type_count++;
901 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
906 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
907 if (!mono_error_ok (error))
910 res = mono_class_from_mono_type (inflated);
911 mono_metadata_free_type (inflated);
916 * mono_class_inflate_generic_class:
918 * Inflate the class GKLASS with CONTEXT.
921 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
926 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
927 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
934 static MonoGenericContext
935 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
937 MonoGenericInst *class_inst = NULL;
938 MonoGenericInst *method_inst = NULL;
939 MonoGenericContext res = { NULL, NULL };
941 mono_error_init (error);
943 if (context->class_inst) {
944 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
945 if (!mono_error_ok (error))
949 if (context->method_inst) {
950 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
951 if (!mono_error_ok (error))
955 res.class_inst = class_inst;
956 res.method_inst = method_inst;
962 * mono_class_inflate_generic_method:
963 * @method: a generic method
964 * @context: a generics context
966 * Instantiate the generic method @method using the generics context @context.
968 * Returns: the new instantiated method
971 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
973 return mono_class_inflate_generic_method_full (method, NULL, context);
977 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
979 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
983 * mono_class_inflate_generic_method_full:
985 * Instantiate method @method with the generic context @context.
986 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
987 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
990 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
993 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
994 if (!mono_error_ok (&error))
995 /*FIXME do proper error handling - on this case, kill this function. */
996 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1002 * mono_class_inflate_generic_method_full_checked:
1003 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1006 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1009 MonoMethodInflated *iresult, *cached;
1010 MonoMethodSignature *sig;
1011 MonoGenericContext tmp_context;
1012 gboolean is_mb_open = FALSE;
1014 mono_error_init (error);
1016 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1017 while (method->is_inflated) {
1018 MonoGenericContext *method_context = mono_method_get_context (method);
1019 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1021 tmp_context = inflate_generic_context (method_context, context, error);
1022 if (!mono_error_ok (error))
1024 context = &tmp_context;
1026 if (mono_metadata_generic_context_equal (method_context, context))
1029 method = imethod->declaring;
1033 * A method only needs to be inflated if the context has argument for which it is
1036 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1037 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1040 if (!((method->is_generic && context->method_inst) ||
1041 (method->klass->generic_container && context->class_inst)))
1045 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1046 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1047 * This is opposite to the way non-SRE MethodInfos behave.
1049 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1051 * void Example<T> () {
1055 * In Example, the method token must be encoded as: "void Example<!!0>()"
1057 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1058 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1060 * On the other hand, inflating a non-SRE generic method with its own arguments should
1061 * return itself. For example:
1063 * MethodInfo m = ... //m is a generic method definition
1064 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1067 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1068 * what happens with regular methods.
1070 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1071 * everything should behave like a regular type or method.
1074 is_mb_open = method->is_generic &&
1075 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1076 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1078 iresult = g_new0 (MonoMethodInflated, 1);
1079 iresult->context = *context;
1080 iresult->declaring = method;
1081 iresult->method.method.is_mb_open = is_mb_open;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 /* This can happen with some callers like mono_object_get_virtual_method () */
1094 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = NULL;
1097 cached = mono_method_inflated_lookup (iresult, FALSE);
1100 return (MonoMethod*)cached;
1103 mono_stats.inflated_method_count++;
1105 inflated_methods_size += sizeof (MonoMethodInflated);
1107 sig = mono_method_signature (method);
1109 char *name = mono_type_get_full_name (method->klass);
1110 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1116 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1118 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1121 result = (MonoMethod *) iresult;
1122 result->is_inflated = TRUE;
1123 result->is_generic = FALSE;
1124 result->sre_method = FALSE;
1125 result->signature = NULL;
1126 result->is_mb_open = is_mb_open;
1128 if (!context->method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1138 if (!klass_hint || !klass_hint->generic_class ||
1139 klass_hint->generic_class->container_class != method->klass ||
1140 klass_hint->generic_class->context.class_inst != context->class_inst)
1143 if (method->klass->generic_container)
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1169 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1177 * mono_get_inflated_method:
1179 * Obsolete. We keep it around since it's mentioned in the public API.
1182 mono_get_inflated_method (MonoMethod *method)
1188 * mono_method_get_context_general:
1190 * @uninflated: handle uninflated methods?
1192 * Returns the generic context of a method or NULL if it doesn't have
1193 * one. For an inflated method that's the context stored in the
1194 * method. Otherwise it's in the method's generic container or in the
1195 * generic container of the method's class.
1198 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1200 if (method->is_inflated) {
1201 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1202 return &imethod->context;
1206 if (method->is_generic)
1207 return &(mono_method_get_generic_container (method)->context);
1208 if (method->klass->generic_container)
1209 return &method->klass->generic_container->context;
1214 * mono_method_get_context:
1217 * Returns the generic context for method if it's inflated, otherwise
1221 mono_method_get_context (MonoMethod *method)
1223 return mono_method_get_context_general (method, FALSE);
1227 * mono_method_get_generic_container:
1229 * Returns the generic container of METHOD, which should be a generic method definition.
1230 * Returns NULL if METHOD is not a generic method definition.
1231 * LOCKING: Acquires the loader lock.
1233 MonoGenericContainer*
1234 mono_method_get_generic_container (MonoMethod *method)
1236 MonoGenericContainer *container;
1238 if (!method->is_generic)
1241 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1242 g_assert (container);
1248 * mono_method_set_generic_container:
1250 * Sets the generic container of METHOD to CONTAINER.
1251 * LOCKING: Acquires the image lock.
1254 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1256 g_assert (method->is_generic);
1258 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1262 * mono_class_find_enum_basetype:
1263 * @class: The enum class
1265 * Determine the basetype of an enum by iterating through its fields. We do this
1266 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1269 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1271 MonoGenericContainer *container = NULL;
1272 MonoImage *m = class->image;
1273 const int top = class->field.count;
1276 g_assert (class->enumtype);
1278 mono_error_init (error);
1280 if (class->generic_container)
1281 container = class->generic_container;
1282 else if (class->generic_class) {
1283 MonoClass *gklass = class->generic_class->container_class;
1285 container = gklass->generic_container;
1286 g_assert (container);
1290 * Fetch all the field information.
1292 for (i = 0; i < top; i++){
1294 guint32 cols [MONO_FIELD_SIZE];
1295 int idx = class->field.first + i;
1298 /* class->field.first and idx points into the fieldptr table */
1299 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1301 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1304 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1305 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1309 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1310 mono_metadata_decode_value (sig, &sig);
1311 /* FIELD signature == 0x06 */
1313 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1317 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1319 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1320 mono_error_set_from_loader_error (error);
1322 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1325 if (class->generic_class) {
1326 //FIXME do we leak here?
1327 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1328 if (!mono_error_ok (error))
1330 ftype->attrs = cols [MONO_FIELD_FLAGS];
1335 mono_error_set_type_load_class (error, class, "Could not find base type");
1338 g_assert (!mono_loader_get_last_error ());
1343 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1346 mono_type_has_exceptions (MonoType *type)
1348 switch (type->type) {
1349 case MONO_TYPE_CLASS:
1350 case MONO_TYPE_VALUETYPE:
1351 case MONO_TYPE_SZARRAY:
1352 return type->data.klass->exception_type;
1353 case MONO_TYPE_ARRAY:
1354 return type->data.array->eklass->exception_type;
1355 case MONO_TYPE_GENERICINST:
1356 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1365 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1369 mono_class_alloc (MonoClass *class, int size)
1371 if (class->generic_class)
1372 return mono_image_set_alloc (class->generic_class->owner, size);
1374 return mono_image_alloc (class->image, size);
1378 mono_class_alloc0 (MonoClass *class, int size)
1382 res = mono_class_alloc (class, size);
1383 memset (res, 0, size);
1387 #define mono_class_new0(class,struct_type, n_structs) \
1388 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1391 * mono_class_setup_basic_field_info:
1392 * @class: The class to initialize
1394 * Initializes the class->fields.
1395 * LOCKING: Assumes the loader lock is held.
1398 mono_class_setup_basic_field_info (MonoClass *class)
1400 MonoClassField *field;
1408 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1409 image = class->image;
1410 top = class->field.count;
1412 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1414 * This happens when a generic instance of an unfinished generic typebuilder
1415 * is used as an element type for creating an array type. We can't initialize
1416 * the fields of this class using the fields of gklass, since gklass is not
1417 * finished yet, fields could be added to it later.
1423 mono_class_setup_basic_field_info (gtd);
1425 top = gtd->field.count;
1426 class->field.first = gtd->field.first;
1427 class->field.count = gtd->field.count;
1430 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1433 * Fetch all the field information.
1435 for (i = 0; i < top; i++){
1436 field = &class->fields [i];
1437 field->parent = class;
1440 field->name = mono_field_get_name (>d->fields [i]);
1442 int idx = class->field.first + i;
1443 /* class->field.first and idx points into the fieldptr table */
1444 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1445 /* The name is needed for fieldrefs */
1446 field->name = mono_metadata_string_heap (image, name_idx);
1452 * mono_class_setup_fields:
1453 * @class: The class to initialize
1455 * Initializes the class->fields.
1456 * LOCKING: Assumes the loader lock is held.
1459 mono_class_setup_fields (MonoClass *class)
1462 MonoImage *m = class->image;
1464 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1465 int i, blittable = TRUE;
1466 guint32 real_size = 0;
1467 guint32 packing_size = 0;
1468 gboolean explicit_size;
1469 MonoClassField *field;
1470 MonoGenericContainer *container = NULL;
1471 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1474 * FIXME: We have a race condition here. It's possible that this function returns
1475 * to its caller with `instance_size` set to `0` instead of the actual size. This
1476 * is not a problem when the function is called recursively on the same class,
1477 * because the size will be initialized by the outer invocation. What follows is a
1478 * description of how it can occur in other cases, too. There it is a problem,
1479 * because it can lead to the GC being asked to allocate an object of size `0`,
1480 * which SGen chokes on. The race condition is triggered infrequently by
1481 * `tests/sgen-suspend.cs`.
1483 * This function is called for a class whenever one of its subclasses is inited.
1484 * For example, it's called for every subclass of Object. What it does is this:
1486 * if (class->setup_fields_called)
1489 * class->instance_size = 0;
1491 * class->setup_fields_called = 1;
1492 * ... critical point
1493 * class->instance_size = actual_instance_size;
1495 * The last two steps are sometimes reversed, but that only changes the way in which
1496 * the race condition works.
1498 * Assume thread A goes through this function and makes it to the critical point.
1499 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1500 * immediately, but `instance_size` is incorrect.
1502 * The other case looks like this:
1504 * if (class->setup_fields_called)
1506 * ... critical point X
1507 * class->instance_size = 0;
1508 * ... critical point Y
1509 * class->instance_size = actual_instance_size;
1511 * class->setup_fields_called = 1;
1513 * Assume thread A goes through the function and makes it to critical point X. Now
1514 * thread B runs through the whole of the function, returning, assuming
1515 * `instance_size` is set. At that point thread A gets to run and makes it to
1516 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1519 if (class->setup_fields_called)
1522 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1524 * This happens when a generic instance of an unfinished generic typebuilder
1525 * is used as an element type for creating an array type. We can't initialize
1526 * the fields of this class using the fields of gklass, since gklass is not
1527 * finished yet, fields could be added to it later.
1532 mono_class_setup_basic_field_info (class);
1533 top = class->field.count;
1536 mono_class_setup_fields (gtd);
1537 if (gtd->exception_type) {
1538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1543 class->instance_size = 0;
1545 class->sizes.class_size = 0;
1547 if (class->parent) {
1548 /* For generic instances, class->parent might not have been initialized */
1549 mono_class_init (class->parent);
1550 if (!class->parent->size_inited) {
1551 mono_class_setup_fields (class->parent);
1552 if (class->parent->exception_type) {
1553 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1557 class->instance_size += class->parent->instance_size;
1558 class->min_align = class->parent->min_align;
1559 /* we use |= since it may have been set already */
1560 class->has_references |= class->parent->has_references;
1561 blittable = class->parent->blittable;
1563 class->instance_size = sizeof (MonoObject);
1564 class->min_align = 1;
1567 /* We can't really enable 16 bytes alignment until the GC supports it.
1568 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1569 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1570 Bug #506144 is an example of this issue.
1572 if (class->simd_type)
1573 class->min_align = 16;
1575 /* Get the real size */
1576 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1578 if (explicit_size) {
1579 if ((packing_size & 0xffffff00) != 0) {
1580 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1581 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1584 class->packing_size = packing_size;
1585 real_size += class->instance_size;
1589 if (explicit_size && real_size) {
1590 class->instance_size = MAX (real_size, class->instance_size);
1592 class->blittable = blittable;
1593 mono_memory_barrier ();
1594 class->size_inited = 1;
1595 class->fields_inited = 1;
1596 class->setup_fields_called = 1;
1600 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
1603 /* Prevent infinite loops if the class references itself */
1604 class->setup_fields_called = 1;
1606 if (class->generic_container) {
1607 container = class->generic_container;
1609 container = gtd->generic_container;
1610 g_assert (container);
1614 * Fetch all the field information.
1616 for (i = 0; i < top; i++){
1617 int idx = class->field.first + i;
1618 field = &class->fields [i];
1620 field->parent = class;
1623 mono_field_resolve_type (field, &error);
1624 if (!mono_error_ok (&error)) {
1625 /*mono_field_resolve_type already failed class*/
1626 mono_error_cleanup (&error);
1630 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1631 g_assert (field->type);
1634 if (mono_field_is_deleted (field))
1637 MonoClassField *gfield = >d->fields [i];
1638 field->offset = gfield->offset;
1640 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1642 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1643 field->offset = offset;
1645 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1646 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1649 if (field->offset < -1) { /*-1 is used to encode special static fields */
1650 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1653 if (class->generic_container) {
1654 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1660 /* Only do these checks if we still think this type is blittable */
1661 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1665 MonoClass *field_class = mono_class_from_mono_type (field->type);
1667 mono_class_setup_fields (field_class);
1668 if (field_class->exception_type) {
1669 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1673 if (!field_class || !field_class->blittable)
1678 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1679 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1680 blittable = class->element_class->blittable;
1683 if (mono_type_has_exceptions (field->type)) {
1684 char *class_name = mono_type_get_full_name (class);
1685 char *type_name = mono_type_full_name (field->type);
1687 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1689 g_free (class_name);
1693 /* The def_value of fields is compute lazily during vtable creation */
1696 if (class == mono_defaults.string_class)
1699 class->blittable = blittable;
1701 if (class->enumtype && !mono_class_enum_basetype (class)) {
1702 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 if (explicit_size && real_size) {
1706 class->instance_size = MAX (real_size, class->instance_size);
1709 if (class->exception_type)
1711 mono_class_layout_fields (class);
1713 /*valuetypes can't be neither bigger than 1Mb or empty. */
1714 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1715 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1717 mono_memory_barrier ();
1718 class->fields_inited = 1;
1722 * mono_class_setup_fields_locking:
1723 * @class: The class to initialize
1725 * Initializes the class->fields array of fields.
1726 * Aquires the loader lock.
1729 mono_class_setup_fields_locking (MonoClass *class)
1731 /* This can be checked without locks */
1732 if (class->fields_inited)
1734 mono_loader_lock ();
1735 mono_class_setup_fields (class);
1736 mono_loader_unlock ();
1740 * mono_class_has_references:
1742 * Returns whenever @klass->has_references is set, initializing it if needed.
1743 * Aquires the loader lock.
1746 mono_class_has_references (MonoClass *klass)
1748 if (klass->init_pending) {
1749 /* Be conservative */
1752 mono_class_init (klass);
1754 return klass->has_references;
1759 * mono_type_get_basic_type_from_generic:
1762 * Returns a closed type corresponding to the possibly open type
1766 mono_type_get_basic_type_from_generic (MonoType *type)
1768 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1769 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1770 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1771 return &mono_defaults.object_class->byval_arg;
1776 type_has_references (MonoClass *klass, MonoType *ftype)
1778 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)))))
1780 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1781 MonoGenericParam *gparam = ftype->data.generic_param;
1783 if (gparam->gshared_constraint)
1784 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1790 * mono_class_layout_fields:
1793 * Compute the placement of fields inside an object or struct, according to
1794 * the layout rules and set the following fields in @class:
1795 * - has_references (if the class contains instance references firled or structs that contain references)
1796 * - has_static_refs (same, but for static fields)
1797 * - instance_size (size of the object in memory)
1798 * - class_size (size needed for the static fields)
1799 * - size_inited (flag set when the instance_size is set)
1801 * LOCKING: this is supposed to be called with the loader lock held.
1804 mono_class_layout_fields (MonoClass *class)
1807 const int top = class->field.count;
1808 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1809 guint32 pass, passes, real_size;
1810 gboolean gc_aware_layout = FALSE;
1811 gboolean has_static_fields = FALSE;
1812 MonoClassField *field;
1815 * When we do generic sharing we need to have layout
1816 * information for open generic classes (either with a generic
1817 * context containing type variables or with a generic
1818 * container), so we don't return in that case anymore.
1822 * Enable GC aware auto layout: in this mode, reference
1823 * fields are grouped together inside objects, increasing collector
1825 * Requires that all classes whose layout is known to native code be annotated
1826 * with [StructLayout (LayoutKind.Sequential)]
1827 * Value types have gc_aware_layout disabled by default, as per
1828 * what the default is for other runtimes.
1830 /* corlib is missing [StructLayout] directives in many places */
1831 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1832 if (!class->valuetype)
1833 gc_aware_layout = TRUE;
1836 /* Compute klass->has_references */
1838 * Process non-static fields first, since static fields might recursively
1839 * refer to the class itself.
1841 for (i = 0; i < top; i++) {
1844 field = &class->fields [i];
1846 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1847 ftype = mono_type_get_underlying_type (field->type);
1848 ftype = mono_type_get_basic_type_from_generic (ftype);
1849 if (type_has_references (class, ftype))
1850 class->has_references = TRUE;
1854 for (i = 0; i < top; i++) {
1857 field = &class->fields [i];
1859 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1860 ftype = mono_type_get_underlying_type (field->type);
1861 ftype = mono_type_get_basic_type_from_generic (ftype);
1862 if (type_has_references (class, ftype))
1863 class->has_static_refs = TRUE;
1867 for (i = 0; i < top; i++) {
1870 field = &class->fields [i];
1872 ftype = mono_type_get_underlying_type (field->type);
1873 ftype = mono_type_get_basic_type_from_generic (ftype);
1874 if (type_has_references (class, ftype)) {
1875 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1876 class->has_static_refs = TRUE;
1878 class->has_references = TRUE;
1883 * Compute field layout and total size (not considering static fields)
1887 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1888 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1890 if (gc_aware_layout)
1895 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1898 if (class->parent) {
1899 mono_class_setup_fields (class->parent);
1900 if (class->parent->exception_type) {
1901 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1904 real_size = class->parent->instance_size;
1906 real_size = sizeof (MonoObject);
1909 for (pass = 0; pass < passes; ++pass) {
1910 for (i = 0; i < top; i++){
1915 field = &class->fields [i];
1917 if (mono_field_is_deleted (field))
1919 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1922 ftype = mono_type_get_underlying_type (field->type);
1923 ftype = mono_type_get_basic_type_from_generic (ftype);
1924 if (gc_aware_layout) {
1925 if (type_has_references (class, ftype)) {
1934 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1935 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1936 /* This field is a hack inserted by MCS to empty structures */
1940 size = mono_type_size (field->type, &align);
1942 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1943 align = class->packing_size ? MIN (class->packing_size, align): align;
1944 /* if the field has managed references, we need to force-align it
1947 if (type_has_references (class, ftype))
1948 align = MAX (align, sizeof (gpointer));
1950 class->min_align = MAX (align, class->min_align);
1951 field->offset = real_size;
1953 field->offset += align - 1;
1954 field->offset &= ~(align - 1);
1956 /*TypeBuilders produce all sort of weird things*/
1957 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1958 real_size = field->offset + size;
1961 class->instance_size = MAX (real_size, class->instance_size);
1963 if (class->instance_size & (class->min_align - 1)) {
1964 class->instance_size += class->min_align - 1;
1965 class->instance_size &= ~(class->min_align - 1);
1969 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1973 for (i = 0; i < top; i++) {
1978 field = &class->fields [i];
1981 * There must be info about all the fields in a type if it
1982 * uses explicit layout.
1984 if (mono_field_is_deleted (field))
1986 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1989 size = mono_type_size (field->type, &align);
1990 align = class->packing_size ? MIN (class->packing_size, align): align;
1991 class->min_align = MAX (align, class->min_align);
1994 * When we get here, field->offset is already set by the
1995 * loader (for either runtime fields or fields loaded from metadata).
1996 * The offset is from the start of the object: this works for both
1997 * classes and valuetypes.
1999 field->offset += sizeof (MonoObject);
2000 ftype = mono_type_get_underlying_type (field->type);
2001 ftype = mono_type_get_basic_type_from_generic (ftype);
2002 if (type_has_references (class, ftype)) {
2003 if (field->offset % sizeof (gpointer)) {
2004 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2011 real_size = MAX (real_size, size + field->offset);
2014 if (class->has_references) {
2015 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2017 /* Check for overlapping reference and non-reference fields */
2018 for (i = 0; i < top; i++) {
2021 field = &class->fields [i];
2023 if (mono_field_is_deleted (field))
2025 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2027 ftype = mono_type_get_underlying_type (field->type);
2028 if (MONO_TYPE_IS_REFERENCE (ftype))
2029 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2031 for (i = 0; i < top; i++) {
2032 field = &class->fields [i];
2034 if (mono_field_is_deleted (field))
2036 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2039 // FIXME: Too much code does this
2041 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2042 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.", class->name, field->offset);
2043 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2047 g_free (ref_bitmap);
2050 class->instance_size = MAX (real_size, class->instance_size);
2051 if (class->instance_size & (class->min_align - 1)) {
2052 class->instance_size += class->min_align - 1;
2053 class->instance_size &= ~(class->min_align - 1);
2059 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2061 * This leads to all kinds of problems with nested structs, so only
2062 * enable it when a MONO_DEBUG property is set.
2064 * For small structs, set min_align to at least the struct size to improve
2065 * performance, and since the JIT memset/memcpy code assumes this and generates
2066 * unaligned accesses otherwise. See #78990 for a testcase.
2068 if (mono_align_small_structs) {
2069 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2070 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2074 mono_memory_barrier ();
2075 class->size_inited = 1;
2078 * Compute static field layout and size
2080 for (i = 0; i < top; i++){
2084 field = &class->fields [i];
2086 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2088 if (mono_field_is_deleted (field))
2091 if (mono_type_has_exceptions (field->type)) {
2092 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2096 has_static_fields = TRUE;
2098 size = mono_type_size (field->type, &align);
2099 field->offset = class->sizes.class_size;
2100 /*align is always non-zero here*/
2101 field->offset += align - 1;
2102 field->offset &= ~(align - 1);
2103 class->sizes.class_size = field->offset + size;
2106 if (has_static_fields && class->sizes.class_size == 0)
2107 /* Simplify code which depends on class_size != 0 if the class has static fields */
2108 class->sizes.class_size = 8;
2112 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2116 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2117 method->klass = class;
2118 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2119 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2120 method->signature = sig;
2121 method->name = name;
2124 if (name [0] == '.') {
2125 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2127 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2133 * mono_class_setup_methods:
2136 * Initializes the 'methods' array in CLASS.
2137 * Calling this method should be avoided if possible since it allocates a lot
2138 * of long-living MonoMethod structures.
2139 * Methods belonging to an interface are assigned a sequential slot starting
2142 * On failure this function sets class->exception_type
2145 mono_class_setup_methods (MonoClass *class)
2148 MonoMethod **methods;
2153 if (class->generic_class) {
2155 MonoClass *gklass = class->generic_class->container_class;
2157 mono_class_init (gklass);
2158 if (!gklass->exception_type)
2159 mono_class_setup_methods (gklass);
2160 if (gklass->exception_type) {
2161 /* FIXME make exception_data less opaque so it's possible to dup it here */
2162 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2166 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2167 count = gklass->method.count;
2168 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2170 for (i = 0; i < count; i++) {
2171 methods [i] = mono_class_inflate_generic_method_full_checked (
2172 gklass->methods [i], class, mono_class_get_context (class), &error);
2173 if (!mono_error_ok (&error)) {
2174 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2175 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2178 mono_error_cleanup (&error);
2182 } else if (class->rank) {
2184 MonoMethod *amethod;
2185 MonoMethodSignature *sig;
2186 int count_generic = 0, first_generic = 0;
2188 gboolean jagged_ctor = FALSE;
2190 count = 3 + (class->rank > 1? 2: 1);
2192 mono_class_setup_interfaces (class, &error);
2193 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2195 if (class->rank == 1 && class->element_class->rank) {
2197 class->method.count ++;
2200 if (class->interface_count) {
2201 count_generic = generic_array_methods (class);
2202 first_generic = count;
2203 count += class->interface_count * count_generic;
2206 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2208 sig = mono_metadata_signature_alloc (class->image, class->rank);
2209 sig->ret = &mono_defaults.void_class->byval_arg;
2210 sig->pinvoke = TRUE;
2211 sig->hasthis = TRUE;
2212 for (i = 0; i < class->rank; ++i)
2213 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2215 amethod = create_array_method (class, ".ctor", sig);
2216 methods [method_num++] = amethod;
2217 if (class->rank > 1) {
2218 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2219 sig->ret = &mono_defaults.void_class->byval_arg;
2220 sig->pinvoke = TRUE;
2221 sig->hasthis = TRUE;
2222 for (i = 0; i < class->rank * 2; ++i)
2223 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2225 amethod = create_array_method (class, ".ctor", sig);
2226 methods [method_num++] = amethod;
2230 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2231 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2232 sig->ret = &mono_defaults.void_class->byval_arg;
2233 sig->pinvoke = TRUE;
2234 sig->hasthis = TRUE;
2235 for (i = 0; i < class->rank + 1; ++i)
2236 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2237 amethod = create_array_method (class, ".ctor", sig);
2238 methods [method_num++] = amethod;
2241 /* element Get (idx11, [idx2, ...]) */
2242 sig = mono_metadata_signature_alloc (class->image, class->rank);
2243 sig->ret = &class->element_class->byval_arg;
2244 sig->pinvoke = TRUE;
2245 sig->hasthis = TRUE;
2246 for (i = 0; i < class->rank; ++i)
2247 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2248 amethod = create_array_method (class, "Get", sig);
2249 methods [method_num++] = amethod;
2250 /* element& Address (idx11, [idx2, ...]) */
2251 sig = mono_metadata_signature_alloc (class->image, class->rank);
2252 sig->ret = &class->element_class->this_arg;
2253 sig->pinvoke = TRUE;
2254 sig->hasthis = TRUE;
2255 for (i = 0; i < class->rank; ++i)
2256 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2257 amethod = create_array_method (class, "Address", sig);
2258 methods [method_num++] = amethod;
2259 /* void Set (idx11, [idx2, ...], element) */
2260 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2261 sig->ret = &mono_defaults.void_class->byval_arg;
2262 sig->pinvoke = TRUE;
2263 sig->hasthis = TRUE;
2264 for (i = 0; i < class->rank; ++i)
2265 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2266 sig->params [i] = &class->element_class->byval_arg;
2267 amethod = create_array_method (class, "Set", sig);
2268 methods [method_num++] = amethod;
2270 for (i = 0; i < class->interface_count; i++)
2271 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2275 count = class->method.count;
2276 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2277 for (i = 0; i < count; ++i) {
2278 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2279 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2281 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2282 mono_error_cleanup (&error);
2287 if (MONO_CLASS_IS_INTERFACE (class)) {
2289 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2290 for (i = 0; i < count; ++i) {
2291 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2292 methods [i]->slot = slot++;
2296 mono_image_lock (class->image);
2298 if (!class->methods) {
2299 class->method.count = count;
2301 /* Needed because of the double-checking locking pattern */
2302 mono_memory_barrier ();
2304 class->methods = methods;
2307 mono_image_unlock (class->image);
2311 * mono_class_get_method_by_index:
2313 * Returns class->methods [index], initializing class->methods if neccesary.
2315 * LOCKING: Acquires the loader lock.
2318 mono_class_get_method_by_index (MonoClass *class, int index)
2321 /* Avoid calling setup_methods () if possible */
2322 if (class->generic_class && !class->methods) {
2323 MonoClass *gklass = class->generic_class->container_class;
2326 m = mono_class_inflate_generic_method_full_checked (
2327 gklass->methods [index], class, mono_class_get_context (class), &error);
2328 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2330 * If setup_methods () is called later for this class, no duplicates are created,
2331 * since inflate_generic_method guarantees that only one instance of a method
2332 * is created for each context.
2335 mono_class_setup_methods (class);
2336 g_assert (m == class->methods [index]);
2340 mono_class_setup_methods (class);
2341 if (class->exception_type) /*FIXME do proper error handling*/
2343 g_assert (index >= 0 && index < class->method.count);
2344 return class->methods [index];
2349 * mono_class_get_inflated_method:
2351 * Given an inflated class CLASS and a method METHOD which should be a method of
2352 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2355 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2357 MonoClass *gklass = class->generic_class->container_class;
2360 g_assert (method->klass == gklass);
2362 mono_class_setup_methods (gklass);
2363 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2365 for (i = 0; i < gklass->method.count; ++i) {
2366 if (gklass->methods [i] == method) {
2367 if (class->methods) {
2368 return class->methods [i];
2371 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2372 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2382 * mono_class_get_vtable_entry:
2384 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2385 * LOCKING: Acquires the loader lock.
2388 mono_class_get_vtable_entry (MonoClass *class, int offset)
2392 if (class->rank == 1) {
2394 * szarrays do not overwrite any methods of Array, so we can avoid
2395 * initializing their vtables in some cases.
2397 mono_class_setup_vtable (class->parent);
2398 if (offset < class->parent->vtable_size)
2399 return class->parent->vtable [offset];
2402 if (class->generic_class) {
2404 MonoClass *gklass = class->generic_class->container_class;
2405 mono_class_setup_vtable (gklass);
2406 m = gklass->vtable [offset];
2408 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2409 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2411 mono_class_setup_vtable (class);
2412 if (class->exception_type)
2414 m = class->vtable [offset];
2421 * mono_class_get_vtable_size:
2423 * Return the vtable size for KLASS.
2426 mono_class_get_vtable_size (MonoClass *klass)
2428 mono_class_setup_vtable (klass);
2430 return klass->vtable_size;
2434 * mono_class_setup_properties:
2436 * Initialize class->ext.property and class->ext.properties.
2438 * This method can fail the class.
2441 mono_class_setup_properties (MonoClass *class)
2443 guint startm, endm, i, j;
2444 guint32 cols [MONO_PROPERTY_SIZE];
2445 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2446 MonoProperty *properties;
2450 if (class->ext && class->ext->properties)
2453 if (class->generic_class) {
2454 MonoClass *gklass = class->generic_class->container_class;
2456 mono_class_init (gklass);
2457 mono_class_setup_properties (gklass);
2458 if (gklass->exception_type) {
2459 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2463 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2465 for (i = 0; i < gklass->ext->property.count; i++) {
2467 MonoProperty *prop = &properties [i];
2469 *prop = gklass->ext->properties [i];
2472 prop->get = mono_class_inflate_generic_method_full_checked (
2473 prop->get, class, mono_class_get_context (class), &error);
2475 prop->set = mono_class_inflate_generic_method_full_checked (
2476 prop->set, class, mono_class_get_context (class), &error);
2478 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2479 prop->parent = class;
2482 first = gklass->ext->property.first;
2483 count = gklass->ext->property.count;
2485 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2486 count = last - first;
2489 mono_class_setup_methods (class);
2490 if (class->exception_type)
2494 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2495 for (i = first; i < last; ++i) {
2496 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2497 properties [i - first].parent = class;
2498 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2499 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2501 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2502 for (j = startm; j < endm; ++j) {
2505 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2507 if (class->image->uncompressed_metadata) {
2509 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2510 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2511 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2513 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2516 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2517 case METHOD_SEMANTIC_SETTER:
2518 properties [i - first].set = method;
2520 case METHOD_SEMANTIC_GETTER:
2521 properties [i - first].get = method;
2530 mono_class_alloc_ext (class);
2532 mono_image_lock (class->image);
2534 if (class->ext->properties) {
2535 /* We leak 'properties' which was allocated from the image mempool */
2536 mono_image_unlock (class->image);
2540 class->ext->property.first = first;
2541 class->ext->property.count = count;
2543 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2544 mono_memory_barrier ();
2546 /* Leave this assignment as the last op in the function */
2547 class->ext->properties = properties;
2549 mono_image_unlock (class->image);
2553 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2555 MonoMethod **om, **retval;
2558 for (om = methods, count = 0; *om; ++om, ++count)
2561 retval = g_new0 (MonoMethod*, count + 1);
2563 for (om = methods, count = 0; *om; ++om, ++count) {
2565 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2566 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2572 /*This method can fail the class.*/
2574 mono_class_setup_events (MonoClass *class)
2577 guint startm, endm, i, j;
2578 guint32 cols [MONO_EVENT_SIZE];
2579 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2583 if (class->ext && class->ext->events)
2586 if (class->generic_class) {
2587 MonoClass *gklass = class->generic_class->container_class;
2588 MonoGenericContext *context = NULL;
2590 mono_class_setup_events (gklass);
2591 if (gklass->exception_type) {
2592 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2596 first = gklass->ext->event.first;
2597 count = gklass->ext->event.count;
2599 events = mono_class_new0 (class, MonoEvent, count);
2602 context = mono_class_get_context (class);
2604 for (i = 0; i < count; i++) {
2606 MonoEvent *event = &events [i];
2607 MonoEvent *gevent = &gklass->ext->events [i];
2609 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2611 event->parent = class;
2612 event->name = gevent->name;
2613 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2614 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2615 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2616 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2617 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2618 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2620 #ifndef MONO_SMALL_CONFIG
2621 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2623 event->attrs = gevent->attrs;
2626 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2627 count = last - first;
2630 mono_class_setup_methods (class);
2631 if (class->exception_type) {
2632 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2637 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2638 for (i = first; i < last; ++i) {
2639 MonoEvent *event = &events [i - first];
2641 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2642 event->parent = class;
2643 event->attrs = cols [MONO_EVENT_FLAGS];
2644 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2646 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2647 for (j = startm; j < endm; ++j) {
2650 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2652 if (class->image->uncompressed_metadata) {
2654 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2655 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2656 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2658 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2661 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2662 case METHOD_SEMANTIC_ADD_ON:
2663 event->add = method;
2665 case METHOD_SEMANTIC_REMOVE_ON:
2666 event->remove = method;
2668 case METHOD_SEMANTIC_FIRE:
2669 event->raise = method;
2671 case METHOD_SEMANTIC_OTHER: {
2672 #ifndef MONO_SMALL_CONFIG
2675 if (event->other == NULL) {
2676 event->other = g_new0 (MonoMethod*, 2);
2678 while (event->other [n])
2680 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2682 event->other [n] = method;
2683 /* NULL terminated */
2684 event->other [n + 1] = NULL;
2695 mono_class_alloc_ext (class);
2697 mono_image_lock (class->image);
2699 if (class->ext->events) {
2700 mono_image_unlock (class->image);
2704 class->ext->event.first = first;
2705 class->ext->event.count = count;
2707 /* Flush any pending writes as we do double checked locking on class->ext.events */
2708 mono_memory_barrier ();
2710 /* Leave this assignment as the last op in the function */
2711 class->ext->events = events;
2713 mono_image_unlock (class->image);
2717 * Global pool of interface IDs, represented as a bitset.
2718 * LOCKING: Protected by the classes lock.
2720 static MonoBitSet *global_interface_bitset = NULL;
2723 * mono_unload_interface_ids:
2724 * @bitset: bit set of interface IDs
2726 * When an image is unloaded, the interface IDs associated with
2727 * the image are put back in the global pool of IDs so the numbers
2731 mono_unload_interface_ids (MonoBitSet *bitset)
2734 mono_bitset_sub (global_interface_bitset, bitset);
2739 mono_unload_interface_id (MonoClass *class)
2741 if (global_interface_bitset && class->interface_id) {
2743 mono_bitset_clear (global_interface_bitset, class->interface_id);
2749 * mono_get_unique_iid:
2752 * Assign a unique integer ID to the interface represented by @class.
2753 * The ID will positive and as small as possible.
2754 * LOCKING: Acquires the classes lock.
2755 * Returns: the new ID.
2758 mono_get_unique_iid (MonoClass *class)
2762 g_assert (MONO_CLASS_IS_INTERFACE (class));
2766 if (!global_interface_bitset) {
2767 global_interface_bitset = mono_bitset_new (128, 0);
2770 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2772 int old_size = mono_bitset_size (global_interface_bitset);
2773 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2774 mono_bitset_free (global_interface_bitset);
2775 global_interface_bitset = new_set;
2778 mono_bitset_set (global_interface_bitset, iid);
2779 /* set the bit also in the per-image set */
2780 if (!class->generic_class) {
2781 if (class->image->interface_bitset) {
2782 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2783 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2784 mono_bitset_free (class->image->interface_bitset);
2785 class->image->interface_bitset = new_set;
2788 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2790 mono_bitset_set (class->image->interface_bitset, iid);
2795 #ifndef MONO_SMALL_CONFIG
2796 if (mono_print_vtable) {
2798 char *type_name = mono_type_full_name (&class->byval_arg);
2799 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2800 generic_id = class->generic_class->context.class_inst->id;
2801 g_assert (generic_id != 0);
2805 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2810 g_assert (iid <= 65535);
2815 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2820 mono_class_setup_interfaces (klass, error);
2821 if (!mono_error_ok (error))
2824 for (i = 0; i < klass->interface_count; i++) {
2825 ic = klass->interfaces [i];
2828 *res = g_ptr_array_new ();
2829 g_ptr_array_add (*res, ic);
2830 mono_class_init (ic);
2831 if (ic->exception_type) {
2832 mono_error_set_type_load_class (error, ic, "Error Loading class");
2836 collect_implemented_interfaces_aux (ic, res, error);
2837 if (!mono_error_ok (error))
2843 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2845 GPtrArray *res = NULL;
2847 collect_implemented_interfaces_aux (klass, &res, error);
2848 if (!mono_error_ok (error)) {
2850 g_ptr_array_free (res, TRUE);
2857 compare_interface_ids (const void *p_key, const void *p_element) {
2858 const MonoClass *key = p_key;
2859 const MonoClass *element = *(MonoClass**) p_element;
2861 return (key->interface_id - element->interface_id);
2864 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2866 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2867 MonoClass **result = mono_binary_search (
2869 klass->interfaces_packed,
2870 klass->interface_offsets_count,
2871 sizeof (MonoClass *),
2872 compare_interface_ids);
2874 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2881 * mono_class_interface_offset_with_variance:
2883 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2884 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2886 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2888 * FIXME figure out MS disambiguation rules and fix this function.
2891 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2892 int i = mono_class_interface_offset (klass, itf);
2893 *non_exact_match = FALSE;
2897 if (!mono_class_has_variant_generic_params (itf))
2900 for (i = 0; i < klass->interface_offsets_count; i++) {
2901 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2902 *non_exact_match = TRUE;
2903 return klass->interface_offsets_packed [i];
2911 print_implemented_interfaces (MonoClass *klass) {
2914 GPtrArray *ifaces = NULL;
2916 int ancestor_level = 0;
2918 name = mono_type_get_full_name (klass);
2919 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2922 for (i = 0; i < klass->interface_offsets_count; i++)
2923 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2924 klass->interfaces_packed [i]->interface_id,
2925 klass->interface_offsets_packed [i],
2926 klass->interfaces_packed [i]->method.count,
2927 klass->interfaces_packed [i]->name_space,
2928 klass->interfaces_packed [i]->name );
2929 printf ("Interface flags: ");
2930 for (i = 0; i <= klass->max_interface_id; i++)
2931 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2932 printf ("(%d,T)", i);
2934 printf ("(%d,F)", i);
2936 printf ("Dump interface flags:");
2937 #ifdef COMPRESSED_INTERFACE_BITMAP
2939 const uint8_t* p = klass->interface_bitmap;
2940 i = klass->max_interface_id;
2942 printf (" %d x 00 %02X", p [0], p [1]);
2948 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2949 printf (" %02X", klass->interface_bitmap [i]);
2952 while (klass != NULL) {
2953 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2954 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2955 if (!mono_error_ok (&error)) {
2956 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2957 mono_error_cleanup (&error);
2958 } else if (ifaces) {
2959 for (i = 0; i < ifaces->len; i++) {
2960 MonoClass *ic = g_ptr_array_index (ifaces, i);
2961 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2962 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2964 mono_class_interface_offset (klass, ic),
2969 g_ptr_array_free (ifaces, TRUE);
2972 klass = klass->parent;
2977 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2980 args [0] = &arg0->byval_arg;
2982 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2986 array_class_get_if_rank (MonoClass *class, guint rank)
2988 return rank ? mono_array_class_get (class, rank) : class;
2992 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2994 valuetype_types [0] = eclass;
2995 if (eclass == mono_defaults.int16_class)
2996 valuetype_types [1] = mono_defaults.uint16_class;
2997 else if (eclass == mono_defaults.uint16_class)
2998 valuetype_types [1] = mono_defaults.int16_class;
2999 else if (eclass == mono_defaults.int32_class)
3000 valuetype_types [1] = mono_defaults.uint32_class;
3001 else if (eclass == mono_defaults.uint32_class)
3002 valuetype_types [1] = mono_defaults.int32_class;
3003 else if (eclass == mono_defaults.int64_class)
3004 valuetype_types [1] = mono_defaults.uint64_class;
3005 else if (eclass == mono_defaults.uint64_class)
3006 valuetype_types [1] = mono_defaults.int64_class;
3007 else if (eclass == mono_defaults.byte_class)
3008 valuetype_types [1] = mono_defaults.sbyte_class;
3009 else if (eclass == mono_defaults.sbyte_class)
3010 valuetype_types [1] = mono_defaults.byte_class;
3011 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3012 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3015 /* this won't be needed once bug #325495 is completely fixed
3016 * though we'll need something similar to know which interfaces to allow
3017 * in arrays when they'll be lazyly created
3019 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3020 * MS returns diferrent types based on which instance is called. For example:
3021 * object obj = new byte[10][];
3022 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3023 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3026 * Fixing this should kill quite some code, save some bits and improve compatibility.
3029 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3031 MonoClass *eclass = class->element_class;
3032 static MonoClass* generic_icollection_class = NULL;
3033 static MonoClass* generic_ienumerable_class = NULL;
3034 static MonoClass* generic_ienumerator_class = NULL;
3035 static MonoClass* generic_ireadonlylist_class = NULL;
3036 static MonoClass* generic_ireadonlycollection_class = NULL;
3037 MonoClass *valuetype_types[2] = { NULL, NULL };
3038 MonoClass **interfaces = NULL;
3039 int i, nifaces, interface_count, real_count, original_rank;
3041 gboolean internal_enumerator;
3042 gboolean eclass_is_valuetype;
3044 if (!mono_defaults.generic_ilist_class) {
3048 internal_enumerator = FALSE;
3049 eclass_is_valuetype = FALSE;
3050 original_rank = eclass->rank;
3051 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3052 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3054 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3056 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3057 original_rank = eclass->rank;
3059 eclass = eclass->element_class;
3060 internal_enumerator = TRUE;
3061 *is_enumerator = TRUE;
3069 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3070 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3072 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3074 if (!generic_icollection_class) {
3075 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3076 "System.Collections.Generic", "ICollection`1");
3077 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3078 "System.Collections.Generic", "IEnumerable`1");
3079 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3080 "System.Collections.Generic", "IEnumerator`1");
3081 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3082 "System.Collections.Generic", "IReadOnlyList`1");
3083 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3084 "System.Collections.Generic", "IReadOnlyCollection`1");
3087 mono_class_init (eclass);
3090 * Arrays in 2.0 need to implement a number of generic interfaces
3091 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3092 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3093 * We collect the types needed to build the
3094 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3095 * the generic interfaces needed to implement.
3097 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3098 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3100 if (eclass->valuetype) {
3101 nifaces = generic_ireadonlylist_class ? 5 : 3;
3102 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3104 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3105 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3106 if (internal_enumerator) {
3108 if (valuetype_types [1])
3112 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3113 interfaces [0] = valuetype_types [0];
3114 if (valuetype_types [1])
3115 interfaces [nifaces] = valuetype_types [1];
3117 eclass_is_valuetype = TRUE;
3120 int idepth = eclass->idepth;
3121 if (!internal_enumerator)
3123 nifaces = generic_ireadonlylist_class ? 2 : 3;
3125 // FIXME: This doesn't seem to work/required for generic params
3126 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3127 mono_class_setup_interface_offsets (eclass);
3129 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3130 /* we add object for interfaces and the supertypes for the other
3131 * types. The last of the supertypes is the element class itself which we
3132 * already created the explicit interfaces for (so we include it for IEnumerator
3133 * and exclude it for arrays).
3135 if (MONO_CLASS_IS_INTERFACE (eclass))
3138 interface_count += idepth;
3139 if (eclass->rank && eclass->element_class->valuetype) {
3140 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3141 if (valuetype_types [1])
3144 /* IList, ICollection, IEnumerable, IReadOnlyList */
3145 interface_count *= nifaces;
3146 real_count = interface_count;
3147 if (internal_enumerator) {
3148 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3149 if (valuetype_types [1])
3152 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3153 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3154 interfaces [0] = mono_defaults.object_class;
3158 for (i = 0; i < idepth; i++) {
3159 mono_class_init (eclass->supertypes [i]);
3160 interfaces [j] = eclass->supertypes [i];
3164 if (all_interfaces) {
3165 for (i = 0; i < eclass->interface_offsets_count; i++) {
3166 interfaces [j] = eclass->interfaces_packed [i];
3170 for (i = 0; i < eclass->interface_count; i++) {
3171 interfaces [j] = eclass->interfaces [i];
3175 if (valuetype_types [1]) {
3176 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3181 /* instantiate the generic interfaces */
3182 for (i = 0; i < interface_count; i += nifaces) {
3183 MonoClass *iface = interfaces [i];
3185 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3186 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3188 if (eclass->valuetype) {
3189 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3190 if (generic_ireadonlylist_class) {
3191 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3192 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3195 if (!generic_ireadonlylist_class)
3196 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3199 if (internal_enumerator) {
3201 /* instantiate IEnumerator<iface> */
3202 for (i = 0; i < interface_count; i++) {
3203 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3205 j = interface_count;
3206 if (!eclass_is_valuetype) {
3207 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3208 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3211 for (i = 0; i < eclass->idepth; i++) {
3212 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3216 for (i = 0; i < eclass->interface_offsets_count; i++) {
3217 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3221 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3223 if (valuetype_types [1])
3224 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3228 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3229 for (i = 0; i < real_count; ++i) {
3230 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3231 g_print ("%s implements %s\n", type_name, name);
3242 find_array_interface (MonoClass *klass, const char *name)
3245 for (i = 0; i < klass->interface_count; ++i) {
3246 if (strcmp (klass->interfaces [i]->name, name) == 0)
3253 * Return the number of virtual methods.
3254 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3255 * Return -1 on failure.
3256 * FIXME It would be nice if this information could be cached somewhere.
3259 count_virtual_methods (MonoClass *class)
3263 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3265 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3266 mono_class_setup_methods (class);
3267 if (class->exception_type)
3270 for (i = 0; i < class->method.count; ++i) {
3271 flags = class->methods [i]->flags;
3272 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3276 for (i = 0; i < class->method.count; ++i) {
3277 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3279 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3287 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3295 m = (l + num_ifaces) / 2;
3296 if (interfaces_full [m] == ic)
3298 if (l == num_ifaces)
3300 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3309 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3311 int i = find_interface (num_ifaces, interfaces_full, ic);
3313 return interface_offsets_full [i];
3318 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3320 int i = find_interface (num_ifaces, interfaces_full, ic);
3324 interface_offsets_full [i] = offset;
3327 for (i = 0; i < num_ifaces; ++i) {
3328 if (interfaces_full [i]) {
3330 if (interfaces_full [i]->interface_id < ic->interface_id)
3333 while (end < num_ifaces && interfaces_full [end]) end++;
3334 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3335 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3337 interfaces_full [i] = ic;
3338 interface_offsets_full [i] = offset;
3344 #ifdef COMPRESSED_INTERFACE_BITMAP
3347 * Compressed interface bitmap design.
3349 * Interface bitmaps take a large amount of memory, because their size is
3350 * linear with the maximum interface id assigned in the process (each interface
3351 * is assigned a unique id as it is loaded). The number of interface classes
3352 * is high because of the many implicit interfaces implemented by arrays (we'll
3353 * need to lazy-load them in the future).
3354 * Most classes implement a very small number of interfaces, so the bitmap is
3355 * sparse. This bitmap needs to be checked by interface casts, so access to the
3356 * needed bit must be fast and doable with few jit instructions.
3358 * The current compression format is as follows:
3359 * *) it is a sequence of one or more two-byte elements
3360 * *) the first byte in the element is the count of empty bitmap bytes
3361 * at the current bitmap position
3362 * *) the second byte in the element is an actual bitmap byte at the current
3365 * As an example, the following compressed bitmap bytes:
3366 * 0x07 0x01 0x00 0x7
3367 * correspond to the following bitmap:
3368 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3370 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3371 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3372 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3376 * mono_compress_bitmap:
3377 * @dest: destination buffer
3378 * @bitmap: bitmap buffer
3379 * @size: size of @bitmap in bytes
3381 * This is a mono internal function.
3382 * The @bitmap data is compressed into a format that is small but
3383 * still searchable in few instructions by the JIT and runtime.
3384 * The compressed data is stored in the buffer pointed to by the
3385 * @dest array. Passing a #NULL value for @dest allows to just compute
3386 * the size of the buffer.
3387 * This compression algorithm assumes the bits set in the bitmap are
3388 * few and far between, like in interface bitmaps.
3389 * Returns: the size of the compressed bitmap in bytes.
3392 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3396 const uint8_t *end = bitmap + size;
3397 while (bitmap < end) {
3398 if (*bitmap || numz == 255) {
3422 * mono_class_interface_match:
3423 * @bitmap: a compressed bitmap buffer
3424 * @id: the index to check in the bitmap
3426 * This is a mono internal function.
3427 * Checks if a bit is set in a compressed interface bitmap. @id must
3428 * be already checked for being smaller than the maximum id encoded in the
3431 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3435 mono_class_interface_match (const uint8_t *bitmap, int id)
3438 id -= bitmap [0] * 8;
3442 return bitmap [1] & (1 << id);
3451 * LOCKING: this is supposed to be called with the loader lock held.
3452 * Return -1 on failure and set exception_type
3455 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3459 int i, j, max_iid, num_ifaces;
3460 MonoClass **interfaces_full = NULL;
3461 int *interface_offsets_full = NULL;
3463 GPtrArray **ifaces_array = NULL;
3464 int interface_offsets_count;
3465 MonoClass **array_interfaces = NULL;
3466 int num_array_interfaces;
3467 int is_enumerator = FALSE;
3469 mono_class_setup_supertypes (class);
3471 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3472 * implicit interfaces have the property that they are assigned the same slot in the
3473 * vtables for compatible interfaces
3475 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3477 /* compute maximum number of slots and maximum interface id */
3479 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3480 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3481 for (j = 0; j < class->idepth; j++) {
3482 k = class->supertypes [j];
3483 num_ifaces += k->interface_count;
3484 for (i = 0; i < k->interface_count; i++) {
3485 ic = k->interfaces [i];
3488 mono_class_init (ic);
3490 if (max_iid < ic->interface_id)
3491 max_iid = ic->interface_id;
3493 ifaces = mono_class_get_implemented_interfaces (k, &error);
3494 if (!mono_error_ok (&error)) {
3495 char *name = mono_type_get_full_name (k);
3496 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3498 mono_error_cleanup (&error);
3503 num_ifaces += ifaces->len;
3504 for (i = 0; i < ifaces->len; ++i) {
3505 ic = g_ptr_array_index (ifaces, i);
3506 if (max_iid < ic->interface_id)
3507 max_iid = ic->interface_id;
3509 ifaces_array [j] = ifaces;
3513 for (i = 0; i < num_array_interfaces; ++i) {
3514 ic = array_interfaces [i];
3515 mono_class_init (ic);
3516 if (max_iid < ic->interface_id)
3517 max_iid = ic->interface_id;
3520 if (MONO_CLASS_IS_INTERFACE (class)) {
3522 if (max_iid < class->interface_id)
3523 max_iid = class->interface_id;
3525 class->max_interface_id = max_iid;
3526 /* compute vtable offset for interfaces */
3527 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3528 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3530 for (i = 0; i < num_ifaces; i++) {
3531 interface_offsets_full [i] = -1;
3534 /* skip the current class */
3535 for (j = 0; j < class->idepth - 1; j++) {
3536 k = class->supertypes [j];
3537 ifaces = ifaces_array [j];
3540 for (i = 0; i < ifaces->len; ++i) {
3542 ic = g_ptr_array_index (ifaces, i);
3544 /*Force the sharing of interface offsets between parent and subtypes.*/
3545 io = mono_class_interface_offset (k, ic);
3547 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3552 g_assert (class == class->supertypes [class->idepth - 1]);
3553 ifaces = ifaces_array [class->idepth - 1];
3555 for (i = 0; i < ifaces->len; ++i) {
3557 ic = g_ptr_array_index (ifaces, i);
3558 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3560 count = count_virtual_methods (ic);
3562 char *name = mono_type_get_full_name (ic);
3563 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3572 if (MONO_CLASS_IS_INTERFACE (class))
3573 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3575 if (num_array_interfaces) {
3576 if (is_enumerator) {
3577 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3578 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3579 g_assert (ienumerator_offset >= 0);
3580 for (i = 0; i < num_array_interfaces; ++i) {
3581 ic = array_interfaces [i];
3582 if (strcmp (ic->name, "IEnumerator`1") == 0)
3583 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3585 g_assert_not_reached ();
3586 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, interface_offsets_full [ic->interface_id], class->interfaces [0]->name);*/
3589 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3590 int ilist_iface_idx = find_array_interface (class, "IList`1");
3591 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3592 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3593 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3594 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3595 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3596 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3597 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3598 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3599 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3600 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3601 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3602 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3603 for (i = 0; i < num_array_interfaces; ++i) {
3605 ic = array_interfaces [i];
3606 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3607 offset = ilist_offset;
3608 else if (strcmp (ic->name, "ICollection`1") == 0)
3609 offset = icollection_offset;
3610 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3611 offset = ienumerable_offset;
3612 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3613 offset = ireadonlylist_offset;
3614 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3615 offset = ireadonlycollection_offset;
3617 g_assert_not_reached ();
3618 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3619 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3624 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3625 if (interface_offsets_full [i] != -1) {
3626 interface_offsets_count ++;
3631 * We might get called multiple times:
3632 * - mono_class_init ()
3633 * - mono_class_setup_vtable ().
3634 * - mono_class_setup_interface_offsets ().
3635 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3636 * means we have to overwrite those when called from other places (#4440).
3638 if (class->interfaces_packed) {
3640 g_assert (class->interface_offsets_count == interface_offsets_count);
3644 class->interface_offsets_count = interface_offsets_count;
3645 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3646 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3647 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3648 #ifdef COMPRESSED_INTERFACE_BITMAP
3649 bitmap = g_malloc0 (bsize);
3651 bitmap = mono_class_alloc0 (class, bsize);
3653 for (i = 0; i < interface_offsets_count; i++) {
3654 int id = interfaces_full [i]->interface_id;
3655 bitmap [id >> 3] |= (1 << (id & 7));
3656 class->interfaces_packed [i] = interfaces_full [i];
3657 class->interface_offsets_packed [i] = interface_offsets_full [i];
3658 /*if (num_array_interfaces)
3659 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3661 #ifdef COMPRESSED_INTERFACE_BITMAP
3662 i = mono_compress_bitmap (NULL, bitmap, bsize);
3663 class->interface_bitmap = mono_class_alloc0 (class, i);
3664 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3667 class->interface_bitmap = bitmap;
3672 g_free (interfaces_full);
3673 g_free (interface_offsets_full);
3674 g_free (array_interfaces);
3675 for (i = 0; i < class->idepth; i++) {
3676 ifaces = ifaces_array [i];
3678 g_ptr_array_free (ifaces, TRUE);
3680 g_free (ifaces_array);
3682 //printf ("JUST DONE: ");
3683 //print_implemented_interfaces (class);
3689 * Setup interface offsets for interfaces.
3691 * - class->max_interface_id
3692 * - class->interface_offsets_count
3693 * - class->interfaces_packed
3694 * - class->interface_offsets_packed
3695 * - class->interface_bitmap
3697 * This function can fail @class.
3700 mono_class_setup_interface_offsets (MonoClass *class)
3702 mono_loader_lock ();
3704 setup_interface_offsets (class, 0, FALSE);
3706 mono_loader_unlock ();
3709 /*Checks if @klass has @parent as one of it's parents type gtd
3713 * Bar<T> : Foo<Bar<Bar<T>>>
3717 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3719 klass = mono_class_get_generic_type_definition (klass);
3720 parent = mono_class_get_generic_type_definition (parent);
3721 mono_class_setup_supertypes (klass);
3722 mono_class_setup_supertypes (parent);
3724 return klass->idepth >= parent->idepth &&
3725 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3729 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3731 MonoGenericInst *ginst;
3733 if (!class->generic_class) {
3734 mono_class_setup_vtable_full (class, in_setup);
3735 return class->exception_type == 0;
3738 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3739 if (class->generic_class->container_class->exception_type) {
3740 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3744 ginst = class->generic_class->context.class_inst;
3745 for (i = 0; i < ginst->type_argc; ++i) {
3747 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3749 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3750 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3751 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3753 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3754 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3762 * mono_class_setup_vtable:
3764 * Creates the generic vtable of CLASS.
3765 * Initializes the following fields in MonoClass:
3768 * Plus all the fields initialized by setup_interface_offsets ().
3769 * If there is an error during vtable construction, class->exception_type is set.
3771 * LOCKING: Acquires the loader lock.
3774 mono_class_setup_vtable (MonoClass *class)
3776 mono_class_setup_vtable_full (class, NULL);
3780 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3782 MonoMethod **overrides;
3783 MonoGenericContext *context;
3791 if (MONO_CLASS_IS_INTERFACE (class)) {
3792 /* This sets method->slot for all methods if this is an interface */
3793 mono_class_setup_methods (class);
3797 if (class->exception_type)
3800 if (g_list_find (in_setup, class))
3803 mono_loader_lock ();
3805 if (class->vtable) {
3806 mono_loader_unlock ();
3810 mono_stats.generic_vtable_count ++;
3811 in_setup = g_list_prepend (in_setup, class);
3813 if (class->generic_class) {
3814 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3815 mono_loader_unlock ();
3816 g_list_remove (in_setup, class);
3820 context = mono_class_get_context (class);
3821 type_token = class->generic_class->container_class->type_token;
3823 context = (MonoGenericContext *) class->generic_container;
3824 type_token = class->type_token;
3827 if (image_is_dynamic (class->image)) {
3828 /* Generic instances can have zero method overrides without causing any harm.
3829 * This is true since we don't do layout all over again for them, we simply inflate
3830 * the layout of the parent.
3832 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3834 /* The following call fails if there are missing methods in the type */
3835 /* FIXME it's probably a good idea to avoid this for generic instances. */
3836 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3840 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3842 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3846 mono_loader_unlock ();
3847 g_list_remove (in_setup, class);
3852 #define DEBUG_INTERFACE_VTABLE_CODE 0
3853 #define TRACE_INTERFACE_VTABLE_CODE 0
3854 #define VERIFY_INTERFACE_VTABLE_CODE 0
3855 #define VTABLE_SELECTOR (1)
3857 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3858 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3859 if (!(VTABLE_SELECTOR)) break; \
3863 #define DEBUG_INTERFACE_VTABLE(stmt)
3866 #if TRACE_INTERFACE_VTABLE_CODE
3867 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3868 if (!(VTABLE_SELECTOR)) break; \
3872 #define TRACE_INTERFACE_VTABLE(stmt)
3875 #if VERIFY_INTERFACE_VTABLE_CODE
3876 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3877 if (!(VTABLE_SELECTOR)) break; \
3881 #define VERIFY_INTERFACE_VTABLE(stmt)
3885 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3887 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3891 GString *res = g_string_new ("");
3893 g_string_append_c (res, '(');
3894 for (i = 0; i < sig->param_count; ++i) {
3896 g_string_append_c (res, ',');
3897 mono_type_get_desc (res, sig->params [i], include_namespace);
3899 g_string_append (res, ")=>");
3900 if (sig->ret != NULL) {
3901 mono_type_get_desc (res, sig->ret, include_namespace);
3903 g_string_append (res, "NULL");
3906 g_string_free (res, FALSE);
3910 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3911 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3912 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3913 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3921 is_wcf_hack_disabled (void)
3923 static gboolean disabled;
3924 static gboolean inited = FALSE;
3926 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3933 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3935 MonoMethodSignature *cmsig, *imsig;
3936 if (strcmp (im->name, cm->name) == 0) {
3937 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3938 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3941 if (! slot_is_empty) {
3942 if (require_newslot) {
3943 if (! interface_is_explicitly_implemented_by_class) {
3944 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3947 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3948 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3952 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3955 cmsig = mono_method_signature (cm);
3956 imsig = mono_method_signature (im);
3957 if (!cmsig || !imsig) {
3958 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3962 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3963 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3964 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3965 TRACE_INTERFACE_VTABLE (printf ("]"));
3968 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3969 if (mono_security_core_clr_enabled ())
3970 mono_security_core_clr_check_override (class, cm, im);
3972 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3973 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3974 char *body_name = mono_method_full_name (cm, TRUE);
3975 char *decl_name = mono_method_full_name (im, TRUE);
3976 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
3984 MonoClass *ic = im->klass;
3985 const char *ic_name_space = ic->name_space;
3986 const char *ic_name = ic->name;
3989 if (! require_newslot) {
3990 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3993 if (cm->klass->rank == 0) {
3994 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3997 cmsig = mono_method_signature (cm);
3998 imsig = mono_method_signature (im);
3999 if (!cmsig || !imsig) {
4000 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4004 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4005 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4006 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4007 TRACE_INTERFACE_VTABLE (printf ("]"));
4010 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4011 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4014 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4015 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4018 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))) {
4019 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4023 subname = strstr (cm->name, ic_name_space);
4024 if (subname != cm->name) {
4025 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4028 subname += strlen (ic_name_space);
4029 if (subname [0] != '.') {
4030 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4034 if (strstr (subname, ic_name) != subname) {
4035 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4038 subname += strlen (ic_name);
4039 if (subname [0] != '.') {
4040 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4044 if (strcmp (subname, im->name) != 0) {
4045 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4049 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4050 if (mono_security_core_clr_enabled ())
4051 mono_security_core_clr_check_override (class, cm, im);
4053 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4054 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4055 char *body_name = mono_method_full_name (cm, TRUE);
4056 char *decl_name = mono_method_full_name (im, TRUE);
4057 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4067 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4069 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4070 MonoMethod *method = key;
4071 MonoMethod *override = value;
4072 MonoClass *method_class = mono_method_get_class (method);
4073 MonoClass *override_class = mono_method_get_class (override);
4075 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4076 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4077 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4080 print_overrides (GHashTable *override_map, const char *message) {
4082 printf ("Override map \"%s\" START:\n", message);
4083 g_hash_table_foreach (override_map, foreach_override, NULL);
4084 printf ("Override map \"%s\" END.\n", message);
4086 printf ("Override map \"%s\" EMPTY.\n", message);
4090 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4091 char *full_name = mono_type_full_name (&class->byval_arg);
4095 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4097 if (print_interfaces) {
4098 print_implemented_interfaces (class);
4099 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4102 if (class->parent) {
4103 parent_size = class->parent->vtable_size;
4107 for (i = 0; i < size; ++i) {
4108 MonoMethod *cm = vtable [i];
4109 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4110 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4112 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4120 #if VERIFY_INTERFACE_VTABLE_CODE
4122 mono_method_try_get_vtable_index (MonoMethod *method)
4124 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4125 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4126 if (imethod->declaring->is_generic)
4127 return imethod->declaring->slot;
4129 return method->slot;
4133 mono_class_verify_vtable (MonoClass *class)
4136 char *full_name = mono_type_full_name (&class->byval_arg);
4138 printf ("*** Verifying VTable of class '%s' \n", full_name);
4142 if (!class->methods)
4145 for (i = 0; i < class->method.count; ++i) {
4146 MonoMethod *cm = class->methods [i];
4149 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4153 full_name = mono_method_full_name (cm, TRUE);
4155 slot = mono_method_try_get_vtable_index (cm);
4157 if (slot >= class->vtable_size) {
4158 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4162 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4163 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4164 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4165 g_free (other_name);
4168 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4175 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4177 char *method_signature;
4180 for (index = 0; index < onum; ++index) {
4181 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4182 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4184 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4185 type_name = mono_type_full_name (&class->byval_arg);
4186 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4187 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4188 g_free (method_signature);
4190 mono_class_setup_methods (class);
4191 if (class->exception_type) {
4192 char *name = mono_type_get_full_name (class);
4193 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4197 for (index = 0; index < class->method.count; ++index) {
4198 MonoMethod *cm = class->methods [index];
4199 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4201 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4202 g_free (method_signature);
4207 mono_method_get_method_definition (MonoMethod *method)
4209 while (method->is_inflated)
4210 method = ((MonoMethodInflated*)method)->declaring;
4215 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4219 for (i = 0; i < onum; ++i) {
4220 MonoMethod *decl = overrides [i * 2];
4221 MonoMethod *body = overrides [i * 2 + 1];
4223 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4224 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4228 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4229 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4230 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4232 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4236 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4237 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4238 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4240 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4244 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4245 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4249 body = mono_method_get_method_definition (body);
4250 decl = mono_method_get_method_definition (decl);
4252 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4253 char *body_name = mono_method_full_name (body, TRUE);
4254 char *decl_name = mono_method_full_name (decl, TRUE);
4255 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4265 mono_class_need_stelemref_method (MonoClass *class)
4267 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4271 * LOCKING: this is supposed to be called with the loader lock held.
4274 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4278 MonoMethod **vtable;
4279 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4280 GPtrArray *ifaces = NULL;
4281 GHashTable *override_map = NULL;
4283 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4284 int first_non_interface_slot;
4286 GSList *virt_methods = NULL, *l;
4287 int stelemref_slot = 0;
4292 if (overrides && !verify_class_overrides (class, overrides, onum))
4295 ifaces = mono_class_get_implemented_interfaces (class, &error);
4296 if (!mono_error_ok (&error)) {
4297 char *name = mono_type_get_full_name (class);
4298 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4300 mono_error_cleanup (&error);
4302 } else if (ifaces) {
4303 for (i = 0; i < ifaces->len; i++) {
4304 MonoClass *ic = g_ptr_array_index (ifaces, i);
4305 max_vtsize += ic->method.count;
4307 g_ptr_array_free (ifaces, TRUE);
4311 if (class->parent) {
4312 mono_class_init (class->parent);
4313 mono_class_setup_vtable_full (class->parent, in_setup);
4315 if (class->parent->exception_type) {
4316 char *name = mono_type_get_full_name (class->parent);
4317 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4322 max_vtsize += class->parent->vtable_size;
4323 cur_slot = class->parent->vtable_size;
4326 max_vtsize += class->method.count;
4328 /*Array have a slot for stelemref*/
4329 if (mono_class_need_stelemref_method (class)) {
4330 stelemref_slot = cur_slot;
4335 vtable = alloca (sizeof (gpointer) * max_vtsize);
4336 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4338 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4340 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4341 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4344 max_iid = class->max_interface_id;
4345 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4347 /* Optimized version for generic instances */
4348 if (class->generic_class) {
4350 MonoClass *gklass = class->generic_class->container_class;
4353 mono_class_setup_vtable_full (gklass, in_setup);
4354 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4355 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4359 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4360 class->vtable_size = gklass->vtable_size;
4361 for (i = 0; i < gklass->vtable_size; ++i)
4362 if (gklass->vtable [i]) {
4363 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4364 if (!mono_error_ok (&error)) {
4365 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4366 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4368 mono_error_cleanup (&error);
4372 tmp [i]->slot = gklass->vtable [i]->slot;
4374 mono_memory_barrier ();
4375 class->vtable = tmp;
4377 /* Have to set method->slot for abstract virtual methods */
4378 if (class->methods && gklass->methods) {
4379 for (i = 0; i < class->method.count; ++i)
4380 if (class->methods [i]->slot == -1)
4381 class->methods [i]->slot = gklass->methods [i]->slot;
4387 if (class->parent && class->parent->vtable_size) {
4388 MonoClass *parent = class->parent;
4391 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4393 // Also inherit parent interface vtables, just as a starting point.
4394 // This is needed otherwise bug-77127.exe fails when the property methods
4395 // have different names in the iterface and the class, because for child
4396 // classes the ".override" information is not used anymore.
4397 for (i = 0; i < parent->interface_offsets_count; i++) {
4398 MonoClass *parent_interface = parent->interfaces_packed [i];
4399 int interface_offset = mono_class_interface_offset (class, parent_interface);
4400 /*FIXME this is now dead code as this condition will never hold true.
4401 Since interface offsets are inherited then the offset of an interface implemented
4402 by a parent will never be the out of it's vtable boundary.
4404 if (interface_offset >= parent->vtable_size) {
4405 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4408 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4409 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4410 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4411 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4412 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4413 parent_interface_offset + j, parent_interface_offset, j,
4414 interface_offset + j, interface_offset, j));
4421 /*Array have a slot for stelemref*/
4422 if (mono_class_need_stelemref_method (class)) {
4423 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4425 method->slot = stelemref_slot;
4427 g_assert (method->slot == stelemref_slot);
4429 vtable [stelemref_slot] = method;
4432 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4433 /* override interface methods */
4434 for (i = 0; i < onum; i++) {
4435 MonoMethod *decl = overrides [i*2];
4436 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4438 dslot = mono_method_get_vtable_slot (decl);
4440 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4444 dslot += mono_class_interface_offset (class, decl->klass);
4445 vtable [dslot] = overrides [i*2 + 1];
4446 vtable [dslot]->slot = dslot;
4448 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4450 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4452 if (mono_security_core_clr_enabled ())
4453 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4456 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4457 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4460 * Create a list of virtual methods to avoid calling
4461 * mono_class_get_virtual_methods () which is slow because of the metadata
4465 gpointer iter = NULL;
4468 virt_methods = NULL;
4469 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4470 virt_methods = g_slist_prepend (virt_methods, cm);
4472 if (class->exception_type)
4476 // Loop on all implemented interfaces...
4477 for (i = 0; i < class->interface_offsets_count; i++) {
4478 MonoClass *parent = class->parent;
4480 gboolean interface_is_explicitly_implemented_by_class;
4483 ic = class->interfaces_packed [i];
4484 ic_offset = mono_class_interface_offset (class, ic);
4486 mono_class_setup_methods (ic);
4487 if (ic->exception_type)
4490 // Check if this interface is explicitly implemented (instead of just inherited)
4491 if (parent != NULL) {
4492 int implemented_interfaces_index;
4493 interface_is_explicitly_implemented_by_class = FALSE;
4494 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4495 if (ic == class->interfaces [implemented_interfaces_index]) {
4496 interface_is_explicitly_implemented_by_class = TRUE;
4501 interface_is_explicitly_implemented_by_class = TRUE;
4504 // Loop on all interface methods...
4505 for (im_index = 0; im_index < ic->method.count; im_index++) {
4506 MonoMethod *im = ic->methods [im_index];
4507 int im_slot = ic_offset + im->slot;
4508 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4510 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4513 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4515 // If there is an explicit implementation, just use it right away,
4516 // otherwise look for a matching method
4517 if (override_im == NULL) {
4521 // First look for a suitable method among the class methods
4522 for (l = virt_methods; l; l = l->next) {
4524 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)));
4525 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4526 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4527 vtable [im_slot] = cm;
4528 /* Why do we need this? */
4533 TRACE_INTERFACE_VTABLE (printf ("\n"));
4534 if (class->exception_type) /*Might be set by check_interface_method_override*/
4538 // If the slot is still empty, look in all the inherited virtual methods...
4539 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4540 MonoClass *parent = class->parent;
4541 // Reverse order, so that last added methods are preferred
4542 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4543 MonoMethod *cm = parent->vtable [cm_index];
4545 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));
4546 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
4547 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4548 vtable [im_slot] = cm;
4549 /* Why do we need this? */
4555 if (class->exception_type) /*Might be set by check_interface_method_override*/
4557 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4561 g_assert (vtable [im_slot] == override_im);
4566 // If the class is not abstract, check that all its interface slots are full.
4567 // The check is done here and not directly at the end of the loop above because
4568 // it can happen (for injected generic array interfaces) that the same slot is
4569 // processed multiple times (those interfaces have overlapping slots), and it
4570 // will not always be the first pass the one that fills the slot.
4571 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4572 for (i = 0; i < class->interface_offsets_count; i++) {
4576 ic = class->interfaces_packed [i];
4577 ic_offset = mono_class_interface_offset (class, ic);
4579 for (im_index = 0; im_index < ic->method.count; im_index++) {
4580 MonoMethod *im = ic->methods [im_index];
4581 int im_slot = ic_offset + im->slot;
4583 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4586 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4587 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4588 if (vtable [im_slot] == NULL) {
4589 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4596 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4597 for (l = virt_methods; l; l = l->next) {
4600 * If the method is REUSE_SLOT, we must check in the
4601 * base class for a method to override.
4603 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4605 for (k = class->parent; k ; k = k->parent) {
4610 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4611 MonoMethodSignature *cmsig, *m1sig;
4613 cmsig = mono_method_signature (cm);
4614 m1sig = mono_method_signature (m1);
4616 if (!cmsig || !m1sig) {
4617 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4621 if (!strcmp(cm->name, m1->name) &&
4622 mono_metadata_signature_equal (cmsig, m1sig)) {
4624 if (mono_security_core_clr_enabled ())
4625 mono_security_core_clr_check_override (class, cm, m1);
4627 slot = mono_method_get_vtable_slot (m1);
4631 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4632 char *body_name = mono_method_full_name (cm, TRUE);
4633 char *decl_name = mono_method_full_name (m1, TRUE);
4634 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4640 g_assert (cm->slot < max_vtsize);
4642 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4643 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4644 mono_method_full_name (m1, 1), m1,
4645 mono_method_full_name (cm, 1), cm));
4646 g_hash_table_insert (override_map, m1, cm);
4650 if (k->exception_type)
4660 /*Non final newslot methods must be given a non-interface vtable slot*/
4661 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4665 cm->slot = cur_slot++;
4667 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4668 vtable [cm->slot] = cm;
4671 /* override non interface methods */
4672 for (i = 0; i < onum; i++) {
4673 MonoMethod *decl = overrides [i*2];
4674 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4675 g_assert (decl->slot != -1);
4676 vtable [decl->slot] = overrides [i*2 + 1];
4677 overrides [i * 2 + 1]->slot = decl->slot;
4679 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4680 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4681 mono_method_full_name (decl, 1), decl,
4682 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4683 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4685 if (mono_security_core_clr_enabled ())
4686 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4691 * If a method occupies more than one place in the vtable, and it is
4692 * overriden, then change the other occurances too.
4697 for (i = 0; i < max_vtsize; ++i)
4699 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4701 cm = g_hash_table_lookup (override_map, vtable [i]);
4706 g_hash_table_destroy (override_map);
4707 override_map = NULL;
4710 g_slist_free (virt_methods);
4711 virt_methods = NULL;
4713 /* Ensure that all vtable slots are filled with concrete instance methods */
4714 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4715 for (i = 0; i < cur_slot; ++i) {
4716 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4717 char *type_name = mono_type_get_full_name (class);
4718 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4719 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4721 g_free (method_name);
4727 if (class->generic_class) {
4728 MonoClass *gklass = class->generic_class->container_class;
4730 mono_class_init (gklass);
4732 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4734 /* Check that the vtable_size value computed in mono_class_init () is correct */
4735 if (class->vtable_size)
4736 g_assert (cur_slot == class->vtable_size);
4737 class->vtable_size = cur_slot;
4740 /* Try to share the vtable with our parent. */
4741 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4742 mono_memory_barrier ();
4743 class->vtable = class->parent->vtable;
4745 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4746 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4747 mono_memory_barrier ();
4748 class->vtable = tmp;
4751 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4752 if (mono_print_vtable) {
4755 print_implemented_interfaces (class);
4757 for (i = 0; i <= max_iid; i++)
4758 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4761 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4762 class->vtable_size, icount);
4764 for (i = 0; i < cur_slot; ++i) {
4769 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4770 mono_method_full_name (cm, TRUE));
4776 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4777 class->name, max_iid);
4779 for (i = 0; i < class->interface_count; i++) {
4780 ic = class->interfaces [i];
4781 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4782 mono_class_interface_offset (class, ic),
4783 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4786 for (k = class->parent; k ; k = k->parent) {
4787 for (i = 0; i < k->interface_count; i++) {
4788 ic = k->interfaces [i];
4789 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4790 mono_class_interface_offset (class, ic),
4791 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4797 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4802 char *name = mono_type_get_full_name (class);
4803 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4806 g_hash_table_destroy (override_map);
4808 g_slist_free (virt_methods);
4813 * mono_method_get_vtable_slot:
4815 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4816 * LOCKING: Acquires the loader lock.
4818 * FIXME Use proper MonoError machinery here.
4821 mono_method_get_vtable_slot (MonoMethod *method)
4823 if (method->slot == -1) {
4824 mono_class_setup_vtable (method->klass);
4825 if (method->klass->exception_type)
4827 if (method->slot == -1) {
4831 if (!method->klass->generic_class) {
4832 g_assert (method->is_inflated);
4833 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4836 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4837 g_assert (method->klass->generic_class);
4838 gklass = method->klass->generic_class->container_class;
4839 mono_class_setup_methods (method->klass);
4840 g_assert (method->klass->methods);
4841 for (i = 0; i < method->klass->method.count; ++i) {
4842 if (method->klass->methods [i] == method)
4845 g_assert (i < method->klass->method.count);
4846 g_assert (gklass->methods);
4847 method->slot = gklass->methods [i]->slot;
4849 g_assert (method->slot != -1);
4851 return method->slot;
4855 * mono_method_get_vtable_index:
4858 * Returns the index into the runtime vtable to access the method or,
4859 * in the case of a virtual generic method, the virtual generic method
4860 * thunk. Returns -1 on failure.
4862 * FIXME Use proper MonoError machinery here.
4865 mono_method_get_vtable_index (MonoMethod *method)
4867 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4868 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4869 if (imethod->declaring->is_generic)
4870 return mono_method_get_vtable_slot (imethod->declaring);
4872 return mono_method_get_vtable_slot (method);
4875 static MonoMethod *default_ghc = NULL;
4876 static MonoMethod *default_finalize = NULL;
4877 static int finalize_slot = -1;
4878 static int ghc_slot = -1;
4881 initialize_object_slots (MonoClass *class)
4886 if (class == mono_defaults.object_class) {
4887 mono_class_setup_vtable (class);
4888 for (i = 0; i < class->vtable_size; ++i) {
4889 MonoMethod *cm = class->vtable [i];
4891 if (!strcmp (cm->name, "GetHashCode"))
4893 else if (!strcmp (cm->name, "Finalize"))
4897 g_assert (ghc_slot > 0);
4898 default_ghc = class->vtable [ghc_slot];
4900 g_assert (finalize_slot > 0);
4901 default_finalize = class->vtable [finalize_slot];
4906 MonoMethod *array_method;
4908 } GenericArrayMethodInfo;
4910 static int generic_array_method_num = 0;
4911 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4914 generic_array_methods (MonoClass *class)
4916 int i, count_generic = 0;
4917 GList *list = NULL, *tmp;
4918 if (generic_array_method_num)
4919 return generic_array_method_num;
4920 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4921 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4922 for (i = 0; i < class->parent->method.count; i++) {
4923 MonoMethod *m = class->parent->methods [i];
4924 if (!strncmp (m->name, "InternalArray__", 15)) {
4926 list = g_list_prepend (list, m);
4929 list = g_list_reverse (list);
4930 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4932 for (tmp = list; tmp; tmp = tmp->next) {
4933 const char *mname, *iname;
4935 MonoMethod *m = tmp->data;
4936 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4937 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4939 generic_array_method_info [i].array_method = m;
4940 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4941 iname = "System.Collections.Generic.ICollection`1.";
4942 mname = m->name + 27;
4943 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4944 iname = "System.Collections.Generic.IEnumerable`1.";
4945 mname = m->name + 27;
4946 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4947 iname = "System.Collections.Generic.IReadOnlyList`1.";
4948 mname = m->name + strlen (ireadonlylist_prefix);
4949 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4950 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4951 mname = m->name + strlen (ireadonlycollection_prefix);
4952 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4953 iname = "System.Collections.Generic.IList`1.";
4954 mname = m->name + 15;
4956 g_assert_not_reached ();
4959 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4960 strcpy (name, iname);
4961 strcpy (name + strlen (iname), mname);
4962 generic_array_method_info [i].name = name;
4965 /*g_print ("array generic methods: %d\n", count_generic);*/
4967 generic_array_method_num = count_generic;
4969 return generic_array_method_num;
4973 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4975 MonoGenericContext tmp_context;
4978 tmp_context.class_inst = NULL;
4979 tmp_context.method_inst = iface->generic_class->context.class_inst;
4980 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4982 for (i = 0; i < generic_array_method_num; i++) {
4984 MonoMethod *m = generic_array_method_info [i].array_method;
4985 MonoMethod *inflated;
4987 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4988 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4989 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4994 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4996 int null_length = strlen ("(null)");
4997 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4998 char *s = mono_image_alloc (image, len);
5001 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5002 g_assert (result == len - 1);
5008 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
5010 gpointer exception_data = NULL;
5012 switch (error->exception_type) {
5013 case MONO_EXCEPTION_TYPE_LOAD:
5014 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5017 case MONO_EXCEPTION_MISSING_METHOD:
5018 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5021 case MONO_EXCEPTION_MISSING_FIELD: {
5022 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5023 const char *class_name;
5026 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5028 class_name = error->klass->name;
5030 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5033 g_free ((void*)class_name);
5037 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5040 if (error->ref_only)
5041 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.";
5043 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5045 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5049 case MONO_EXCEPTION_BAD_IMAGE:
5050 exception_data = error->msg;
5054 g_assert_not_reached ();
5057 mono_class_set_failure (class, error->exception_type, exception_data);
5062 * @class: the class to initialize
5064 * Compute the instance_size, class_size and other infos that cannot be
5065 * computed at mono_class_get() time. Also compute vtable_size if possible.
5066 * Returns TRUE on success or FALSE if there was a problem in loading
5067 * the type (incorrect assemblies, missing assemblies, methods, etc).
5069 * LOCKING: Acquires the loader lock.
5072 mono_class_init (MonoClass *class)
5075 MonoCachedClassInfo cached_info;
5076 gboolean has_cached_info;
5080 /* Double-checking locking pattern */
5081 if (class->inited || class->exception_type)
5082 return class->exception_type == MONO_EXCEPTION_NONE;
5084 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5086 /* We do everything inside the lock to prevent races */
5087 mono_loader_lock ();
5089 if (class->inited || class->exception_type) {
5090 mono_loader_unlock ();
5091 /* Somebody might have gotten in before us */
5092 return class->exception_type == MONO_EXCEPTION_NONE;
5095 if (class->init_pending) {
5096 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5100 class->init_pending = 1;
5102 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5103 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5108 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5109 MonoClass *element_class = class->element_class;
5110 if (!element_class->inited)
5111 mono_class_init (element_class);
5112 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5113 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5118 mono_stats.initialized_class_count++;
5120 if (class->generic_class && !class->generic_class->is_dynamic) {
5121 MonoClass *gklass = class->generic_class->container_class;
5123 mono_stats.generic_class_count++;
5125 class->method = gklass->method;
5126 class->field = gklass->field;
5128 mono_class_init (gklass);
5129 // FIXME: Why is this needed ?
5130 if (!gklass->exception_type)
5131 mono_class_setup_methods (gklass);
5132 if (gklass->exception_type) {
5133 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5137 if (MONO_CLASS_IS_INTERFACE (class))
5138 class->interface_id = mono_get_unique_iid (class);
5141 if (class->parent && !class->parent->inited)
5142 mono_class_init (class->parent);
5144 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5146 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5147 class->nested_classes_inited = TRUE;
5150 * Computes the size used by the fields, and their locations
5152 if (has_cached_info) {
5153 class->instance_size = cached_info.instance_size;
5154 class->sizes.class_size = cached_info.class_size;
5155 class->packing_size = cached_info.packing_size;
5156 class->min_align = cached_info.min_align;
5157 class->blittable = cached_info.blittable;
5158 class->has_references = cached_info.has_references;
5159 class->has_static_refs = cached_info.has_static_refs;
5160 class->no_special_static_fields = cached_info.no_special_static_fields;
5163 if (!class->size_inited){
5164 mono_class_setup_fields (class);
5165 if (class->exception_type || mono_loader_get_last_error ())
5169 /* Initialize arrays */
5171 class->method.count = 3 + (class->rank > 1? 2: 1);
5173 if (class->interface_count) {
5174 int count_generic = generic_array_methods (class);
5175 class->method.count += class->interface_count * count_generic;
5179 mono_class_setup_supertypes (class);
5182 initialize_object_slots (class);
5185 * Initialize the rest of the data without creating a generic vtable if possible.
5186 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5187 * also avoid computing a generic vtable.
5189 if (has_cached_info) {
5191 class->vtable_size = cached_info.vtable_size;
5192 class->has_finalize = cached_info.has_finalize;
5193 class->has_finalize_inited = TRUE;
5194 class->ghcimpl = cached_info.ghcimpl;
5195 class->has_cctor = cached_info.has_cctor;
5196 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5197 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5198 * The first slot if for array with.
5200 static int szarray_vtable_size[2] = { 0 };
5202 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5205 if (!szarray_vtable_size [slot]) {
5206 mono_class_setup_vtable (class);
5207 szarray_vtable_size [slot] = class->vtable_size;
5209 class->vtable_size = szarray_vtable_size[slot];
5211 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5212 MonoClass *gklass = class->generic_class->container_class;
5214 /* Generic instance case */
5215 class->ghcimpl = gklass->ghcimpl;
5216 class->has_cctor = gklass->has_cctor;
5218 mono_class_setup_vtable (gklass);
5219 if (gklass->exception_type) {
5220 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5224 class->vtable_size = gklass->vtable_size;
5228 /* ghcimpl is not currently used
5230 if (class->parent) {
5231 MonoMethod *cmethod = class->vtable [ghc_slot];
5232 if (cmethod->is_inflated)
5233 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5234 if (cmethod == default_ghc) {
5240 /* C# doesn't allow interfaces to have cctors */
5241 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5242 MonoMethod *cmethod = NULL;
5244 if (class->type_token) {
5245 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5246 /* The find_method function ignores the 'flags' argument */
5247 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5248 class->has_cctor = 1;
5250 mono_class_setup_methods (class);
5251 if (class->exception_type)
5254 for (i = 0; i < class->method.count; ++i) {
5255 MonoMethod *method = class->methods [i];
5256 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5257 (strcmp (".cctor", method->name) == 0)) {
5258 class->has_cctor = 1;
5266 if (class->parent) {
5267 int first_iface_slot;
5268 /* This will compute class->parent->vtable_size for some classes */
5269 mono_class_init (class->parent);
5270 if (class->parent->exception_type) {
5271 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5274 if (mono_loader_get_last_error ())
5276 if (!class->parent->vtable_size) {
5277 /* FIXME: Get rid of this somehow */
5278 mono_class_setup_vtable (class->parent);
5279 if (class->parent->exception_type) {
5280 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5283 if (mono_loader_get_last_error ())
5286 first_iface_slot = class->parent->vtable_size;
5287 if (mono_class_need_stelemref_method (class))
5289 setup_interface_offsets (class, first_iface_slot, TRUE);
5291 setup_interface_offsets (class, 0, TRUE);
5294 if (mono_security_core_clr_enabled ())
5295 mono_security_core_clr_check_inheritance (class);
5297 if (mono_loader_get_last_error ()) {
5298 if (class->exception_type == MONO_EXCEPTION_NONE) {
5299 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5301 mono_loader_clear_error ();
5304 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5305 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5310 /* Because of the double-checking locking pattern */
5311 mono_memory_barrier ();
5313 class->init_pending = 0;
5315 mono_loader_unlock ();
5317 return class->exception_type == MONO_EXCEPTION_NONE;
5321 * mono_class_has_finalizer:
5323 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5327 mono_class_has_finalizer (MonoClass *klass)
5329 MonoClass *class = klass;
5330 gboolean has_finalize = FALSE;
5332 if (klass->has_finalize_inited)
5333 return klass->has_finalize;
5335 /* Interfaces and valuetypes are not supposed to have finalizers */
5336 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5337 MonoMethod *cmethod = NULL;
5339 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5340 } else if (class->generic_class) {
5341 MonoClass *gklass = class->generic_class->container_class;
5343 has_finalize = mono_class_has_finalizer (gklass);
5344 } else if (class->parent && class->parent->has_finalize) {
5345 has_finalize = TRUE;
5347 if (class->parent) {
5349 * Can't search in metadata for a method named Finalize, because that
5350 * ignores overrides.
5352 mono_class_setup_vtable (class);
5353 if (class->exception_type || mono_loader_get_last_error ())
5356 cmethod = class->vtable [finalize_slot];
5360 g_assert (class->vtable_size > finalize_slot);
5362 if (class->parent) {
5363 if (cmethod->is_inflated)
5364 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5365 if (cmethod != default_finalize)
5366 has_finalize = TRUE;
5372 mono_image_lock (klass->image);
5374 if (!klass->has_finalize_inited) {
5375 klass->has_finalize = has_finalize ? 1 : 0;
5377 mono_memory_barrier ();
5378 klass->has_finalize_inited = TRUE;
5381 mono_image_unlock (klass->image);
5383 return klass->has_finalize;
5387 mono_is_corlib_image (MonoImage *image)
5389 /* FIXME: allow the dynamic case for our compilers and with full trust */
5390 if (image_is_dynamic (image))
5391 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5393 return image == mono_defaults.corlib;
5397 * LOCKING: this assumes the loader lock is held
5400 mono_class_setup_mono_type (MonoClass *class)
5402 const char *name = class->name;
5403 const char *nspace = class->name_space;
5404 gboolean is_corlib = mono_is_corlib_image (class->image);
5406 class->this_arg.byref = 1;
5407 class->this_arg.data.klass = class;
5408 class->this_arg.type = MONO_TYPE_CLASS;
5409 class->byval_arg.data.klass = class;
5410 class->byval_arg.type = MONO_TYPE_CLASS;
5412 if (is_corlib && !strcmp (nspace, "System")) {
5413 if (!strcmp (name, "ValueType")) {
5415 * do not set the valuetype bit for System.ValueType.
5416 * class->valuetype = 1;
5418 class->blittable = TRUE;
5419 } else if (!strcmp (name, "Enum")) {
5421 * do not set the valuetype bit for System.Enum.
5422 * class->valuetype = 1;
5424 class->valuetype = 0;
5425 class->enumtype = 0;
5426 } else if (!strcmp (name, "Object")) {
5427 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5428 } else if (!strcmp (name, "String")) {
5429 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5430 } else if (!strcmp (name, "TypedReference")) {
5431 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5435 if (class->valuetype) {
5436 int t = MONO_TYPE_VALUETYPE;
5438 if (is_corlib && !strcmp (nspace, "System")) {
5441 if (!strcmp (name, "Boolean")) {
5442 t = MONO_TYPE_BOOLEAN;
5443 } else if (!strcmp(name, "Byte")) {
5445 class->blittable = TRUE;
5449 if (!strcmp (name, "Char")) {
5454 if (!strcmp (name, "Double")) {
5456 class->blittable = TRUE;
5460 if (!strcmp (name, "Int32")) {
5462 class->blittable = TRUE;
5463 } else if (!strcmp(name, "Int16")) {
5465 class->blittable = TRUE;
5466 } else if (!strcmp(name, "Int64")) {
5468 class->blittable = TRUE;
5469 } else if (!strcmp(name, "IntPtr")) {
5471 class->blittable = TRUE;
5475 if (!strcmp (name, "Single")) {
5477 class->blittable = TRUE;
5478 } else if (!strcmp(name, "SByte")) {
5480 class->blittable = TRUE;
5484 if (!strcmp (name, "UInt32")) {
5486 class->blittable = TRUE;
5487 } else if (!strcmp(name, "UInt16")) {
5489 class->blittable = TRUE;
5490 } else if (!strcmp(name, "UInt64")) {
5492 class->blittable = TRUE;
5493 } else if (!strcmp(name, "UIntPtr")) {
5495 class->blittable = TRUE;
5499 if (!strcmp (name, "TypedReference")) {
5500 t = MONO_TYPE_TYPEDBYREF;
5501 class->blittable = TRUE;
5505 if (!strcmp (name, "Void")) {
5513 class->this_arg.type = class->byval_arg.type = t;
5516 if (MONO_CLASS_IS_INTERFACE (class))
5517 class->interface_id = mono_get_unique_iid (class);
5523 * COM initialization is delayed until needed.
5524 * However when a [ComImport] attribute is present on a type it will trigger
5525 * the initialization. This is not a problem unless the BCL being executed
5526 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5529 init_com_from_comimport (MonoClass *class)
5531 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5532 if (mono_security_core_clr_enabled ()) {
5533 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5534 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5535 /* but it can not be made available for application (i.e. user code) since all COM calls
5536 * are considered native calls. In this case we fail with a TypeLoadException (just like
5537 * Silverlight 2 does */
5538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5543 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5545 #endif /*DISABLE_COM*/
5548 * LOCKING: this assumes the loader lock is held
5551 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5553 gboolean system_namespace;
5554 gboolean is_corlib = mono_is_corlib_image (class->image);
5556 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5558 /* if root of the hierarchy */
5559 if (system_namespace && !strcmp (class->name, "Object")) {
5560 class->parent = NULL;
5561 class->instance_size = sizeof (MonoObject);
5564 if (!strcmp (class->name, "<Module>")) {
5565 class->parent = NULL;
5566 class->instance_size = 0;
5570 if (!MONO_CLASS_IS_INTERFACE (class)) {
5571 /* Imported COM Objects always derive from __ComObject. */
5573 if (MONO_CLASS_IS_IMPORT (class)) {
5574 init_com_from_comimport (class);
5575 if (parent == mono_defaults.object_class)
5576 parent = mono_class_get_com_object_class ();
5580 /* set the parent to something useful and safe, but mark the type as broken */
5581 parent = mono_defaults.object_class;
5582 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5585 class->parent = parent;
5587 if (parent->generic_class && !parent->name) {
5589 * If the parent is a generic instance, we may get
5590 * called before it is fully initialized, especially
5591 * before it has its name.
5596 #ifndef DISABLE_REMOTING
5597 class->marshalbyref = parent->marshalbyref;
5598 class->contextbound = parent->contextbound;
5601 class->delegate = parent->delegate;
5603 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5604 mono_class_set_is_com_object (class);
5606 if (system_namespace) {
5607 #ifndef DISABLE_REMOTING
5608 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5609 class->marshalbyref = 1;
5611 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5612 class->contextbound = 1;
5614 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5615 class->delegate = 1;
5618 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5619 (strcmp (class->parent->name_space, "System") == 0)))
5620 class->valuetype = 1;
5621 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5622 class->valuetype = class->enumtype = 1;
5624 /*class->enumtype = class->parent->enumtype; */
5626 /* initialize com types if COM interfaces are present */
5628 if (MONO_CLASS_IS_IMPORT (class))
5629 init_com_from_comimport (class);
5631 class->parent = NULL;
5637 * mono_class_setup_supertypes:
5640 * Build the data structure needed to make fast type checks work.
5641 * This currently sets two fields in @class:
5642 * - idepth: distance between @class and System.Object in the type
5644 * - supertypes: array of classes: each element has a class in the hierarchy
5645 * starting from @class up to System.Object
5647 * LOCKING: This function is atomic, in case of contention we waste memory.
5650 mono_class_setup_supertypes (MonoClass *class)
5653 MonoClass **supertypes;
5655 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5659 if (class->parent && !class->parent->supertypes)
5660 mono_class_setup_supertypes (class->parent);
5662 class->idepth = class->parent->idepth + 1;
5666 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5667 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5669 if (class->parent) {
5670 supertypes [class->idepth - 1] = class;
5671 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5673 supertypes [0] = class;
5676 mono_atomic_store_release (&class->supertypes, supertypes);
5680 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5682 MonoClass *gtd = (MonoClass*)user_data;
5683 /* Only try to fix generic instances of @gtd */
5684 if (gclass->generic_class->container_class != gtd)
5687 /* Check if the generic instance has no parent. */
5688 if (gtd->parent && !gclass->parent)
5689 mono_generic_class_setup_parent (gclass, gtd);
5695 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5697 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5698 mono_error_set_type_load_class (error, class, msg);
5702 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5704 MonoLoaderError *lerror = mono_loader_get_last_error ();
5707 set_failure_from_loader_error (class, lerror);
5708 mono_error_set_from_loader_error (error);
5712 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5713 mono_error_set_type_load_class (error, class, msg);
5718 * mono_class_create_from_typedef:
5719 * @image: image where the token is valid
5720 * @type_token: typedef token
5721 * @error: used to return any error found while creating the type
5723 * Create the MonoClass* representing the specified type token.
5724 * @type_token must be a TypeDef token.
5726 * FIXME: don't return NULL on failure, just the the caller figure it out.
5729 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5731 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5732 MonoClass *class, *parent = NULL;
5733 guint32 cols [MONO_TYPEDEF_SIZE];
5734 guint32 cols_next [MONO_TYPEDEF_SIZE];
5735 guint tidx = mono_metadata_token_index (type_token);
5736 MonoGenericContext *context = NULL;
5737 const char *name, *nspace;
5739 MonoClass **interfaces;
5740 guint32 field_last, method_last;
5741 guint32 nesting_tokeen;
5743 mono_error_init (error);
5745 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5746 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5747 g_assert (!mono_loader_get_last_error ());
5751 mono_loader_lock ();
5753 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5754 mono_loader_unlock ();
5755 g_assert (!mono_loader_get_last_error ());
5759 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5761 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5762 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5764 class = mono_image_alloc0 (image, sizeof (MonoClass));
5767 class->name_space = nspace;
5769 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5771 class->image = image;
5772 class->type_token = type_token;
5773 class->flags = cols [MONO_TYPEDEF_FLAGS];
5775 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5777 classes_size += sizeof (MonoClass);
5780 * Check whether we're a generic type definition.
5782 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5783 if (class->generic_container) {
5784 class->is_generic = 1;
5785 class->generic_container->owner.klass = class;
5786 context = &class->generic_container->context;
5789 if (class->generic_container)
5790 enable_gclass_recording ();
5792 if (cols [MONO_TYPEDEF_EXTENDS]) {
5794 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5796 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5797 /*WARNING: this must satisfy mono_metadata_type_hash*/
5798 class->this_arg.byref = 1;
5799 class->this_arg.data.klass = class;
5800 class->this_arg.type = MONO_TYPE_CLASS;
5801 class->byval_arg.data.klass = class;
5802 class->byval_arg.type = MONO_TYPE_CLASS;
5804 parent = mono_class_get_checked (image, parent_token, error);
5805 if (parent && context) /* Always inflate */
5806 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5808 if (parent == NULL) {
5809 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5810 goto parent_failure;
5813 for (tmp = parent; tmp; tmp = tmp->parent) {
5815 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5816 goto parent_failure;
5818 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5819 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5820 goto parent_failure;
5825 mono_class_setup_parent (class, parent);
5827 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5828 mono_class_setup_mono_type (class);
5830 if (class->generic_container)
5831 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5834 * This might access class->byval_arg for recursion generated by generic constraints,
5835 * so it has to come after setup_mono_type ().
5837 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5838 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5839 if (!mono_error_ok (error)) {
5840 /*FIXME implement a mono_class_set_failure_from_mono_error */
5841 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5842 mono_loader_unlock ();
5843 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5844 g_assert (!mono_loader_get_last_error ());
5849 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5853 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5857 class->cast_class = class->element_class = class;
5859 if (!class->enumtype) {
5860 if (!mono_metadata_interfaces_from_typedef_full (
5861 image, type_token, &interfaces, &icount, FALSE, context, error)){
5863 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5864 mono_loader_unlock ();
5865 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5869 class->interfaces = interfaces;
5870 class->interface_count = icount;
5871 class->interfaces_inited = 1;
5874 /*g_print ("Load class %s\n", name);*/
5877 * Compute the field and method lists
5879 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5880 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5882 if (tt->rows > tidx){
5883 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5884 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5885 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5887 field_last = image->tables [MONO_TABLE_FIELD].rows;
5888 method_last = image->tables [MONO_TABLE_METHOD].rows;
5891 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5892 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5893 class->field.count = field_last - class->field.first;
5895 class->field.count = 0;
5897 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5898 class->method.count = method_last - class->method.first;
5900 class->method.count = 0;
5902 /* reserve space to store vector pointer in arrays */
5903 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5904 class->instance_size += 2 * sizeof (gpointer);
5905 g_assert (class->field.count == 0);
5908 if (class->enumtype) {
5909 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5910 if (!enum_basetype) {
5911 /*set it to a default value as the whole runtime can't handle this to be null*/
5912 class->cast_class = class->element_class = mono_defaults.int32_class;
5913 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5914 mono_loader_unlock ();
5915 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5916 g_assert (!mono_loader_get_last_error ());
5919 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5923 * If we're a generic type definition, load the constraints.
5924 * We must do this after the class has been constructed to make certain recursive scenarios
5927 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5928 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5929 mono_loader_unlock ();
5930 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5931 g_assert (!mono_loader_get_last_error ());
5935 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5936 if (!strncmp (name, "Vector", 6))
5937 class->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");
5940 mono_loader_unlock ();
5942 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5943 g_assert (!mono_loader_get_last_error ());
5948 mono_class_setup_mono_type (class);
5949 mono_loader_unlock ();
5950 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5951 g_assert (!mono_loader_get_last_error ());
5955 /** is klass Nullable<T>? */
5957 mono_class_is_nullable (MonoClass *klass)
5959 return klass->generic_class != NULL &&
5960 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5964 /** if klass is T? return T */
5966 mono_class_get_nullable_param (MonoClass *klass)
5968 g_assert (mono_class_is_nullable (klass));
5969 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5973 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5977 MonoGenericClass *gclass = klass->generic_class;
5979 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5980 if (!mono_error_ok (&error)) {
5981 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5982 klass->parent = mono_defaults.object_class;
5983 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5984 mono_error_cleanup (&error);
5988 mono_class_setup_parent (klass, klass->parent);
5990 if (klass->enumtype) {
5991 klass->cast_class = gtd->cast_class;
5992 klass->element_class = gtd->element_class;
5998 * Create the `MonoClass' for an instantiation of a generic type.
5999 * We only do this if we actually need it.
6002 mono_generic_class_get_class (MonoGenericClass *gclass)
6004 MonoClass *klass, *gklass;
6006 if (gclass->cached_class)
6007 return gclass->cached_class;
6009 mono_loader_lock ();
6010 if (gclass->cached_class) {
6011 mono_loader_unlock ();
6012 return gclass->cached_class;
6015 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6017 gklass = gclass->container_class;
6019 if (record_gclass_instantiation > 0)
6020 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6022 if (gklass->nested_in) {
6023 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6024 klass->nested_in = gklass->nested_in;
6027 klass->name = gklass->name;
6028 klass->name_space = gklass->name_space;
6030 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6032 klass->image = gklass->image;
6033 klass->flags = gklass->flags;
6034 klass->type_token = gklass->type_token;
6035 klass->field.count = gklass->field.count;
6037 klass->is_inflated = 1;
6038 klass->generic_class = gclass;
6040 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6041 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6042 klass->this_arg.byref = TRUE;
6043 klass->enumtype = gklass->enumtype;
6044 klass->valuetype = gklass->valuetype;
6046 klass->cast_class = klass->element_class = klass;
6048 if (mono_class_is_nullable (klass))
6049 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6052 * We're not interested in the nested classes of a generic instance.
6053 * We use the generic type definition to look for nested classes.
6056 mono_generic_class_setup_parent (klass, gklass);
6058 if (gclass->is_dynamic) {
6060 * 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.
6061 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6062 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6064 if (!gklass->wastypebuilder)
6067 mono_class_setup_supertypes (klass);
6069 if (klass->enumtype) {
6071 * For enums, gklass->fields might not been set, but instance_size etc. is
6072 * already set in mono_reflection_create_internal_class (). For non-enums,
6073 * these will be computed normally in mono_class_layout_fields ().
6075 klass->instance_size = gklass->instance_size;
6076 klass->sizes.class_size = gklass->sizes.class_size;
6077 mono_memory_barrier ();
6078 klass->size_inited = 1;
6082 mono_memory_barrier ();
6083 gclass->cached_class = klass;
6085 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6087 inflated_classes ++;
6088 inflated_classes_size += sizeof (MonoClass);
6090 mono_loader_unlock ();
6096 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6098 MonoClass *klass, **ptr;
6100 MonoGenericContainer *container = mono_generic_param_owner (param);
6104 image = mono_defaults.corlib;
6106 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6107 classes_size += sizeof (MonoClass);
6110 klass->name = pinfo->name;
6112 int n = mono_generic_param_num (param);
6113 klass->name = mono_image_alloc0 (image, 16);
6114 sprintf ((char*)klass->name, "%d", n);
6119 MonoMethod *omethod = container->owner.method;
6120 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6122 MonoClass *oklass = container->owner.klass;
6123 klass->name_space = oklass ? oklass->name_space : "";
6126 klass->name_space = "";
6129 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6133 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6137 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6138 klass->parent = pinfo->constraints [0];
6140 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6141 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6143 klass->parent = mono_defaults.object_class;
6146 if (count - pos > 0) {
6147 klass->interface_count = count - pos;
6148 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6149 klass->interfaces_inited = TRUE;
6150 for (i = pos; i < count; i++)
6151 klass->interfaces [i - pos] = pinfo->constraints [i];
6154 klass->image = image;
6156 klass->inited = TRUE;
6157 klass->cast_class = klass->element_class = klass;
6158 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6160 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6161 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6162 klass->this_arg.byref = TRUE;
6164 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6165 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6167 /*Init these fields to sane values*/
6168 klass->min_align = 1;
6170 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6171 * constrained to, the JIT depends on this.
6173 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6174 mono_memory_barrier ();
6175 klass->size_inited = 1;
6176 klass->setup_fields_called = 1;
6178 mono_class_setup_supertypes (klass);
6180 if (count - pos > 0) {
6181 mono_class_setup_vtable (klass->parent);
6182 if (klass->parent->exception_type)
6183 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6185 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6191 #define FAST_CACHE_SIZE 16
6194 * LOCKING: Takes the image lock depending on @take_lock.
6197 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6199 int n = mono_generic_param_num (param);
6200 MonoImage *image = param->image;
6201 MonoClass *klass = NULL;
6206 if (param->gshared_constraint) {
6207 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6210 mono_image_lock (image);
6211 klass = g_hash_table_lookup (ht, param);
6213 mono_image_unlock (image);
6218 if (n < FAST_CACHE_SIZE) {
6220 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6222 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6224 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6227 mono_image_lock (image);
6228 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6230 mono_image_unlock (image);
6237 * LOCKING: Image lock (param->image) must be held
6240 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6242 int n = mono_generic_param_num (param);
6243 MonoImage *image = param->image;
6247 if (param->gshared_constraint) {
6248 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6250 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6251 mono_memory_barrier ();
6253 image->mvar_cache_constrained = ht;
6255 image->var_cache_constrained = ht;
6257 g_hash_table_insert (ht, param, klass);
6258 } else if (n < FAST_CACHE_SIZE) {
6260 /* Requires locking to avoid droping an already published class */
6261 if (!image->mvar_cache_fast)
6262 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6263 image->mvar_cache_fast [n] = klass;
6265 if (!image->var_cache_fast)
6266 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6267 image->var_cache_fast [n] = klass;
6270 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6272 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6274 ht = g_hash_table_new (NULL, NULL);
6275 mono_memory_barrier ();
6277 image->mvar_cache_slow = ht;
6279 image->var_cache_slow = ht;
6282 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6287 * LOCKING: Acquires the image lock (@image).
6290 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6292 MonoGenericContainer *container = mono_generic_param_owner (param);
6293 MonoGenericParamInfo *pinfo = NULL;
6294 MonoClass *klass, *klass2;
6297 pinfo = mono_generic_param_info (param);
6298 klass = pinfo->pklass;
6301 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6306 if (!image && container) {
6308 MonoMethod *method = container->owner.method;
6309 image = (method && method->klass) ? method->klass->image : NULL;
6311 MonoClass *klass = container->owner.klass;
6312 // FIXME: 'klass' should not be null
6313 // But, monodis creates GenericContainers without associating a owner to it
6314 image = klass ? klass->image : NULL;
6318 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6320 mono_memory_barrier ();
6322 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6323 image = mono_defaults.corlib;
6325 mono_image_lock (image);
6327 klass2 = pinfo->pklass;
6329 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6335 pinfo->pklass = klass;
6337 set_anon_gparam_class (param, is_mvar, klass);
6339 mono_image_unlock (image);
6341 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6343 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6345 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6351 mono_ptr_class_get (MonoType *type)
6354 MonoClass *el_class;
6358 el_class = mono_class_from_mono_type (type);
6359 image = el_class->image;
6361 mono_image_lock (image);
6362 if (image->ptr_cache) {
6363 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6364 mono_image_unlock (image);
6368 mono_image_unlock (image);
6370 result = mono_image_alloc0 (image, sizeof (MonoClass));
6372 classes_size += sizeof (MonoClass);
6374 result->parent = NULL; /* no parent for PTR types */
6375 result->name_space = el_class->name_space;
6376 name = g_strdup_printf ("%s*", el_class->name);
6377 result->name = mono_image_strdup (image, name);
6380 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6382 result->image = el_class->image;
6383 result->inited = TRUE;
6384 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6385 /* Can pointers get boxed? */
6386 result->instance_size = sizeof (gpointer);
6387 result->cast_class = result->element_class = el_class;
6388 result->blittable = TRUE;
6390 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6391 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6392 result->this_arg.byref = TRUE;
6394 mono_class_setup_supertypes (result);
6396 mono_image_lock (image);
6397 if (image->ptr_cache) {
6399 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6400 mono_image_unlock (image);
6401 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6405 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6407 g_hash_table_insert (image->ptr_cache, el_class, result);
6408 mono_image_unlock (image);
6410 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6416 mono_fnptr_class_get (MonoMethodSignature *sig)
6419 static GHashTable *ptr_hash = NULL;
6421 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6423 mono_loader_lock ();
6426 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6428 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6429 mono_loader_unlock ();
6432 result = g_new0 (MonoClass, 1);
6434 result->parent = NULL; /* no parent for PTR types */
6435 result->name_space = "System";
6436 result->name = "MonoFNPtrFakeClass";
6438 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6440 result->image = mono_defaults.corlib; /* need to fix... */
6441 result->inited = TRUE;
6442 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6443 /* Can pointers get boxed? */
6444 result->instance_size = sizeof (gpointer);
6445 result->cast_class = result->element_class = result;
6446 result->blittable = TRUE;
6448 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6449 result->this_arg.data.method = result->byval_arg.data.method = sig;
6450 result->this_arg.byref = TRUE;
6451 result->blittable = TRUE;
6453 mono_class_setup_supertypes (result);
6455 g_hash_table_insert (ptr_hash, sig, result);
6457 mono_loader_unlock ();
6459 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6465 mono_class_from_mono_type (MonoType *type)
6467 switch (type->type) {
6468 case MONO_TYPE_OBJECT:
6469 return type->data.klass? type->data.klass: mono_defaults.object_class;
6470 case MONO_TYPE_VOID:
6471 return type->data.klass? type->data.klass: mono_defaults.void_class;
6472 case MONO_TYPE_BOOLEAN:
6473 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6474 case MONO_TYPE_CHAR:
6475 return type->data.klass? type->data.klass: mono_defaults.char_class;
6477 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6479 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6481 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6483 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6485 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6487 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6489 return type->data.klass? type->data.klass: mono_defaults.int_class;
6491 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6493 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6495 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6497 return type->data.klass? type->data.klass: mono_defaults.single_class;
6499 return type->data.klass? type->data.klass: mono_defaults.double_class;
6500 case MONO_TYPE_STRING:
6501 return type->data.klass? type->data.klass: mono_defaults.string_class;
6502 case MONO_TYPE_TYPEDBYREF:
6503 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6504 case MONO_TYPE_ARRAY:
6505 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6507 return mono_ptr_class_get (type->data.type);
6508 case MONO_TYPE_FNPTR:
6509 return mono_fnptr_class_get (type->data.method);
6510 case MONO_TYPE_SZARRAY:
6511 return mono_array_class_get (type->data.klass, 1);
6512 case MONO_TYPE_CLASS:
6513 case MONO_TYPE_VALUETYPE:
6514 return type->data.klass;
6515 case MONO_TYPE_GENERICINST:
6516 return mono_generic_class_get_class (type->data.generic_class);
6518 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6519 case MONO_TYPE_MVAR:
6520 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6522 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6523 g_assert_not_reached ();
6530 * mono_type_retrieve_from_typespec
6531 * @image: context where the image is created
6532 * @type_spec: typespec token
6533 * @context: the generic context used to evaluate generic instantiations in
6536 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6538 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6540 *did_inflate = FALSE;
6545 if (context && (context->class_inst || context->method_inst)) {
6546 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6548 if (!mono_error_ok (error)) {
6549 g_assert (!mono_loader_get_last_error ());
6555 *did_inflate = TRUE;
6562 * mono_class_create_from_typespec
6563 * @image: context where the image is created
6564 * @type_spec: typespec token
6565 * @context: the generic context used to evaluate generic instantiations in
6568 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6571 gboolean inflated = FALSE;
6572 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6573 if (!mono_error_ok (error))
6575 ret = mono_class_from_mono_type (t);
6577 mono_metadata_free_type (t);
6582 * mono_bounded_array_class_get:
6583 * @element_class: element class
6584 * @rank: the dimension of the array class
6585 * @bounded: whenever the array has non-zero bounds
6587 * Returns: a class object describing the array with element type @element_type and
6591 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6595 MonoClass *parent = NULL;
6596 GSList *list, *rootlist = NULL;
6599 gboolean corlib_type = FALSE;
6601 g_assert (rank <= 255);
6604 /* bounded only matters for one-dimensional arrays */
6607 image = eclass->image;
6609 if (rank == 1 && !bounded) {
6611 * This case is very frequent not just during compilation because of calls
6612 * from mono_class_from_mono_type (), mono_array_new (),
6613 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6615 mono_mutex_lock (&image->szarray_cache_lock);
6616 if (!image->szarray_cache)
6617 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6618 class = g_hash_table_lookup (image->szarray_cache, eclass);
6619 mono_mutex_unlock (&image->szarray_cache_lock);
6623 mono_loader_lock ();
6625 mono_loader_lock ();
6627 if (!image->array_cache)
6628 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6630 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6631 for (; list; list = list->next) {
6633 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6634 mono_loader_unlock ();
6641 /* for the building corlib use System.Array from it */
6642 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6643 parent = mono_class_from_name (image, "System", "Array");
6646 parent = mono_defaults.array_class;
6647 if (!parent->inited)
6648 mono_class_init (parent);
6651 class = mono_image_alloc0 (image, sizeof (MonoClass));
6653 class->image = image;
6654 class->name_space = eclass->name_space;
6655 nsize = strlen (eclass->name);
6656 name = g_malloc (nsize + 2 + rank + 1);
6657 memcpy (name, eclass->name, nsize);
6660 memset (name + nsize + 1, ',', rank - 1);
6662 name [nsize + rank] = '*';
6663 name [nsize + rank + bounded] = ']';
6664 name [nsize + rank + bounded + 1] = 0;
6665 class->name = mono_image_strdup (image, name);
6668 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6670 classes_size += sizeof (MonoClass);
6672 class->type_token = 0;
6673 /* all arrays are marked serializable and sealed, bug #42779 */
6674 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6675 class->parent = parent;
6676 class->instance_size = mono_class_instance_size (class->parent);
6678 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6679 /*Arrays of those two types are invalid.*/
6680 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6681 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6682 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6683 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6684 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6686 /* element_size -1 is ok as this is not an instantitable type*/
6687 class->sizes.element_size = -1;
6689 class->sizes.element_size = mono_class_array_element_size (eclass);
6691 mono_class_setup_supertypes (class);
6693 if (eclass->generic_class)
6694 mono_class_init (eclass);
6695 if (!eclass->size_inited)
6696 mono_class_setup_fields (eclass);
6697 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6698 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6700 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6704 if (eclass->enumtype)
6705 class->cast_class = eclass->element_class;
6707 class->cast_class = eclass;
6709 switch (class->cast_class->byval_arg.type) {
6711 class->cast_class = mono_defaults.byte_class;
6714 class->cast_class = mono_defaults.int16_class;
6717 #if SIZEOF_VOID_P == 4
6721 class->cast_class = mono_defaults.int32_class;
6724 #if SIZEOF_VOID_P == 8
6728 class->cast_class = mono_defaults.int64_class;
6734 class->element_class = eclass;
6736 if ((rank > 1) || bounded) {
6737 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6738 class->byval_arg.type = MONO_TYPE_ARRAY;
6739 class->byval_arg.data.array = at;
6740 at->eklass = eclass;
6742 /* FIXME: complete.... */
6744 class->byval_arg.type = MONO_TYPE_SZARRAY;
6745 class->byval_arg.data.klass = eclass;
6747 class->this_arg = class->byval_arg;
6748 class->this_arg.byref = 1;
6753 class->generic_container = eclass->generic_container;
6755 if (rank == 1 && !bounded) {
6756 MonoClass *prev_class;
6758 mono_mutex_lock (&image->szarray_cache_lock);
6759 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6761 /* Someone got in before us */
6764 g_hash_table_insert (image->szarray_cache, eclass, class);
6765 mono_mutex_unlock (&image->szarray_cache_lock);
6767 list = g_slist_append (rootlist, class);
6768 g_hash_table_insert (image->array_cache, eclass, list);
6771 mono_loader_unlock ();
6773 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6779 * mono_array_class_get:
6780 * @element_class: element class
6781 * @rank: the dimension of the array class
6783 * Returns: a class object describing the array with element type @element_type and
6787 mono_array_class_get (MonoClass *eclass, guint32 rank)
6789 return mono_bounded_array_class_get (eclass, rank, FALSE);
6793 * mono_class_instance_size:
6796 * Returns: the size of an object instance
6799 mono_class_instance_size (MonoClass *klass)
6801 if (!klass->size_inited)
6802 mono_class_init (klass);
6804 return klass->instance_size;
6808 * mono_class_min_align:
6811 * Returns: minimm alignment requirements
6814 mono_class_min_align (MonoClass *klass)
6816 if (!klass->size_inited)
6817 mono_class_init (klass);
6819 return klass->min_align;
6823 * mono_class_value_size:
6826 * This function is used for value types, and return the
6827 * space and the alignment to store that kind of value object.
6829 * Returns: the size of a value of kind @klass
6832 mono_class_value_size (MonoClass *klass, guint32 *align)
6836 /* fixme: check disable, because we still have external revereces to
6837 * mscorlib and Dummy Objects
6839 /*g_assert (klass->valuetype);*/
6841 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6844 *align = klass->min_align;
6850 * mono_class_data_size:
6853 * Returns: the size of the static class data
6856 mono_class_data_size (MonoClass *klass)
6859 mono_class_init (klass);
6860 /* This can happen with dynamically created types */
6861 if (!klass->fields_inited)
6862 mono_class_setup_fields_locking (klass);
6864 /* in arrays, sizes.class_size is unioned with element_size
6865 * and arrays have no static fields
6869 return klass->sizes.class_size;
6873 * Auxiliary routine to mono_class_get_field
6875 * Takes a field index instead of a field token.
6877 static MonoClassField *
6878 mono_class_get_field_idx (MonoClass *class, int idx)
6880 mono_class_setup_fields_locking (class);
6881 if (class->exception_type)
6885 if (class->image->uncompressed_metadata) {
6887 * class->field.first points to the FieldPtr table, while idx points into the
6888 * Field table, so we have to do a search.
6890 /*FIXME this is broken for types with multiple fields with the same name.*/
6891 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6894 for (i = 0; i < class->field.count; ++i)
6895 if (mono_field_get_name (&class->fields [i]) == name)
6896 return &class->fields [i];
6897 g_assert_not_reached ();
6899 if (class->field.count) {
6900 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6901 return &class->fields [idx - class->field.first];
6905 class = class->parent;
6911 * mono_class_get_field:
6912 * @class: the class to lookup the field.
6913 * @field_token: the field token
6915 * Returns: A MonoClassField representing the type and offset of
6916 * the field, or a NULL value if the field does not belong to this
6920 mono_class_get_field (MonoClass *class, guint32 field_token)
6922 int idx = mono_metadata_token_index (field_token);
6924 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6926 return mono_class_get_field_idx (class, idx - 1);
6930 * mono_class_get_field_from_name:
6931 * @klass: the class to lookup the field.
6932 * @name: the field name
6934 * Search the class @klass and it's parents for a field with the name @name.
6936 * Returns: the MonoClassField pointer of the named field or NULL
6939 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6941 return mono_class_get_field_from_name_full (klass, name, NULL);
6945 * mono_class_get_field_from_name_full:
6946 * @klass: the class to lookup the field.
6947 * @name: the field name
6948 * @type: the type of the fields. This optional.
6950 * Search the class @klass and it's parents for a field with the name @name and type @type.
6952 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6953 * of its generic type definition.
6955 * Returns: the MonoClassField pointer of the named field or NULL
6958 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6962 mono_class_setup_fields_locking (klass);
6963 if (klass->exception_type)
6967 for (i = 0; i < klass->field.count; ++i) {
6968 MonoClassField *field = &klass->fields [i];
6970 if (strcmp (name, mono_field_get_name (field)) != 0)
6974 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6975 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6980 klass = klass->parent;
6986 * mono_class_get_field_token:
6987 * @field: the field we need the token of
6989 * Get the token of a field. Note that the tokesn is only valid for the image
6990 * the field was loaded from. Don't use this function for fields in dynamic types.
6992 * Returns: the token representing the field in the image it was loaded from.
6995 mono_class_get_field_token (MonoClassField *field)
6997 MonoClass *klass = field->parent;
7000 mono_class_setup_fields_locking (klass);
7005 for (i = 0; i < klass->field.count; ++i) {
7006 if (&klass->fields [i] == field) {
7007 int idx = klass->field.first + i + 1;
7009 if (klass->image->uncompressed_metadata)
7010 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7011 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7014 klass = klass->parent;
7017 g_assert_not_reached ();
7022 mono_field_get_index (MonoClassField *field)
7024 int index = field - field->parent->fields;
7026 g_assert (index >= 0 && index < field->parent->field.count);
7032 * mono_class_get_field_default_value:
7034 * Return the default value of the field as a pointer into the metadata blob.
7037 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7040 guint32 constant_cols [MONO_CONSTANT_SIZE];
7042 MonoClass *klass = field->parent;
7044 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7046 if (!klass->ext || !klass->ext->field_def_values) {
7047 MonoFieldDefaultValue *def_values;
7049 mono_class_alloc_ext (klass);
7051 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7053 mono_image_lock (klass->image);
7054 mono_memory_barrier ();
7055 if (!klass->ext->field_def_values)
7056 klass->ext->field_def_values = def_values;
7057 mono_image_unlock (klass->image);
7060 field_index = mono_field_get_index (field);
7062 if (!klass->ext->field_def_values [field_index].data) {
7063 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7067 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7069 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7070 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7071 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7074 *def_type = klass->ext->field_def_values [field_index].def_type;
7075 return klass->ext->field_def_values [field_index].data;
7079 mono_property_get_index (MonoProperty *prop)
7081 int index = prop - prop->parent->ext->properties;
7083 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7089 * mono_class_get_property_default_value:
7091 * Return the default value of the field as a pointer into the metadata blob.
7094 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7097 guint32 constant_cols [MONO_CONSTANT_SIZE];
7098 MonoClass *klass = property->parent;
7100 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7102 * We don't cache here because it is not used by C# so it's quite rare, but
7103 * we still do the lookup in klass->ext because that is where the data
7104 * is stored for dynamic assemblies.
7107 if (image_is_dynamic (klass->image)) {
7108 int prop_index = mono_property_get_index (property);
7109 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7110 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7111 return klass->ext->prop_def_values [prop_index].data;
7115 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7119 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7120 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7121 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7125 mono_class_get_event_token (MonoEvent *event)
7127 MonoClass *klass = event->parent;
7132 for (i = 0; i < klass->ext->event.count; ++i) {
7133 if (&klass->ext->events [i] == event)
7134 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7137 klass = klass->parent;
7140 g_assert_not_reached ();
7145 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7149 gpointer iter = NULL;
7150 while ((p = mono_class_get_properties (klass, &iter))) {
7151 if (! strcmp (name, p->name))
7154 klass = klass->parent;
7160 mono_class_get_property_token (MonoProperty *prop)
7162 MonoClass *klass = prop->parent;
7166 gpointer iter = NULL;
7167 while ((p = mono_class_get_properties (klass, &iter))) {
7168 if (&klass->ext->properties [i] == prop)
7169 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7173 klass = klass->parent;
7176 g_assert_not_reached ();
7181 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7183 const char *name, *nspace;
7184 if (image_is_dynamic (image))
7185 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7187 switch (type_token & 0xff000000){
7188 case MONO_TOKEN_TYPE_DEF: {
7189 guint32 cols [MONO_TYPEDEF_SIZE];
7190 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7191 guint tidx = mono_metadata_token_index (type_token);
7193 if (tidx > tt->rows)
7194 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7196 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7197 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7198 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7199 if (strlen (nspace) == 0)
7200 return g_strdup_printf ("%s", name);
7202 return g_strdup_printf ("%s.%s", nspace, name);
7205 case MONO_TOKEN_TYPE_REF: {
7207 guint32 cols [MONO_TYPEREF_SIZE];
7208 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7209 guint tidx = mono_metadata_token_index (type_token);
7212 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7214 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7215 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7216 mono_error_cleanup (&error);
7220 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7221 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7222 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7223 if (strlen (nspace) == 0)
7224 return g_strdup_printf ("%s", name);
7226 return g_strdup_printf ("%s.%s", nspace, name);
7229 case MONO_TOKEN_TYPE_SPEC:
7230 return g_strdup_printf ("Typespec 0x%08x", type_token);
7232 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7237 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7239 if (image_is_dynamic (image))
7240 return g_strdup_printf ("DynamicAssembly %s", image->name);
7242 switch (type_token & 0xff000000){
7243 case MONO_TOKEN_TYPE_DEF:
7244 if (image->assembly)
7245 return mono_stringify_assembly_name (&image->assembly->aname);
7246 else if (image->assembly_name)
7247 return g_strdup (image->assembly_name);
7248 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7249 case MONO_TOKEN_TYPE_REF: {
7251 MonoAssemblyName aname;
7252 guint32 cols [MONO_TYPEREF_SIZE];
7253 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7254 guint32 idx = mono_metadata_token_index (type_token);
7257 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7259 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7260 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7261 mono_error_cleanup (&error);
7264 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7266 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7267 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7268 case MONO_RESOLUTION_SCOPE_MODULE:
7270 return g_strdup ("");
7271 case MONO_RESOLUTION_SCOPE_MODULEREF:
7273 return g_strdup ("");
7274 case MONO_RESOLUTION_SCOPE_TYPEREF:
7276 return g_strdup ("");
7277 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7278 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7279 return mono_stringify_assembly_name (&aname);
7281 g_assert_not_reached ();
7285 case MONO_TOKEN_TYPE_SPEC:
7287 return g_strdup ("");
7289 g_assert_not_reached ();
7296 * mono_class_get_full:
7297 * @image: the image where the class resides
7298 * @type_token: the token for the class
7299 * @context: the generic context used to evaluate generic instantiations in
7300 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7302 * Returns: the MonoClass that represents @type_token in @image
7305 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7309 class = mono_class_get_checked (image, type_token, &error);
7311 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7312 class = mono_class_inflate_generic_class_checked (class, context, &error);
7314 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7320 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7324 mono_error_init (error);
7325 class = mono_class_get_checked (image, type_token, error);
7327 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7328 class = mono_class_inflate_generic_class_checked (class, context, error);
7333 * mono_class_get_checked:
7334 * @image: the image where the class resides
7335 * @type_token: the token for the class
7336 * @error: error object to return any error
7338 * Returns: the MonoClass that represents @type_token in @image
7341 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7343 MonoClass *class = NULL;
7345 mono_error_init (error);
7347 if (image_is_dynamic (image)) {
7348 int table = mono_metadata_token_table (type_token);
7350 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7351 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7354 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7358 switch (type_token & 0xff000000){
7359 case MONO_TOKEN_TYPE_DEF:
7360 class = mono_class_create_from_typedef (image, type_token, error);
7362 case MONO_TOKEN_TYPE_REF:
7363 class = mono_class_from_typeref_checked (image, type_token, error);
7365 case MONO_TOKEN_TYPE_SPEC:
7366 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7369 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7373 /* Generic case, should be avoided for when a better error is possible. */
7374 if (!class && mono_error_ok (error)) {
7375 char *name = mono_class_name_from_token (image, type_token);
7376 char *assembly = mono_assembly_name_from_token (image, type_token);
7377 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7385 * mono_type_get_checked:
7386 * @image: the image where the type resides
7387 * @type_token: the token for the type
7388 * @context: the generic context used to evaluate generic instantiations in
7389 * @error: Error handling context
7391 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7393 * Returns: the MonoType that represents @type_token in @image
7396 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7398 MonoType *type = NULL;
7399 gboolean inflated = FALSE;
7401 mono_error_init (error);
7403 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7404 if (image_is_dynamic (image))
7405 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7407 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7408 MonoClass *class = mono_class_get_checked (image, type_token, error);
7411 g_assert (!mono_loader_get_last_error ());
7416 return mono_class_get_type (class);
7419 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7422 g_assert (!mono_loader_get_last_error ());
7427 MonoType *tmp = type;
7428 type = mono_class_get_type (mono_class_from_mono_type (type));
7429 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7430 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7431 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7433 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7435 if (type->type != tmp->type)
7438 mono_metadata_free_type (tmp);
7445 mono_class_get (MonoImage *image, guint32 type_token)
7447 return mono_class_get_full (image, type_token, NULL);
7451 * mono_image_init_name_cache:
7453 * Initializes the class name cache stored in image->name_cache.
7455 * LOCKING: Acquires the corresponding image lock.
7458 mono_image_init_name_cache (MonoImage *image)
7460 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7461 guint32 cols [MONO_TYPEDEF_SIZE];
7464 guint32 i, visib, nspace_index;
7465 GHashTable *name_cache2, *nspace_table;
7467 mono_image_lock (image);
7469 if (image->name_cache) {
7470 mono_image_unlock (image);
7474 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7476 if (image_is_dynamic (image)) {
7477 mono_image_unlock (image);
7481 /* Temporary hash table to avoid lookups in the nspace_table */
7482 name_cache2 = g_hash_table_new (NULL, NULL);
7484 for (i = 1; i <= t->rows; ++i) {
7485 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7486 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7488 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7489 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7491 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7493 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7494 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7496 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7497 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7498 if (!nspace_table) {
7499 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7500 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7501 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7504 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7507 /* Load type names from EXPORTEDTYPES table */
7509 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7510 guint32 cols [MONO_EXP_TYPE_SIZE];
7513 for (i = 0; i < t->rows; ++i) {
7514 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7515 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7516 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7518 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7519 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7520 if (!nspace_table) {
7521 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7522 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7523 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7526 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7530 g_hash_table_destroy (name_cache2);
7531 mono_image_unlock (image);
7534 /*FIXME Only dynamic assemblies should allow this operation.*/
7536 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7537 const char *name, guint32 index)
7539 GHashTable *nspace_table;
7540 GHashTable *name_cache;
7543 mono_image_lock (image);
7545 if (!image->name_cache)
7546 mono_image_init_name_cache (image);
7548 name_cache = image->name_cache;
7549 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7550 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7551 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7554 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7555 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7557 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7559 mono_image_unlock (image);
7568 find_nocase (gpointer key, gpointer value, gpointer user_data)
7570 char *name = (char*)key;
7571 FindUserData *data = (FindUserData*)user_data;
7573 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7574 data->value = value;
7578 * mono_class_from_name_case:
7579 * @image: The MonoImage where the type is looked up in
7580 * @name_space: the type namespace
7581 * @name: the type short name.
7582 * @deprecated: use the _checked variant
7584 * Obtains a MonoClass with a given namespace and a given name which
7585 * is located in the given MonoImage. The namespace and name
7586 * lookups are case insensitive.
7589 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7592 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7593 g_assert (!mono_error_ok (&error));
7598 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7600 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7601 guint32 cols [MONO_TYPEDEF_SIZE];
7606 mono_error_init (error);
7608 if (image_is_dynamic (image)) {
7610 FindUserData user_data;
7612 mono_image_lock (image);
7614 if (!image->name_cache)
7615 mono_image_init_name_cache (image);
7617 user_data.key = name_space;
7618 user_data.value = NULL;
7619 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7621 if (user_data.value) {
7622 GHashTable *nspace_table = (GHashTable*)user_data.value;
7624 user_data.key = name;
7625 user_data.value = NULL;
7627 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7629 if (user_data.value)
7630 token = GPOINTER_TO_UINT (user_data.value);
7633 mono_image_unlock (image);
7636 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7642 /* add a cache if needed */
7643 for (i = 1; i <= t->rows; ++i) {
7644 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7645 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7647 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7648 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7650 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7652 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7653 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7654 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7655 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7661 return_nested_in (MonoClass *class, char *nested)
7664 char *s = strchr (nested, '/');
7665 gpointer iter = NULL;
7672 while ((found = mono_class_get_nested_types (class, &iter))) {
7673 if (strcmp (found->name, nested) == 0) {
7675 return return_nested_in (found, s);
7683 search_modules (MonoImage *image, const char *name_space, const char *name)
7685 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7686 MonoImage *file_image;
7691 * The EXPORTEDTYPES table only contains public types, so have to search the
7693 * Note: image->modules contains the contents of the MODULEREF table, while
7694 * the real module list is in the FILE table.
7696 for (i = 0; i < file_table->rows; i++) {
7697 guint32 cols [MONO_FILE_SIZE];
7698 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7699 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7702 file_image = mono_image_load_file_for_image (image, i + 1);
7704 class = mono_class_from_name (file_image, name_space, name);
7714 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7716 GHashTable *nspace_table;
7717 MonoImage *loaded_image;
7724 mono_error_init (error);
7726 if ((nested = strchr (name, '/'))) {
7727 int pos = nested - name;
7728 int len = strlen (name);
7731 memcpy (buf, name, len + 1);
7733 nested = buf + pos + 1;
7737 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7738 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7739 gboolean res = get_class_from_name (image, name_space, name, &class);
7742 class = search_modules (image, name_space, name);
7744 return class ? return_nested_in (class, nested) : NULL;
7750 mono_image_lock (image);
7752 if (!image->name_cache)
7753 mono_image_init_name_cache (image);
7755 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7758 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7760 mono_image_unlock (image);
7762 if (!token && image_is_dynamic (image) && image->modules) {
7763 /* Search modules as well */
7764 for (i = 0; i < image->module_count; ++i) {
7765 MonoImage *module = image->modules [i];
7767 class = mono_class_from_name (module, name_space, name);
7774 class = search_modules (image, name_space, name);
7782 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7783 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7784 guint32 cols [MONO_EXP_TYPE_SIZE];
7787 idx = mono_metadata_token_index (token);
7789 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7791 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7792 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7793 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7796 class = mono_class_from_name (loaded_image, name_space, name);
7798 return return_nested_in (class, nested);
7800 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7801 guint32 assembly_idx;
7803 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7805 mono_assembly_load_reference (image, assembly_idx - 1);
7806 g_assert (image->references [assembly_idx - 1]);
7807 if (image->references [assembly_idx - 1] == (gpointer)-1)
7810 /* FIXME: Cycle detection */
7811 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7813 g_error ("not yet implemented");
7817 token = MONO_TOKEN_TYPE_DEF | token;
7819 class = mono_class_get_checked (image, token, error);
7821 return return_nested_in (class, nested);
7826 * mono_class_from_name:
7827 * @image: The MonoImage where the type is looked up in
7828 * @name_space: the type namespace
7829 * @name: the type short name.
7831 * Obtains a MonoClass with a given namespace and a given name which
7832 * is located in the given MonoImage.
7834 * To reference nested classes, use the "/" character as a separator.
7835 * For example use "Foo/Bar" to reference the class Bar that is nested
7836 * inside Foo, like this: "class Foo { class Bar {} }".
7839 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7844 klass = mono_class_from_name_checked (image, name_space, name, &error);
7845 if (!mono_error_ok (&error)) {
7846 mono_loader_set_error_from_mono_error (&error);
7847 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7853 * mono_class_is_subclass_of:
7854 * @klass: class to probe if it is a subclass of another one
7855 * @klassc: the class we suspect is the base class
7856 * @check_interfaces: whether we should perform interface checks
7858 * This method determines whether @klass is a subclass of @klassc.
7860 * If the @check_interfaces flag is set, then if @klassc is an interface
7861 * this method return true if the @klass implements the interface or
7862 * if @klass is an interface, if one of its base classes is @klass.
7864 * If @check_interfaces is false then, then if @klass is not an interface
7865 * then it returns true if the @klass is a subclass of @klassc.
7867 * if @klass is an interface and @klassc is System.Object, then this function
7872 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7873 gboolean check_interfaces)
7875 /*FIXME test for interfaces with variant generic arguments*/
7877 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7878 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7880 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7883 for (i = 0; i < klass->interface_count; i ++) {
7884 MonoClass *ic = klass->interfaces [i];
7889 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7894 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7897 if (klassc == mono_defaults.object_class)
7904 mono_type_is_generic_argument (MonoType *type)
7906 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7910 mono_class_has_variant_generic_params (MonoClass *klass)
7913 MonoGenericContainer *container;
7915 if (!klass->generic_class)
7918 container = klass->generic_class->container_class->generic_container;
7920 for (i = 0; i < container->type_argc; ++i)
7921 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7928 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7930 if (target == candidate)
7933 if (check_for_reference_conv &&
7934 mono_type_is_generic_argument (&target->byval_arg) &&
7935 mono_type_is_generic_argument (&candidate->byval_arg)) {
7936 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7937 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7939 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7942 if (!mono_class_is_assignable_from (target, candidate))
7948 * @container the generic container from the GTD
7949 * @klass: the class to be assigned to
7950 * @oklass: the source class
7952 * Both klass and oklass must be instances of the same generic interface.
7953 * Return true if @klass can be assigned to a @klass variable
7956 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7959 MonoType **klass_argv, **oklass_argv;
7960 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7961 MonoGenericContainer *container = klass_gtd->generic_container;
7963 if (klass == oklass)
7966 /*Viable candidates are instances of the same generic interface*/
7967 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7970 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7971 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7973 for (j = 0; j < container->type_argc; ++j) {
7974 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7975 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7977 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7981 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7982 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7984 if (param1_class != param2_class) {
7985 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7986 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7988 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7989 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7999 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8001 MonoGenericParam *gparam, *ogparam;
8002 MonoGenericParamInfo *tinfo, *cinfo;
8003 MonoClass **candidate_class;
8004 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8007 if (target == candidate)
8009 if (target->byval_arg.type != candidate->byval_arg.type)
8012 gparam = target->byval_arg.data.generic_param;
8013 ogparam = candidate->byval_arg.data.generic_param;
8014 tinfo = mono_generic_param_info (gparam);
8015 cinfo = mono_generic_param_info (ogparam);
8017 class_constraint_satisfied = FALSE;
8018 valuetype_constraint_satisfied = FALSE;
8020 /*candidate must have a super set of target's special constraints*/
8021 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8022 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8024 if (cinfo->constraints) {
8025 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8026 MonoClass *cc = *candidate_class;
8028 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8029 class_constraint_satisfied = TRUE;
8030 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8031 valuetype_constraint_satisfied = TRUE;
8034 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8035 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8037 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8039 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8041 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8042 valuetype_constraint_satisfied)) {
8047 /*candidate type constraints must be a superset of target's*/
8048 if (tinfo->constraints) {
8049 MonoClass **target_class;
8050 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8051 MonoClass *tc = *target_class;
8054 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8055 * check it's constraints since it satisfy the constraint by itself.
8057 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8060 if (!cinfo->constraints)
8063 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8064 MonoClass *cc = *candidate_class;
8066 if (mono_class_is_assignable_from (tc, cc))
8070 * This happens when we have the following:
8072 * Bar<K> where K : IFace
8073 * Foo<T, U> where T : U where U : IFace
8075 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8078 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8079 if (mono_gparam_is_assignable_from (target, cc))
8083 if (!*candidate_class)
8088 /*candidate itself must have a constraint that satisfy target*/
8089 if (cinfo->constraints) {
8090 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8091 MonoClass *cc = *candidate_class;
8092 if (mono_class_is_assignable_from (target, cc))
8100 * mono_class_is_assignable_from:
8101 * @klass: the class to be assigned to
8102 * @oklass: the source class
8104 * Return: true if an instance of object oklass can be assigned to an
8105 * instance of object @klass
8108 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8110 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8112 mono_class_init (klass);
8114 if (!oklass->inited)
8115 mono_class_init (oklass);
8117 if (klass->exception_type || oklass->exception_type)
8120 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8121 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8123 return mono_gparam_is_assignable_from (klass, oklass);
8126 if (MONO_CLASS_IS_INTERFACE (klass)) {
8127 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8128 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8129 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8133 for (i = 0; constraints [i]; ++i) {
8134 if (mono_class_is_assignable_from (klass, constraints [i]))
8142 /* interface_offsets might not be set for dynamic classes */
8143 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8145 * oklass might be a generic type parameter but they have
8146 * interface_offsets set.
8148 return mono_reflection_call_is_assignable_to (oklass, klass);
8149 if (!oklass->interface_bitmap)
8150 /* Happens with generic instances of not-yet created dynamic types */
8152 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8155 if (mono_class_has_variant_generic_params (klass)) {
8158 mono_class_setup_interfaces (oklass, &error);
8159 if (!mono_error_ok (&error)) {
8160 mono_error_cleanup (&error);
8164 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8165 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8166 MonoClass *iface = oklass->interfaces_packed [i];
8168 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8173 } else if (klass->delegate) {
8174 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8176 }else if (klass->rank) {
8177 MonoClass *eclass, *eoclass;
8179 if (oklass->rank != klass->rank)
8182 /* vectors vs. one dimensional arrays */
8183 if (oklass->byval_arg.type != klass->byval_arg.type)
8186 eclass = klass->cast_class;
8187 eoclass = oklass->cast_class;
8190 * a is b does not imply a[] is b[] when a is a valuetype, and
8191 * b is a reference type.
8194 if (eoclass->valuetype) {
8195 if ((eclass == mono_defaults.enum_class) ||
8196 (eclass == mono_defaults.enum_class->parent) ||
8197 (eclass == mono_defaults.object_class))
8201 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8202 } else if (mono_class_is_nullable (klass)) {
8203 if (mono_class_is_nullable (oklass))
8204 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8206 return mono_class_is_assignable_from (klass->cast_class, oklass);
8207 } else if (klass == mono_defaults.object_class)
8210 return mono_class_has_parent (oklass, klass);
8213 /*Check if @oklass is variant compatible with @klass.*/
8215 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8218 MonoType **klass_argv, **oklass_argv;
8219 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8220 MonoGenericContainer *container = klass_gtd->generic_container;
8222 /*Viable candidates are instances of the same generic interface*/
8223 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8226 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8227 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8229 for (j = 0; j < container->type_argc; ++j) {
8230 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8231 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8233 if (param1_class->valuetype != param2_class->valuetype)
8237 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8238 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8240 if (param1_class != param2_class) {
8241 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8242 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8244 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8245 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8253 /*Check if @candidate implements the interface @target*/
8255 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8259 gboolean is_variant = mono_class_has_variant_generic_params (target);
8261 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8262 if (mono_class_is_variant_compatible_slow (target, candidate))
8267 if (candidate == target)
8270 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8271 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8272 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8274 if (tb && tb->interfaces) {
8275 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8276 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8277 MonoClass *iface_class;
8279 /* we can't realize the type here since it can do pretty much anything. */
8282 iface_class = mono_class_from_mono_type (iface->type);
8283 if (iface_class == target)
8285 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8287 if (mono_class_implement_interface_slow (target, iface_class))
8292 /*setup_interfaces don't mono_class_init anything*/
8293 /*FIXME this doesn't handle primitive type arrays.
8294 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8295 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8297 mono_class_setup_interfaces (candidate, &error);
8298 if (!mono_error_ok (&error)) {
8299 mono_error_cleanup (&error);
8303 for (i = 0; i < candidate->interface_count; ++i) {
8304 if (candidate->interfaces [i] == target)
8307 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8310 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8314 candidate = candidate->parent;
8315 } while (candidate);
8321 * Check if @oklass can be assigned to @klass.
8322 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8325 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8327 if (candidate == target)
8329 if (target == mono_defaults.object_class)
8332 if (mono_class_has_parent (candidate, target))
8335 /*If target is not an interface there is no need to check them.*/
8336 if (MONO_CLASS_IS_INTERFACE (target))
8337 return mono_class_implement_interface_slow (target, candidate);
8339 if (target->delegate && mono_class_has_variant_generic_params (target))
8340 return mono_class_is_variant_compatible (target, candidate, FALSE);
8343 MonoClass *eclass, *eoclass;
8345 if (target->rank != candidate->rank)
8348 /* vectors vs. one dimensional arrays */
8349 if (target->byval_arg.type != candidate->byval_arg.type)
8352 eclass = target->cast_class;
8353 eoclass = candidate->cast_class;
8356 * a is b does not imply a[] is b[] when a is a valuetype, and
8357 * b is a reference type.
8360 if (eoclass->valuetype) {
8361 if ((eclass == mono_defaults.enum_class) ||
8362 (eclass == mono_defaults.enum_class->parent) ||
8363 (eclass == mono_defaults.object_class))
8367 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8369 /*FIXME properly handle nullables */
8370 /*FIXME properly handle (M)VAR */
8375 * mono_class_get_cctor:
8376 * @klass: A MonoClass pointer
8378 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8381 mono_class_get_cctor (MonoClass *klass)
8383 MonoCachedClassInfo cached_info;
8385 if (image_is_dynamic (klass->image)) {
8387 * has_cctor is not set for these classes because mono_class_init () is
8390 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8393 if (!klass->has_cctor)
8396 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8398 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8399 if (!mono_error_ok (&error))
8400 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8404 if (klass->generic_class && !klass->methods)
8405 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8407 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8411 * mono_class_get_finalizer:
8412 * @klass: The MonoClass pointer
8414 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8417 mono_class_get_finalizer (MonoClass *klass)
8419 MonoCachedClassInfo cached_info;
8422 mono_class_init (klass);
8423 if (!mono_class_has_finalizer (klass))
8426 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8428 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8429 if (!mono_error_ok (&error))
8430 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8433 mono_class_setup_vtable (klass);
8434 return klass->vtable [finalize_slot];
8439 * mono_class_needs_cctor_run:
8440 * @klass: the MonoClass pointer
8441 * @caller: a MonoMethod describing the caller
8443 * Determines whenever the class has a static constructor and whenever it
8444 * needs to be called when executing CALLER.
8447 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8451 method = mono_class_get_cctor (klass);
8453 return (method == caller) ? FALSE : TRUE;
8459 * mono_class_array_element_size:
8462 * Returns: the number of bytes an element of type @klass
8463 * uses when stored into an array.
8466 mono_class_array_element_size (MonoClass *klass)
8468 MonoType *type = &klass->byval_arg;
8471 switch (type->type) {
8474 case MONO_TYPE_BOOLEAN:
8478 case MONO_TYPE_CHAR:
8487 case MONO_TYPE_CLASS:
8488 case MONO_TYPE_STRING:
8489 case MONO_TYPE_OBJECT:
8490 case MONO_TYPE_SZARRAY:
8491 case MONO_TYPE_ARRAY:
8492 return sizeof (gpointer);
8497 case MONO_TYPE_VALUETYPE:
8498 if (type->data.klass->enumtype) {
8499 type = mono_class_enum_basetype (type->data.klass);
8500 klass = klass->element_class;
8503 return mono_class_instance_size (klass) - sizeof (MonoObject);
8504 case MONO_TYPE_GENERICINST:
8505 type = &type->data.generic_class->container_class->byval_arg;
8508 case MONO_TYPE_MVAR: {
8511 return mono_type_size (type, &align);
8513 case MONO_TYPE_VOID:
8517 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8523 * mono_array_element_size:
8524 * @ac: pointer to a #MonoArrayClass
8526 * Returns: the size of single array element.
8529 mono_array_element_size (MonoClass *ac)
8531 g_assert (ac->rank);
8532 return ac->sizes.element_size;
8536 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8537 MonoGenericContext *context)
8540 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8541 g_assert (mono_error_ok (&error));
8546 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8547 MonoGenericContext *context, MonoError *error)
8549 mono_error_init (error);
8551 if (image_is_dynamic (image)) {
8552 MonoClass *tmp_handle_class;
8553 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8555 g_assert (tmp_handle_class);
8557 *handle_class = tmp_handle_class;
8559 if (tmp_handle_class == mono_defaults.typehandle_class)
8560 return &((MonoClass*)obj)->byval_arg;
8565 switch (token & 0xff000000) {
8566 case MONO_TOKEN_TYPE_DEF:
8567 case MONO_TOKEN_TYPE_REF:
8568 case MONO_TOKEN_TYPE_SPEC: {
8571 *handle_class = mono_defaults.typehandle_class;
8572 type = mono_type_get_checked (image, token, context, error);
8576 mono_class_init (mono_class_from_mono_type (type));
8577 /* We return a MonoType* as handle */
8580 case MONO_TOKEN_FIELD_DEF: {
8582 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8584 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8588 *handle_class = mono_defaults.fieldhandle_class;
8589 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8593 mono_class_init (class);
8594 return mono_class_get_field (class, token);
8596 case MONO_TOKEN_METHOD_DEF:
8597 case MONO_TOKEN_METHOD_SPEC: {
8599 meth = mono_get_method_checked (image, token, NULL, context, error);
8601 *handle_class = mono_defaults.methodhandle_class;
8607 case MONO_TOKEN_MEMBER_REF: {
8608 guint32 cols [MONO_MEMBERREF_SIZE];
8610 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8611 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8612 mono_metadata_decode_blob_size (sig, &sig);
8613 if (*sig == 0x6) { /* it's a field */
8615 MonoClassField *field;
8616 field = mono_field_from_token_checked (image, token, &klass, context, error);
8618 *handle_class = mono_defaults.fieldhandle_class;
8622 meth = mono_get_method_checked (image, token, NULL, context, error);
8624 *handle_class = mono_defaults.methodhandle_class;
8629 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8635 * This function might need to call runtime functions so it can't be part
8636 * of the metadata library.
8638 static MonoLookupDynamicToken lookup_dynamic = NULL;
8641 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8643 lookup_dynamic = func;
8647 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8649 MonoClass *handle_class;
8651 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8655 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8657 return lookup_dynamic (image, token, valid_token, handle_class, context);
8660 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8663 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8665 get_cached_class_info = func;
8669 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8671 if (!get_cached_class_info)
8674 return get_cached_class_info (klass, res);
8678 mono_install_get_class_from_name (MonoGetClassFromName func)
8680 get_class_from_name = func;
8684 mono_class_get_image (MonoClass *klass)
8686 return klass->image;
8690 * mono_class_get_element_class:
8691 * @klass: the MonoClass to act on
8693 * Returns: the element class of an array or an enumeration.
8696 mono_class_get_element_class (MonoClass *klass)
8698 return klass->element_class;
8702 * mono_class_is_valuetype:
8703 * @klass: the MonoClass to act on
8705 * Returns: true if the MonoClass represents a ValueType.
8708 mono_class_is_valuetype (MonoClass *klass)
8710 return klass->valuetype;
8714 * mono_class_is_enum:
8715 * @klass: the MonoClass to act on
8717 * Returns: true if the MonoClass represents an enumeration.
8720 mono_class_is_enum (MonoClass *klass)
8722 return klass->enumtype;
8726 * mono_class_enum_basetype:
8727 * @klass: the MonoClass to act on
8729 * Returns: the underlying type representation for an enumeration.
8732 mono_class_enum_basetype (MonoClass *klass)
8734 if (klass->element_class == klass)
8735 /* SRE or broken types */
8738 return &klass->element_class->byval_arg;
8742 * mono_class_get_parent
8743 * @klass: the MonoClass to act on
8745 * Returns: the parent class for this class.
8748 mono_class_get_parent (MonoClass *klass)
8750 return klass->parent;
8754 * mono_class_get_nesting_type;
8755 * @klass: the MonoClass to act on
8757 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8760 mono_class_get_nesting_type (MonoClass *klass)
8762 return klass->nested_in;
8766 * mono_class_get_rank:
8767 * @klass: the MonoClass to act on
8769 * Returns: the rank for the array (the number of dimensions).
8772 mono_class_get_rank (MonoClass *klass)
8778 * mono_class_get_flags:
8779 * @klass: the MonoClass to act on
8781 * The type flags from the TypeDef table from the metadata.
8782 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8785 * Returns: the flags from the TypeDef table.
8788 mono_class_get_flags (MonoClass *klass)
8790 return klass->flags;
8794 * mono_class_get_name
8795 * @klass: the MonoClass to act on
8797 * Returns: the name of the class.
8800 mono_class_get_name (MonoClass *klass)
8806 * mono_class_get_namespace:
8807 * @klass: the MonoClass to act on
8809 * Returns: the namespace of the class.
8812 mono_class_get_namespace (MonoClass *klass)
8814 return klass->name_space;
8818 * mono_class_get_type:
8819 * @klass: the MonoClass to act on
8821 * This method returns the internal Type representation for the class.
8823 * Returns: the MonoType from the class.
8826 mono_class_get_type (MonoClass *klass)
8828 return &klass->byval_arg;
8832 * mono_class_get_type_token
8833 * @klass: the MonoClass to act on
8835 * This method returns type token for the class.
8837 * Returns: the type token for the class.
8840 mono_class_get_type_token (MonoClass *klass)
8842 return klass->type_token;
8846 * mono_class_get_byref_type:
8847 * @klass: the MonoClass to act on
8852 mono_class_get_byref_type (MonoClass *klass)
8854 return &klass->this_arg;
8858 * mono_class_num_fields:
8859 * @klass: the MonoClass to act on
8861 * Returns: the number of static and instance fields in the class.
8864 mono_class_num_fields (MonoClass *klass)
8866 return klass->field.count;
8870 * mono_class_num_methods:
8871 * @klass: the MonoClass to act on
8873 * Returns: the number of methods in the class.
8876 mono_class_num_methods (MonoClass *klass)
8878 return klass->method.count;
8882 * mono_class_num_properties
8883 * @klass: the MonoClass to act on
8885 * Returns: the number of properties in the class.
8888 mono_class_num_properties (MonoClass *klass)
8890 mono_class_setup_properties (klass);
8892 return klass->ext->property.count;
8896 * mono_class_num_events:
8897 * @klass: the MonoClass to act on
8899 * Returns: the number of events in the class.
8902 mono_class_num_events (MonoClass *klass)
8904 mono_class_setup_events (klass);
8906 return klass->ext->event.count;
8910 * mono_class_get_fields:
8911 * @klass: the MonoClass to act on
8913 * This routine is an iterator routine for retrieving the fields in a class.
8915 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8916 * iterate over all of the elements. When no more values are
8917 * available, the return value is NULL.
8919 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8922 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8924 MonoClassField* field;
8928 mono_class_setup_fields_locking (klass);
8929 if (klass->exception_type)
8931 /* start from the first */
8932 if (klass->field.count) {
8933 return *iter = &klass->fields [0];
8941 if (field < &klass->fields [klass->field.count]) {
8942 return *iter = field;
8948 * mono_class_get_methods
8949 * @klass: the MonoClass to act on
8951 * This routine is an iterator routine for retrieving the fields in a class.
8953 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8954 * iterate over all of the elements. When no more values are
8955 * available, the return value is NULL.
8957 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8960 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8962 MonoMethod** method;
8966 mono_class_setup_methods (klass);
8969 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8970 * FIXME we should better report this error to the caller
8972 if (!klass->methods)
8974 /* start from the first */
8975 if (klass->method.count) {
8976 *iter = &klass->methods [0];
8977 return klass->methods [0];
8985 if (method < &klass->methods [klass->method.count]) {
8993 * mono_class_get_virtual_methods:
8995 * Iterate over the virtual methods of KLASS.
8997 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9000 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9002 MonoMethod** method;
9005 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9007 mono_class_setup_methods (klass);
9009 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9010 * FIXME we should better report this error to the caller
9012 if (!klass->methods)
9014 /* start from the first */
9015 method = &klass->methods [0];
9020 while (method < &klass->methods [klass->method.count]) {
9021 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9025 if (method < &klass->methods [klass->method.count]) {
9032 /* Search directly in metadata to avoid calling setup_methods () */
9033 MonoMethod *res = NULL;
9039 start_index = GPOINTER_TO_UINT (*iter);
9042 for (i = start_index; i < klass->method.count; ++i) {
9045 /* class->method.first points into the methodptr table */
9046 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9048 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9052 if (i < klass->method.count) {
9054 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9055 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9057 /* Add 1 here so the if (*iter) check fails */
9058 *iter = GUINT_TO_POINTER (i + 1);
9067 * mono_class_get_properties:
9068 * @klass: the MonoClass to act on
9070 * This routine is an iterator routine for retrieving the properties in a class.
9072 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9073 * iterate over all of the elements. When no more values are
9074 * available, the return value is NULL.
9076 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9079 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9081 MonoProperty* property;
9085 mono_class_setup_properties (klass);
9086 /* start from the first */
9087 if (klass->ext->property.count) {
9088 return *iter = &klass->ext->properties [0];
9096 if (property < &klass->ext->properties [klass->ext->property.count]) {
9097 return *iter = property;
9103 * mono_class_get_events:
9104 * @klass: the MonoClass to act on
9106 * This routine is an iterator routine for retrieving the properties in a class.
9108 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9109 * iterate over all of the elements. When no more values are
9110 * available, the return value is NULL.
9112 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9115 mono_class_get_events (MonoClass* klass, gpointer *iter)
9121 mono_class_setup_events (klass);
9122 /* start from the first */
9123 if (klass->ext->event.count) {
9124 return *iter = &klass->ext->events [0];
9132 if (event < &klass->ext->events [klass->ext->event.count]) {
9133 return *iter = event;
9139 * mono_class_get_interfaces
9140 * @klass: the MonoClass to act on
9142 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9144 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9145 * iterate over all of the elements. When no more values are
9146 * available, the return value is NULL.
9148 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9151 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9159 mono_class_init (klass);
9160 if (!klass->interfaces_inited) {
9161 mono_class_setup_interfaces (klass, &error);
9162 if (!mono_error_ok (&error)) {
9163 mono_error_cleanup (&error);
9167 /* start from the first */
9168 if (klass->interface_count) {
9169 *iter = &klass->interfaces [0];
9170 return klass->interfaces [0];
9178 if (iface < &klass->interfaces [klass->interface_count]) {
9186 setup_nested_types (MonoClass *klass)
9189 GList *classes, *nested_classes, *l;
9192 if (klass->nested_classes_inited)
9195 if (!klass->type_token)
9196 klass->nested_classes_inited = TRUE;
9198 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9202 guint32 cols [MONO_NESTED_CLASS_SIZE];
9203 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9204 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9205 if (!mono_error_ok (&error)) {
9206 /*FIXME don't swallow the error message*/
9207 mono_error_cleanup (&error);
9209 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9213 classes = g_list_prepend (classes, nclass);
9215 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9218 mono_class_alloc_ext (klass);
9220 nested_classes = NULL;
9221 for (l = classes; l; l = l->next)
9222 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9223 g_list_free (classes);
9225 mono_image_lock (klass->image);
9227 mono_memory_barrier ();
9228 if (!klass->nested_classes_inited) {
9229 klass->ext->nested_classes = nested_classes;
9230 mono_memory_barrier ();
9231 klass->nested_classes_inited = TRUE;
9234 mono_image_unlock (klass->image);
9238 * mono_class_get_nested_types
9239 * @klass: the MonoClass to act on
9241 * This routine is an iterator routine for retrieving the nested types of a class.
9242 * This works only if @klass is non-generic, or a generic type definition.
9244 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9245 * iterate over all of the elements. When no more values are
9246 * available, the return value is NULL.
9248 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9251 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9257 if (!klass->nested_classes_inited)
9258 setup_nested_types (klass);
9261 /* start from the first */
9262 if (klass->ext && klass->ext->nested_classes) {
9263 *iter = klass->ext->nested_classes;
9264 return klass->ext->nested_classes->data;
9266 /* no nested types */
9281 * mono_class_is_delegate
9282 * @klass: the MonoClass to act on
9284 * Returns: true if the MonoClass represents a System.Delegate.
9287 mono_class_is_delegate (MonoClass *klass)
9289 return klass->delegate;
9293 * mono_class_implements_interface
9294 * @klass: The MonoClass to act on
9295 * @interface: The interface to check if @klass implements.
9297 * Returns: true if @klass implements @interface.
9300 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9302 return mono_class_is_assignable_from (iface, klass);
9306 * mono_field_get_name:
9307 * @field: the MonoClassField to act on
9309 * Returns: the name of the field.
9312 mono_field_get_name (MonoClassField *field)
9318 * mono_field_get_type:
9319 * @field: the MonoClassField to act on
9321 * Returns: MonoType of the field.
9324 mono_field_get_type (MonoClassField *field)
9327 MonoType *type = mono_field_get_type_checked (field, &error);
9328 if (!mono_error_ok (&error)) {
9329 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9330 mono_error_cleanup (&error);
9337 * mono_field_get_type_checked:
9338 * @field: the MonoClassField to act on
9339 * @error: used to return any erro found while retrieving @field type
9341 * Returns: MonoType of the field.
9344 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9346 mono_error_init (error);
9348 mono_field_resolve_type (field, error);
9353 * mono_field_get_parent:
9354 * @field: the MonoClassField to act on
9356 * Returns: MonoClass where the field was defined.
9359 mono_field_get_parent (MonoClassField *field)
9361 return field->parent;
9365 * mono_field_get_flags;
9366 * @field: the MonoClassField to act on
9368 * The metadata flags for a field are encoded using the
9369 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9371 * Returns: the flags for the field.
9374 mono_field_get_flags (MonoClassField *field)
9377 return mono_field_resolve_flags (field);
9378 return field->type->attrs;
9382 * mono_field_get_offset;
9383 * @field: the MonoClassField to act on
9385 * Returns: the field offset.
9388 mono_field_get_offset (MonoClassField *field)
9390 return field->offset;
9394 mono_field_get_rva (MonoClassField *field)
9398 MonoClass *klass = field->parent;
9399 MonoFieldDefaultValue *field_def_values;
9401 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9403 if (!klass->ext || !klass->ext->field_def_values) {
9404 mono_class_alloc_ext (klass);
9406 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9408 mono_image_lock (klass->image);
9409 if (!klass->ext->field_def_values)
9410 klass->ext->field_def_values = field_def_values;
9411 mono_image_unlock (klass->image);
9414 field_index = mono_field_get_index (field);
9416 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9417 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9419 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9420 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9423 return klass->ext->field_def_values [field_index].data;
9427 * mono_field_get_data;
9428 * @field: the MonoClassField to act on
9430 * Returns: pointer to the metadata constant value or to the field
9431 * data if it has an RVA flag.
9434 mono_field_get_data (MonoClassField *field)
9436 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9437 MonoTypeEnum def_type;
9439 return mono_class_get_field_default_value (field, &def_type);
9440 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9441 return mono_field_get_rva (field);
9448 * mono_property_get_name:
9449 * @prop: the MonoProperty to act on
9451 * Returns: the name of the property
9454 mono_property_get_name (MonoProperty *prop)
9460 * mono_property_get_set_method
9461 * @prop: the MonoProperty to act on.
9463 * Returns: the setter method of the property (A MonoMethod)
9466 mono_property_get_set_method (MonoProperty *prop)
9472 * mono_property_get_get_method
9473 * @prop: the MonoProperty to act on.
9475 * Returns: the setter method of the property (A MonoMethod)
9478 mono_property_get_get_method (MonoProperty *prop)
9484 * mono_property_get_parent:
9485 * @prop: the MonoProperty to act on.
9487 * Returns: the MonoClass where the property was defined.
9490 mono_property_get_parent (MonoProperty *prop)
9492 return prop->parent;
9496 * mono_property_get_flags:
9497 * @prop: the MonoProperty to act on.
9499 * The metadata flags for a property are encoded using the
9500 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9502 * Returns: the flags for the property.
9505 mono_property_get_flags (MonoProperty *prop)
9511 * mono_event_get_name:
9512 * @event: the MonoEvent to act on
9514 * Returns: the name of the event.
9517 mono_event_get_name (MonoEvent *event)
9523 * mono_event_get_add_method:
9524 * @event: The MonoEvent to act on.
9526 * Returns: the @add' method for the event (a MonoMethod).
9529 mono_event_get_add_method (MonoEvent *event)
9535 * mono_event_get_remove_method:
9536 * @event: The MonoEvent to act on.
9538 * Returns: the @remove method for the event (a MonoMethod).
9541 mono_event_get_remove_method (MonoEvent *event)
9543 return event->remove;
9547 * mono_event_get_raise_method:
9548 * @event: The MonoEvent to act on.
9550 * Returns: the @raise method for the event (a MonoMethod).
9553 mono_event_get_raise_method (MonoEvent *event)
9555 return event->raise;
9559 * mono_event_get_parent:
9560 * @event: the MonoEvent to act on.
9562 * Returns: the MonoClass where the event is defined.
9565 mono_event_get_parent (MonoEvent *event)
9567 return event->parent;
9571 * mono_event_get_flags
9572 * @event: the MonoEvent to act on.
9574 * The metadata flags for an event are encoded using the
9575 * EVENT_* constants. See the tabledefs.h file for details.
9577 * Returns: the flags for the event.
9580 mono_event_get_flags (MonoEvent *event)
9582 return event->attrs;
9586 * mono_class_get_method_from_name:
9587 * @klass: where to look for the method
9588 * @name: name of the method
9589 * @param_count: number of parameters. -1 for any number.
9591 * Obtains a MonoMethod with a given name and number of parameters.
9592 * It only works if there are no multiple signatures for any given method name.
9595 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9597 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9601 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9603 MonoMethod *res = NULL;
9606 /* Search directly in the metadata to avoid calling setup_methods () */
9607 for (i = 0; i < klass->method.count; ++i) {
9609 guint32 cols [MONO_METHOD_SIZE];
9611 MonoMethodSignature *sig;
9613 /* class->method.first points into the methodptr table */
9614 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9616 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9617 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9619 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9622 if (param_count == -1) {
9626 sig = mono_method_signature_checked (method, &error);
9628 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9631 if (sig->param_count == param_count) {
9642 * mono_class_get_method_from_name_flags:
9643 * @klass: where to look for the method
9644 * @name_space: name of the method
9645 * @param_count: number of parameters. -1 for any number.
9646 * @flags: flags which must be set in the method
9648 * Obtains a MonoMethod with a given name and number of parameters.
9649 * It only works if there are no multiple signatures for any given method name.
9652 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9654 MonoMethod *res = NULL;
9657 mono_class_init (klass);
9659 if (klass->generic_class && !klass->methods) {
9660 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9663 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9664 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9669 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9670 mono_class_setup_methods (klass);
9672 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9673 See mono/tests/array_load_exception.il
9674 FIXME we should better report this error to the caller
9676 if (!klass->methods)
9678 for (i = 0; i < klass->method.count; ++i) {
9679 MonoMethod *method = klass->methods [i];
9681 if (method->name[0] == name [0] &&
9682 !strcmp (name, method->name) &&
9683 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9684 ((method->flags & flags) == flags)) {
9691 res = find_method_in_metadata (klass, name, param_count, flags);
9698 * mono_class_set_failure:
9699 * @klass: class in which the failure was detected
9700 * @ex_type: the kind of exception/error to be thrown (later)
9701 * @ex_data: exception data (specific to each type of exception/error)
9703 * Keep a detected failure informations in the class for later processing.
9704 * Note that only the first failure is kept.
9706 * LOCKING: Acquires the loader lock.
9709 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9711 if (klass->exception_type)
9714 mono_loader_lock ();
9715 klass->exception_type = ex_type;
9717 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9718 mono_loader_unlock ();
9724 * mono_class_get_exception_data:
9726 * Return the exception_data property of KLASS.
9728 * LOCKING: Acquires the loader lock.
9731 mono_class_get_exception_data (MonoClass *klass)
9733 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9737 * mono_classes_init:
9739 * Initialize the resources used by this module.
9742 mono_classes_init (void)
9744 mono_mutex_init (&classes_mutex);
9746 mono_counters_register ("Inflated methods size",
9747 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9748 mono_counters_register ("Inflated classes",
9749 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9750 mono_counters_register ("Inflated classes size",
9751 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9752 mono_counters_register ("MonoClass size",
9753 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9754 mono_counters_register ("MonoClassExt size",
9755 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9759 * mono_classes_cleanup:
9761 * Free the resources used by this module.
9764 mono_classes_cleanup (void)
9766 if (global_interface_bitset)
9767 mono_bitset_free (global_interface_bitset);
9768 global_interface_bitset = NULL;
9769 mono_mutex_destroy (&classes_mutex);
9773 * mono_class_get_exception_for_failure:
9774 * @klass: class in which the failure was detected
9776 * Return a constructed MonoException than the caller can then throw
9777 * using mono_raise_exception - or NULL if no failure is present (or
9778 * doesn't result in an exception).
9781 mono_class_get_exception_for_failure (MonoClass *klass)
9783 gpointer exception_data = mono_class_get_exception_data (klass);
9785 switch (klass->exception_type) {
9786 case MONO_EXCEPTION_TYPE_LOAD: {
9789 char *str = mono_type_get_full_name (klass);
9790 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9791 name = mono_string_new (mono_domain_get (), str);
9793 ex = mono_get_exception_type_load (name, astr);
9797 case MONO_EXCEPTION_MISSING_METHOD: {
9798 char *class_name = exception_data;
9799 char *assembly_name = class_name + strlen (class_name) + 1;
9801 return mono_get_exception_missing_method (class_name, assembly_name);
9803 case MONO_EXCEPTION_MISSING_FIELD: {
9804 char *class_name = exception_data;
9805 char *member_name = class_name + strlen (class_name) + 1;
9807 return mono_get_exception_missing_field (class_name, member_name);
9809 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9810 char *msg_format = exception_data;
9811 char *assembly_name = msg_format + strlen (msg_format) + 1;
9812 char *msg = g_strdup_printf (msg_format, assembly_name);
9815 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9821 case MONO_EXCEPTION_BAD_IMAGE: {
9822 return mono_get_exception_bad_image_format (exception_data);
9825 MonoLoaderError *error;
9828 error = mono_loader_get_last_error ();
9830 ex = mono_loader_error_prepare_exception (error);
9834 /* TODO - handle other class related failures */
9841 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9843 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9844 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9846 if (outer_klass == inner_klass)
9848 inner_klass = inner_klass->nested_in;
9849 } while (inner_klass);
9854 mono_class_get_generic_type_definition (MonoClass *klass)
9856 return klass->generic_class ? klass->generic_class->container_class : klass;
9860 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9862 * Generic instantiations are ignored for all super types of @klass.
9864 * Visibility checks ignoring generic instantiations.
9867 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9870 klass = mono_class_get_generic_type_definition (klass);
9871 parent = mono_class_get_generic_type_definition (parent);
9872 mono_class_setup_supertypes (klass);
9874 for (i = 0; i < klass->idepth; ++i) {
9875 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9881 * Subtype can only access parent members with family protection if the site object
9882 * is subclass of Subtype. For example:
9883 * class A { protected int x; }
9885 * void valid_access () {
9889 * void invalid_access () {
9896 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9898 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9901 if (context_klass == NULL)
9903 /*if access_klass is not member_klass context_klass must be type compat*/
9904 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9910 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9913 if (accessing == accessed)
9915 if (!accessed || !accessing)
9918 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9919 * anywhere so untrusted friends are not safe to access platform's code internals */
9920 if (mono_security_core_clr_enabled ()) {
9921 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9925 mono_assembly_load_friends (accessed);
9926 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9927 MonoAssemblyName *friend = tmp->data;
9928 /* Be conservative with checks */
9931 if (strcmp (accessing->aname.name, friend->name))
9933 if (friend->public_key_token [0]) {
9934 if (!accessing->aname.public_key_token [0])
9936 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9945 * If klass is a generic type or if it is derived from a generic type, return the
9946 * MonoClass of the generic definition
9947 * Returns NULL if not found
9950 get_generic_definition_class (MonoClass *klass)
9953 if (klass->generic_class && klass->generic_class->container_class)
9954 return klass->generic_class->container_class;
9955 klass = klass->parent;
9961 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9964 for (i = 0; i < ginst->type_argc; ++i) {
9965 MonoType *type = ginst->type_argv[i];
9966 switch (type->type) {
9967 case MONO_TYPE_SZARRAY:
9968 if (!can_access_type (access_klass, type->data.klass))
9971 case MONO_TYPE_ARRAY:
9972 if (!can_access_type (access_klass, type->data.array->eklass))
9976 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9979 case MONO_TYPE_CLASS:
9980 case MONO_TYPE_VALUETYPE:
9981 case MONO_TYPE_GENERICINST:
9982 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9992 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9996 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9999 if (access_klass->element_class && !access_klass->enumtype)
10000 access_klass = access_klass->element_class;
10002 if (member_klass->element_class && !member_klass->enumtype)
10003 member_klass = member_klass->element_class;
10005 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10007 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10010 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10013 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10016 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10019 /*Non nested type with nested visibility. We just fail it.*/
10020 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10023 switch (access_level) {
10024 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10025 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10027 case TYPE_ATTRIBUTE_PUBLIC:
10030 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10033 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10034 return is_nesting_type (member_klass, access_klass);
10036 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10037 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10039 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10040 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10042 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10043 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10044 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10046 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10047 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10048 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10053 /* FIXME: check visibility of type, too */
10055 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10057 MonoClass *member_generic_def;
10058 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10061 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10062 access_klass->generic_container) &&
10063 (member_generic_def = get_generic_definition_class (member_klass))) {
10064 MonoClass *access_container;
10066 if (access_klass->generic_container)
10067 access_container = access_klass;
10069 access_container = access_klass->generic_class->container_class;
10071 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10075 /* Partition I 8.5.3.2 */
10076 /* the access level values are the same for fields and methods */
10077 switch (access_level) {
10078 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10079 /* same compilation unit */
10080 return access_klass->image == member_klass->image;
10081 case FIELD_ATTRIBUTE_PRIVATE:
10082 return access_klass == member_klass;
10083 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10084 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10085 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10088 case FIELD_ATTRIBUTE_ASSEMBLY:
10089 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10090 case FIELD_ATTRIBUTE_FAMILY:
10091 if (is_valid_family_access (access_klass, member_klass, context_klass))
10094 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10095 if (is_valid_family_access (access_klass, member_klass, context_klass))
10097 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10098 case FIELD_ATTRIBUTE_PUBLIC:
10105 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10107 /* FIXME: check all overlapping fields */
10108 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10110 MonoClass *nested = method->klass->nested_in;
10112 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10115 nested = nested->nested_in;
10122 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10124 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10126 MonoClass *nested = method->klass->nested_in;
10128 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10131 nested = nested->nested_in;
10136 * with generics calls to explicit interface implementations can be expressed
10137 * directly: the method is private, but we must allow it. This may be opening
10138 * a hole or the generics code should handle this differently.
10139 * Maybe just ensure the interface type is public.
10141 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10147 * mono_method_can_access_method_full:
10148 * @method: The caller method
10149 * @called: The called method
10150 * @context_klass: The static type on stack of the owner @called object used
10152 * This function must be used with instance calls, as they have more strict family accessibility.
10153 * It can be used with static methods, but context_klass should be NULL.
10155 * Returns: TRUE if caller have proper visibility and acessibility to @called
10158 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10160 MonoClass *access_class = method->klass;
10161 MonoClass *member_class = called->klass;
10162 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10164 MonoClass *nested = access_class->nested_in;
10166 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10169 nested = nested->nested_in;
10176 can = can_access_type (access_class, member_class);
10178 MonoClass *nested = access_class->nested_in;
10180 can = can_access_type (nested, member_class);
10183 nested = nested->nested_in;
10190 if (called->is_inflated) {
10191 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10192 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10201 * mono_method_can_access_field_full:
10202 * @method: The caller method
10203 * @field: The accessed field
10204 * @context_klass: The static type on stack of the owner @field object used
10206 * This function must be used with instance fields, as they have more strict family accessibility.
10207 * It can be used with static fields, but context_klass should be NULL.
10209 * Returns: TRUE if caller have proper visibility and acessibility to @field
10212 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10214 MonoClass *access_class = method->klass;
10215 MonoClass *member_class = field->parent;
10216 /* FIXME: check all overlapping fields */
10217 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10219 MonoClass *nested = access_class->nested_in;
10221 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10224 nested = nested->nested_in;
10231 can = can_access_type (access_class, member_class);
10233 MonoClass *nested = access_class->nested_in;
10235 can = can_access_type (nested, member_class);
10238 nested = nested->nested_in;
10248 * mono_class_can_access_class:
10249 * @source_class: The source class
10250 * @target_class: The accessed class
10252 * This function returns is @target_class is visible to @source_class
10254 * Returns: TRUE if source have proper visibility and acessibility to target
10257 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10259 return can_access_type (source_class, target_class);
10263 * mono_type_is_valid_enum_basetype:
10264 * @type: The MonoType to check
10266 * Returns: TRUE if the type can be used as the basetype of an enum
10268 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10269 switch (type->type) {
10272 case MONO_TYPE_BOOLEAN:
10275 case MONO_TYPE_CHAR:
10289 * mono_class_is_valid_enum:
10290 * @klass: An enum class to be validated
10292 * This method verify the required properties an enum should have.
10294 * Returns: TRUE if the informed enum class is valid
10296 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10297 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10298 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10300 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10301 MonoClassField * field;
10302 gpointer iter = NULL;
10303 gboolean found_base_field = FALSE;
10305 g_assert (klass->enumtype);
10306 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10307 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10311 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10314 while ((field = mono_class_get_fields (klass, &iter))) {
10315 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10316 if (found_base_field)
10318 found_base_field = TRUE;
10319 if (!mono_type_is_valid_enum_basetype (field->type))
10324 if (!found_base_field)
10327 if (klass->method.count > 0)
10334 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10336 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10340 * mono_class_setup_interface_id:
10342 * Initializes MonoClass::interface_id if required.
10344 * LOCKING: Acquires the loader lock.
10347 mono_class_setup_interface_id (MonoClass *class)
10349 mono_loader_lock ();
10350 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10351 class->interface_id = mono_get_unique_iid (class);
10352 mono_loader_unlock ();
10356 * mono_class_alloc_ext:
10358 * Allocate klass->ext if not already done.
10361 mono_class_alloc_ext (MonoClass *klass)
10368 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10369 mono_image_lock (klass->image);
10370 mono_memory_barrier ();
10373 class_ext_size += sizeof (MonoClassExt);
10374 mono_image_unlock (klass->image);
10378 * mono_class_setup_interfaces:
10380 * Initialize class->interfaces/interfaces_count.
10381 * LOCKING: Acquires the loader lock.
10382 * This function can fail the type.
10385 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10387 int i, interface_count;
10388 MonoClass **interfaces;
10390 mono_error_init (error);
10392 if (klass->interfaces_inited)
10395 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10396 MonoType *args [1];
10398 /* generic IList, ICollection, IEnumerable */
10399 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10400 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10402 args [0] = &klass->element_class->byval_arg;
10403 interfaces [0] = mono_class_bind_generic_parameters (
10404 mono_defaults.generic_ilist_class, 1, args, FALSE);
10405 if (interface_count > 1)
10406 interfaces [1] = mono_class_bind_generic_parameters (
10407 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10408 } else if (klass->generic_class) {
10409 MonoClass *gklass = klass->generic_class->container_class;
10411 mono_class_setup_interfaces (gklass, error);
10412 if (!mono_error_ok (error)) {
10413 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10417 interface_count = gklass->interface_count;
10418 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10419 for (i = 0; i < interface_count; i++) {
10420 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10421 if (!mono_error_ok (error)) {
10422 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10427 interface_count = 0;
10431 mono_image_lock (klass->image);
10433 if (!klass->interfaces_inited) {
10434 klass->interface_count = interface_count;
10435 klass->interfaces = interfaces;
10437 mono_memory_barrier ();
10439 klass->interfaces_inited = TRUE;
10442 mono_image_unlock (klass->image);
10446 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10448 MonoClass *class = field->parent;
10449 MonoImage *image = class->image;
10450 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10451 int field_idx = field - class->fields;
10453 mono_error_init (error);
10456 MonoClassField *gfield = >d->fields [field_idx];
10457 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10458 if (!mono_error_ok (error)) {
10459 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10460 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10464 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10465 if (!mono_error_ok (error)) {
10466 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10467 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10472 guint32 cols [MONO_FIELD_SIZE];
10473 MonoGenericContainer *container = NULL;
10474 int idx = class->field.first + field_idx;
10476 /*FIXME, in theory we do not lazy load SRE fields*/
10477 g_assert (!image_is_dynamic (image));
10479 if (class->generic_container) {
10480 container = class->generic_container;
10482 container = gtd->generic_container;
10483 g_assert (container);
10486 /* class->field.first and idx points into the fieldptr table */
10487 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10489 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10490 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10491 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10495 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10497 mono_metadata_decode_value (sig, &sig);
10498 /* FIELD signature == 0x06 */
10499 g_assert (*sig == 0x06);
10500 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10502 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10507 mono_field_resolve_flags (MonoClassField *field)
10509 MonoClass *class = field->parent;
10510 MonoImage *image = class->image;
10511 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10512 int field_idx = field - class->fields;
10516 MonoClassField *gfield = >d->fields [field_idx];
10517 return mono_field_get_flags (gfield);
10519 int idx = class->field.first + field_idx;
10521 /*FIXME, in theory we do not lazy load SRE fields*/
10522 g_assert (!image_is_dynamic (image));
10524 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10529 * mono_class_setup_basic_field_info:
10530 * @class: The class to initialize
10532 * Initializes the class->fields array of fields.
10533 * Aquires the loader lock.
10536 mono_class_setup_basic_field_info_locking (MonoClass *class)
10538 mono_loader_lock ();
10539 mono_class_setup_basic_field_info (class);
10540 mono_loader_unlock ();
10544 * mono_class_get_fields_lazy:
10545 * @klass: the MonoClass to act on
10547 * This routine is an iterator routine for retrieving the fields in a class.
10548 * Only minimal information about fields are loaded. Accessors must be used
10549 * for all MonoClassField returned.
10551 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10552 * iterate over all of the elements. When no more values are
10553 * available, the return value is NULL.
10555 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10558 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10560 MonoClassField* field;
10564 mono_class_setup_basic_field_info_locking (klass);
10565 if (!klass->fields)
10567 /* start from the first */
10568 if (klass->field.count) {
10569 return *iter = &klass->fields [0];
10577 if (field < &klass->fields [klass->field.count]) {
10578 return *iter = field;
10584 mono_class_full_name (MonoClass *klass)
10586 return mono_type_full_name (&klass->byval_arg);