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;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation;
99 static GSList *gclass_recorded_list;
100 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
105 mono_locks_acquire (&classes_mutex, ClassesLock);
109 classes_unlock (void)
111 mono_locks_release (&classes_mutex, ClassesLock);
115 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
118 enable_gclass_recording (void)
120 ++record_gclass_instantiation;
124 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
127 disable_gclass_recording (gclass_record_func func, void *user_data)
129 GSList **head = &gclass_recorded_list;
131 g_assert (record_gclass_instantiation > 0);
132 --record_gclass_instantiation;
135 GSList *node = *head;
136 if (func ((MonoClass*)node->data, user_data)) {
138 g_slist_free_1 (node);
144 /* We automatically discard all recorded gclasses when disabled. */
145 if (!record_gclass_instantiation && gclass_recorded_list) {
146 g_slist_free (gclass_recorded_list);
147 gclass_recorded_list = NULL;
152 * mono_class_from_typeref:
153 * @image: a MonoImage
154 * @type_token: a TypeRef token
156 * Creates the MonoClass* structure representing the type defined by
157 * the typeref token valid inside @image.
158 * Returns: the MonoClass* representing the typeref token, NULL ifcould
162 mono_class_from_typeref (MonoImage *image, guint32 type_token)
165 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
166 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
171 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
173 guint32 cols [MONO_TYPEREF_SIZE];
174 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
176 const char *name, *nspace;
177 MonoClass *res = NULL;
180 mono_error_init (error);
182 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
185 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
187 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
188 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
190 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
191 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
192 case MONO_RESOLUTION_SCOPE_MODULE:
194 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
195 This is not the observed behavior of existing implementations.
196 The defacto behavior is that it's just a typedef in disguise.
198 /* a typedef in disguise */
199 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
202 case MONO_RESOLUTION_SCOPE_MODULEREF:
203 module = mono_image_load_module (image, idx);
205 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
208 case MONO_RESOLUTION_SCOPE_TYPEREF: {
209 MonoClass *enclosing;
212 if (idx == mono_metadata_token_index (type_token)) {
213 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
217 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
218 if (!mono_error_ok (error))
221 if (enclosing->nested_classes_inited && enclosing->ext) {
222 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
223 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
225 if (strcmp (res->name, name) == 0)
229 /* Don't call mono_class_init as we might've been called by it recursively */
230 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
232 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
233 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
234 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
236 if (strcmp (nname, name) == 0)
237 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
239 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
242 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
245 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
249 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
250 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
254 if (!image->references || !image->references [idx - 1])
255 mono_assembly_load_reference (image, idx - 1);
256 g_assert (image->references [idx - 1]);
258 /* If the assembly did not load, register this as a type load exception */
259 if (image->references [idx - 1] == REFERENCE_MISSING){
260 MonoAssemblyName aname;
263 mono_assembly_get_assemblyref (image, idx - 1, &aname);
264 human_name = mono_stringify_assembly_name (&aname);
265 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
269 /* FIXME this leaks loader errors */
270 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
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:
625 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
627 mono_error_init (error);
629 switch (type->type) {
630 case MONO_TYPE_MVAR: {
632 int num = mono_type_get_generic_param_num (type);
633 MonoGenericInst *inst = context->method_inst;
634 if (!inst || !inst->type_argv)
636 if (num >= inst->type_argc) {
637 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
638 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
639 num, info ? info->name : "", inst->type_argc);
643 if (!is_valid_generic_argument (inst->type_argv [num])) {
644 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
645 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
646 num, info ? info->name : "", inst->type_argv [num]->type);
650 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
651 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
652 * ->byref and ->attrs from @type are propagated to the returned type.
654 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
655 nt->byref = type->byref;
656 nt->attrs = type->attrs;
659 case MONO_TYPE_VAR: {
661 int num = mono_type_get_generic_param_num (type);
662 MonoGenericInst *inst = context->class_inst;
665 if (num >= inst->type_argc) {
666 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
667 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
668 num, info ? info->name : "", inst->type_argc);
671 if (!is_valid_generic_argument (inst->type_argv [num])) {
672 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
673 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
674 num, info ? info->name : "", inst->type_argv [num]->type);
677 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
678 nt->byref = type->byref;
679 nt->attrs = type->attrs;
682 case MONO_TYPE_SZARRAY: {
683 MonoClass *eclass = type->data.klass;
684 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
685 if (!inflated || !mono_error_ok (error))
687 nt = mono_metadata_type_dup (image, type);
688 nt->data.klass = mono_class_from_mono_type (inflated);
689 mono_metadata_free_type (inflated);
692 case MONO_TYPE_ARRAY: {
693 MonoClass *eclass = type->data.array->eklass;
694 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
695 if (!inflated || !mono_error_ok (error))
697 nt = mono_metadata_type_dup (image, type);
698 nt->data.array->eklass = mono_class_from_mono_type (inflated);
699 mono_metadata_free_type (inflated);
702 case MONO_TYPE_GENERICINST: {
703 MonoGenericClass *gclass = type->data.generic_class;
704 MonoGenericInst *inst;
706 if (!gclass->context.class_inst->is_open)
709 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
710 if (!mono_error_ok (error))
712 if (inst != gclass->context.class_inst)
713 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
715 if (gclass == type->data.generic_class)
718 nt = mono_metadata_type_dup (image, type);
719 nt->data.generic_class = gclass;
722 case MONO_TYPE_CLASS:
723 case MONO_TYPE_VALUETYPE: {
724 MonoClass *klass = type->data.klass;
725 MonoGenericContainer *container = klass->generic_container;
726 MonoGenericInst *inst;
727 MonoGenericClass *gclass = NULL;
733 /* We can't use context->class_inst directly, since it can have more elements */
734 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
735 if (!mono_error_ok (error))
737 if (inst == container->context.class_inst)
740 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
742 nt = mono_metadata_type_dup (image, type);
743 nt->type = MONO_TYPE_GENERICINST;
744 nt->data.generic_class = gclass;
754 mono_generic_class_get_context (MonoGenericClass *gclass)
756 return &gclass->context;
760 mono_class_get_context (MonoClass *class)
762 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
766 * mono_class_get_generic_container:
768 * Return the generic container of KLASS which should be a generic type definition.
770 MonoGenericContainer*
771 mono_class_get_generic_container (MonoClass *klass)
773 g_assert (klass->is_generic);
775 return klass->generic_container;
779 * mono_class_get_generic_class:
781 * Return the MonoGenericClass of KLASS, which should be a generic instance.
784 mono_class_get_generic_class (MonoClass *klass)
786 g_assert (klass->is_inflated);
788 return klass->generic_class;
792 * mono_class_inflate_generic_type_with_mempool:
793 * @mempool: a mempool
795 * @context: a generics context
796 * @error: error context
798 * The same as mono_class_inflate_generic_type, but allocates the MonoType
799 * from mempool if it is non-NULL. If it is NULL, the MonoType is
800 * allocated on the heap and is owned by the caller.
801 * The returned type can potentially be the same as TYPE, so it should not be
802 * modified by the caller, and it should be freed using mono_metadata_free_type ().
805 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
807 MonoType *inflated = NULL;
808 mono_error_init (error);
811 inflated = inflate_generic_type (image, type, context, error);
812 if (!mono_error_ok (error))
816 MonoType *shared = mono_metadata_get_shared_type (type);
821 return mono_metadata_type_dup (image, type);
825 mono_stats.inflated_type_count++;
830 * mono_class_inflate_generic_type:
832 * @context: a generics context
834 * If @type is a generic type and @context is not NULL, instantiate it using the
835 * generics context @context.
837 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
838 * on the heap and is owned by the caller. Returns NULL on error.
840 * @deprecated Please use mono_class_inflate_generic_type_checked instead
843 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
847 result = mono_class_inflate_generic_type_checked (type, context, &error);
849 if (!mono_error_ok (&error)) {
850 mono_error_cleanup (&error);
857 * mono_class_inflate_generic_type:
859 * @context: a generics context
860 * @error: error context to use
862 * If @type is a generic type and @context is not NULL, instantiate it using the
863 * generics context @context.
865 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
866 * on the heap and is owned by the caller.
869 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
871 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
875 * mono_class_inflate_generic_type_no_copy:
877 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
881 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
883 MonoType *inflated = NULL;
885 mono_error_init (error);
887 inflated = inflate_generic_type (image, type, context, error);
888 if (!mono_error_ok (error))
895 mono_stats.inflated_type_count++;
900 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
905 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
906 if (!mono_error_ok (error))
909 res = mono_class_from_mono_type (inflated);
910 mono_metadata_free_type (inflated);
915 * mono_class_inflate_generic_class:
917 * Inflate the class GKLASS with CONTEXT.
920 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
925 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
926 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
933 static MonoGenericContext
934 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
936 MonoGenericInst *class_inst = NULL;
937 MonoGenericInst *method_inst = NULL;
938 MonoGenericContext res = { NULL, NULL };
940 mono_error_init (error);
942 if (context->class_inst) {
943 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
944 if (!mono_error_ok (error))
948 if (context->method_inst) {
949 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
950 if (!mono_error_ok (error))
954 res.class_inst = class_inst;
955 res.method_inst = method_inst;
961 * mono_class_inflate_generic_method:
962 * @method: a generic method
963 * @context: a generics context
965 * Instantiate the generic method @method using the generics context @context.
967 * Returns: the new instantiated method
970 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
972 return mono_class_inflate_generic_method_full (method, NULL, context);
976 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
978 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
982 * mono_class_inflate_generic_method_full:
984 * Instantiate method @method with the generic context @context.
985 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
986 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
989 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
992 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
993 if (!mono_error_ok (&error))
994 /*FIXME do proper error handling - on this case, kill this function. */
995 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1001 * mono_class_inflate_generic_method_full_checked:
1002 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1005 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1008 MonoMethodInflated *iresult, *cached;
1009 MonoMethodSignature *sig;
1010 MonoGenericContext tmp_context;
1011 gboolean is_mb_open = FALSE;
1013 mono_error_init (error);
1015 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1016 while (method->is_inflated) {
1017 MonoGenericContext *method_context = mono_method_get_context (method);
1018 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1020 tmp_context = inflate_generic_context (method_context, context, error);
1021 if (!mono_error_ok (error))
1023 context = &tmp_context;
1025 if (mono_metadata_generic_context_equal (method_context, context))
1028 method = imethod->declaring;
1032 * A method only needs to be inflated if the context has argument for which it is
1035 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1036 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1039 if (!((method->is_generic && context->method_inst) ||
1040 (method->klass->generic_container && context->class_inst)))
1044 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1045 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1046 * This is opposite to the way non-SRE MethodInfos behave.
1048 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1050 * void Example<T> () {
1054 * In Example, the method token must be encoded as: "void Example<!!0>()"
1056 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1057 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1059 * On the other hand, inflating a non-SRE generic method with its own arguments should
1060 * return itself. For example:
1062 * MethodInfo m = ... //m is a generic method definition
1063 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1066 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1067 * what happens with regular methods.
1069 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1070 * everything should behave like a regular type or method.
1073 is_mb_open = method->is_generic &&
1074 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1075 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1077 iresult = g_new0 (MonoMethodInflated, 1);
1078 iresult->context = *context;
1079 iresult->declaring = method;
1080 iresult->method.method.is_mb_open = is_mb_open;
1082 if (!context->method_inst && method->is_generic)
1083 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1085 if (!context->class_inst) {
1086 g_assert (!iresult->declaring->klass->generic_class);
1087 if (iresult->declaring->klass->generic_container)
1088 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1089 else if (iresult->declaring->klass->generic_class)
1090 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 cached = mono_method_inflated_lookup (iresult, FALSE);
1096 return (MonoMethod*)cached;
1099 mono_stats.inflated_method_count++;
1101 inflated_methods_size += sizeof (MonoMethodInflated);
1103 sig = mono_method_signature (method);
1105 char *name = mono_type_get_full_name (method->klass);
1106 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1112 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1114 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1117 result = (MonoMethod *) iresult;
1118 result->is_inflated = TRUE;
1119 result->is_generic = FALSE;
1120 result->sre_method = FALSE;
1121 result->signature = NULL;
1122 result->is_mb_open = is_mb_open;
1124 if (!context->method_inst) {
1125 /* Set the generic_container of the result to the generic_container of method */
1126 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1128 if (generic_container) {
1129 result->is_generic = 1;
1130 mono_method_set_generic_container (result, generic_container);
1134 if (!klass_hint || !klass_hint->generic_class ||
1135 klass_hint->generic_class->container_class != method->klass ||
1136 klass_hint->generic_class->context.class_inst != context->class_inst)
1139 if (method->klass->generic_container)
1140 result->klass = klass_hint;
1142 if (!result->klass) {
1143 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1144 if (!mono_error_ok (error))
1147 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1149 mono_metadata_free_type (inflated);
1153 * FIXME: This should hold, but it doesn't:
1155 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1156 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1157 * g_assert (result->is_generic);
1160 * Fixing this here causes other things to break, hence a very
1161 * ugly hack in mini-trampolines.c - see
1162 * is_generic_method_definition().
1165 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1173 * mono_get_inflated_method:
1175 * Obsolete. We keep it around since it's mentioned in the public API.
1178 mono_get_inflated_method (MonoMethod *method)
1184 * mono_method_get_context_general:
1186 * @uninflated: handle uninflated methods?
1188 * Returns the generic context of a method or NULL if it doesn't have
1189 * one. For an inflated method that's the context stored in the
1190 * method. Otherwise it's in the method's generic container or in the
1191 * generic container of the method's class.
1194 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1196 if (method->is_inflated) {
1197 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1198 return &imethod->context;
1202 if (method->is_generic)
1203 return &(mono_method_get_generic_container (method)->context);
1204 if (method->klass->generic_container)
1205 return &method->klass->generic_container->context;
1210 * mono_method_get_context:
1213 * Returns the generic context for method if it's inflated, otherwise
1217 mono_method_get_context (MonoMethod *method)
1219 return mono_method_get_context_general (method, FALSE);
1223 * mono_method_get_generic_container:
1225 * Returns the generic container of METHOD, which should be a generic method definition.
1226 * Returns NULL if METHOD is not a generic method definition.
1227 * LOCKING: Acquires the loader lock.
1229 MonoGenericContainer*
1230 mono_method_get_generic_container (MonoMethod *method)
1232 MonoGenericContainer *container;
1234 if (!method->is_generic)
1237 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1238 g_assert (container);
1244 * mono_method_set_generic_container:
1246 * Sets the generic container of METHOD to CONTAINER.
1247 * LOCKING: Acquires the image lock.
1250 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1252 g_assert (method->is_generic);
1254 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1258 * mono_class_find_enum_basetype:
1259 * @class: The enum class
1261 * Determine the basetype of an enum by iterating through its fields. We do this
1262 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1265 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1267 MonoGenericContainer *container = NULL;
1268 MonoImage *m = class->image;
1269 const int top = class->field.count;
1272 g_assert (class->enumtype);
1274 mono_error_init (error);
1276 if (class->generic_container)
1277 container = class->generic_container;
1278 else if (class->generic_class) {
1279 MonoClass *gklass = class->generic_class->container_class;
1281 container = gklass->generic_container;
1282 g_assert (container);
1286 * Fetch all the field information.
1288 for (i = 0; i < top; i++){
1290 guint32 cols [MONO_FIELD_SIZE];
1291 int idx = class->field.first + i;
1294 /* class->field.first and idx points into the fieldptr table */
1295 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1297 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1300 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1301 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1305 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1306 mono_metadata_decode_value (sig, &sig);
1307 /* FIELD signature == 0x06 */
1309 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1313 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1315 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1316 mono_error_set_from_loader_error (error);
1318 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1321 if (class->generic_class) {
1322 //FIXME do we leak here?
1323 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1324 if (!mono_error_ok (error))
1326 ftype->attrs = cols [MONO_FIELD_FLAGS];
1331 mono_error_set_type_load_class (error, class, "Could not find base type");
1334 g_assert (!mono_loader_get_last_error ());
1339 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1342 mono_type_has_exceptions (MonoType *type)
1344 switch (type->type) {
1345 case MONO_TYPE_CLASS:
1346 case MONO_TYPE_VALUETYPE:
1347 case MONO_TYPE_SZARRAY:
1348 return type->data.klass->exception_type;
1349 case MONO_TYPE_ARRAY:
1350 return type->data.array->eklass->exception_type;
1351 case MONO_TYPE_GENERICINST:
1352 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1360 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1364 mono_class_alloc (MonoClass *class, int size)
1366 if (class->generic_class)
1367 return mono_image_set_alloc (class->generic_class->owner, size);
1369 return mono_image_alloc (class->image, size);
1373 mono_class_alloc0 (MonoClass *class, int size)
1377 res = mono_class_alloc (class, size);
1378 memset (res, 0, size);
1382 #define mono_class_new0(class,struct_type, n_structs) \
1383 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1386 * mono_class_setup_basic_field_info:
1387 * @class: The class to initialize
1389 * Initializes the class->fields.
1390 * LOCKING: Assumes the loader lock is held.
1393 mono_class_setup_basic_field_info (MonoClass *class)
1395 MonoClassField *field;
1403 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1404 image = class->image;
1405 top = class->field.count;
1407 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1409 * This happens when a generic instance of an unfinished generic typebuilder
1410 * is used as an element type for creating an array type. We can't initialize
1411 * the fields of this class using the fields of gklass, since gklass is not
1412 * finished yet, fields could be added to it later.
1418 mono_class_setup_basic_field_info (gtd);
1420 top = gtd->field.count;
1421 class->field.first = gtd->field.first;
1422 class->field.count = gtd->field.count;
1425 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1428 * Fetch all the field information.
1430 for (i = 0; i < top; i++){
1431 field = &class->fields [i];
1432 field->parent = class;
1435 field->name = mono_field_get_name (>d->fields [i]);
1437 int idx = class->field.first + i;
1438 /* class->field.first and idx points into the fieldptr table */
1439 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1440 /* The name is needed for fieldrefs */
1441 field->name = mono_metadata_string_heap (image, name_idx);
1447 * mono_class_setup_fields:
1448 * @class: The class to initialize
1450 * Initializes the class->fields.
1451 * LOCKING: Assumes the loader lock is held.
1454 mono_class_setup_fields (MonoClass *class)
1457 MonoImage *m = class->image;
1459 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1460 int i, blittable = TRUE;
1461 guint32 real_size = 0;
1462 guint32 packing_size = 0;
1463 gboolean explicit_size;
1464 MonoClassField *field;
1465 MonoGenericContainer *container = NULL;
1466 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1469 * FIXME: We have a race condition here. It's possible that this function returns
1470 * to its caller with `instance_size` set to `0` instead of the actual size. This
1471 * is not a problem when the function is called recursively on the same class,
1472 * because the size will be initialized by the outer invocation. What follows is a
1473 * description of how it can occur in other cases, too. There it is a problem,
1474 * because it can lead to the GC being asked to allocate an object of size `0`,
1475 * which SGen chokes on. The race condition is triggered infrequently by
1476 * `tests/sgen-suspend.cs`.
1478 * This function is called for a class whenever one of its subclasses is inited.
1479 * For example, it's called for every subclass of Object. What it does is this:
1481 * if (class->setup_fields_called)
1484 * class->instance_size = 0;
1486 * class->setup_fields_called = 1;
1487 * ... critical point
1488 * class->instance_size = actual_instance_size;
1490 * The last two steps are sometimes reversed, but that only changes the way in which
1491 * the race condition works.
1493 * Assume thread A goes through this function and makes it to the critical point.
1494 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1495 * immediately, but `instance_size` is incorrect.
1497 * The other case looks like this:
1499 * if (class->setup_fields_called)
1501 * ... critical point X
1502 * class->instance_size = 0;
1503 * ... critical point Y
1504 * class->instance_size = actual_instance_size;
1506 * class->setup_fields_called = 1;
1508 * Assume thread A goes through the function and makes it to critical point X. Now
1509 * thread B runs through the whole of the function, returning, assuming
1510 * `instance_size` is set. At that point thread A gets to run and makes it to
1511 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1514 if (class->setup_fields_called)
1517 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1519 * This happens when a generic instance of an unfinished generic typebuilder
1520 * is used as an element type for creating an array type. We can't initialize
1521 * the fields of this class using the fields of gklass, since gklass is not
1522 * finished yet, fields could be added to it later.
1527 mono_class_setup_basic_field_info (class);
1528 top = class->field.count;
1531 mono_class_setup_fields (gtd);
1532 if (gtd->exception_type) {
1533 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1538 class->instance_size = 0;
1540 class->sizes.class_size = 0;
1542 if (class->parent) {
1543 /* For generic instances, class->parent might not have been initialized */
1544 mono_class_init (class->parent);
1545 if (!class->parent->size_inited) {
1546 mono_class_setup_fields (class->parent);
1547 if (class->parent->exception_type) {
1548 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1552 class->instance_size += class->parent->instance_size;
1553 class->min_align = class->parent->min_align;
1554 /* we use |= since it may have been set already */
1555 class->has_references |= class->parent->has_references;
1556 blittable = class->parent->blittable;
1558 class->instance_size = sizeof (MonoObject);
1559 class->min_align = 1;
1562 /* We can't really enable 16 bytes alignment until the GC supports it.
1563 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1564 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1565 Bug #506144 is an example of this issue.
1567 if (class->simd_type)
1568 class->min_align = 16;
1570 /* Get the real size */
1571 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1573 if (explicit_size) {
1574 if ((packing_size & 0xffffff00) != 0) {
1575 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1576 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1579 class->packing_size = packing_size;
1580 real_size += class->instance_size;
1584 if (explicit_size && real_size) {
1585 class->instance_size = MAX (real_size, class->instance_size);
1587 class->blittable = blittable;
1588 mono_memory_barrier ();
1589 class->size_inited = 1;
1590 class->fields_inited = 1;
1591 class->setup_fields_called = 1;
1595 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1598 /* Prevent infinite loops if the class references itself */
1599 class->setup_fields_called = 1;
1601 if (class->generic_container) {
1602 container = class->generic_container;
1604 container = gtd->generic_container;
1605 g_assert (container);
1609 * Fetch all the field information.
1611 for (i = 0; i < top; i++){
1612 int idx = class->field.first + i;
1613 field = &class->fields [i];
1615 field->parent = class;
1618 mono_field_resolve_type (field, &error);
1619 if (!mono_error_ok (&error)) {
1620 /*mono_field_resolve_type already failed class*/
1621 mono_error_cleanup (&error);
1625 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1626 g_assert (field->type);
1629 if (mono_field_is_deleted (field))
1632 MonoClassField *gfield = >d->fields [i];
1633 field->offset = gfield->offset;
1635 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1637 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1638 field->offset = offset;
1640 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1641 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1644 if (field->offset < -1) { /*-1 is used to encode special static fields */
1645 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1648 if (class->generic_container) {
1649 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1655 /* Only do these checks if we still think this type is blittable */
1656 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1657 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1660 MonoClass *field_class = mono_class_from_mono_type (field->type);
1662 mono_class_setup_fields (field_class);
1663 if (field_class->exception_type) {
1664 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1668 if (!field_class || !field_class->blittable)
1673 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1674 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1675 blittable = class->element_class->blittable;
1678 if (mono_type_has_exceptions (field->type)) {
1679 char *class_name = mono_type_get_full_name (class);
1680 char *type_name = mono_type_full_name (field->type);
1682 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1683 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1684 g_free (class_name);
1688 /* The def_value of fields is compute lazily during vtable creation */
1691 if (class == mono_defaults.string_class)
1694 class->blittable = blittable;
1696 if (class->enumtype && !mono_class_enum_basetype (class)) {
1697 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1700 if (explicit_size && real_size) {
1701 class->instance_size = MAX (real_size, class->instance_size);
1704 if (class->exception_type)
1706 mono_class_layout_fields (class);
1708 /*valuetypes can't be neither bigger than 1Mb or empty. */
1709 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1710 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1712 mono_memory_barrier ();
1713 class->fields_inited = 1;
1717 * mono_class_setup_fields_locking:
1718 * @class: The class to initialize
1720 * Initializes the class->fields array of fields.
1721 * Aquires the loader lock.
1724 mono_class_setup_fields_locking (MonoClass *class)
1726 /* This can be checked without locks */
1727 if (class->fields_inited)
1729 mono_loader_lock ();
1730 mono_class_setup_fields (class);
1731 mono_loader_unlock ();
1735 * mono_class_has_references:
1737 * Returns whenever @klass->has_references is set, initializing it if needed.
1738 * Aquires the loader lock.
1741 mono_class_has_references (MonoClass *klass)
1743 if (klass->init_pending) {
1744 /* Be conservative */
1747 mono_class_init (klass);
1749 return klass->has_references;
1754 * mono_type_get_basic_type_from_generic:
1757 * Returns a closed type corresponding to the possibly open type
1761 mono_type_get_basic_type_from_generic (MonoType *type)
1763 /* When we do generic sharing we let type variables stand for reference types. */
1764 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1765 return &mono_defaults.object_class->byval_arg;
1770 * mono_class_layout_fields:
1773 * Compute the placement of fields inside an object or struct, according to
1774 * the layout rules and set the following fields in @class:
1775 * - has_references (if the class contains instance references firled or structs that contain references)
1776 * - has_static_refs (same, but for static fields)
1777 * - instance_size (size of the object in memory)
1778 * - class_size (size needed for the static fields)
1779 * - size_inited (flag set when the instance_size is set)
1781 * LOCKING: this is supposed to be called with the loader lock held.
1784 mono_class_layout_fields (MonoClass *class)
1787 const int top = class->field.count;
1788 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1789 guint32 pass, passes, real_size;
1790 gboolean gc_aware_layout = FALSE;
1791 gboolean has_static_fields = FALSE;
1792 MonoClassField *field;
1795 * When we do generic sharing we need to have layout
1796 * information for open generic classes (either with a generic
1797 * context containing type variables or with a generic
1798 * container), so we don't return in that case anymore.
1802 * Enable GC aware auto layout: in this mode, reference
1803 * fields are grouped together inside objects, increasing collector
1805 * Requires that all classes whose layout is known to native code be annotated
1806 * with [StructLayout (LayoutKind.Sequential)]
1807 * Value types have gc_aware_layout disabled by default, as per
1808 * what the default is for other runtimes.
1810 /* corlib is missing [StructLayout] directives in many places */
1811 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1812 if (!class->valuetype)
1813 gc_aware_layout = TRUE;
1816 /* Compute klass->has_references */
1818 * Process non-static fields first, since static fields might recursively
1819 * refer to the class itself.
1821 for (i = 0; i < top; i++) {
1824 field = &class->fields [i];
1826 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1827 ftype = mono_type_get_underlying_type (field->type);
1828 ftype = mono_type_get_basic_type_from_generic (ftype);
1829 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1830 class->has_references = TRUE;
1834 for (i = 0; i < top; i++) {
1837 field = &class->fields [i];
1839 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1840 ftype = mono_type_get_underlying_type (field->type);
1841 ftype = mono_type_get_basic_type_from_generic (ftype);
1842 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1843 class->has_static_refs = TRUE;
1847 for (i = 0; i < top; i++) {
1850 field = &class->fields [i];
1852 ftype = mono_type_get_underlying_type (field->type);
1853 ftype = mono_type_get_basic_type_from_generic (ftype);
1854 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1855 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1856 class->has_static_refs = TRUE;
1858 class->has_references = TRUE;
1863 * Compute field layout and total size (not considering static fields)
1867 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1868 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1870 if (gc_aware_layout)
1875 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1878 if (class->parent) {
1879 mono_class_setup_fields (class->parent);
1880 if (class->parent->exception_type) {
1881 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1884 real_size = class->parent->instance_size;
1886 real_size = sizeof (MonoObject);
1889 for (pass = 0; pass < passes; ++pass) {
1890 for (i = 0; i < top; i++){
1895 field = &class->fields [i];
1897 if (mono_field_is_deleted (field))
1899 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1902 ftype = mono_type_get_underlying_type (field->type);
1903 ftype = mono_type_get_basic_type_from_generic (ftype);
1904 if (gc_aware_layout) {
1905 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1914 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1915 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1916 /* This field is a hack inserted by MCS to empty structures */
1920 size = mono_type_size (field->type, &align);
1922 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1923 align = class->packing_size ? MIN (class->packing_size, align): align;
1924 /* if the field has managed references, we need to force-align it
1927 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1928 align = MAX (align, sizeof (gpointer));
1930 class->min_align = MAX (align, class->min_align);
1931 field->offset = real_size;
1933 field->offset += align - 1;
1934 field->offset &= ~(align - 1);
1936 /*TypeBuilders produce all sort of weird things*/
1937 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1938 real_size = field->offset + size;
1941 class->instance_size = MAX (real_size, class->instance_size);
1943 if (class->instance_size & (class->min_align - 1)) {
1944 class->instance_size += class->min_align - 1;
1945 class->instance_size &= ~(class->min_align - 1);
1949 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1953 for (i = 0; i < top; i++) {
1958 field = &class->fields [i];
1961 * There must be info about all the fields in a type if it
1962 * uses explicit layout.
1964 if (mono_field_is_deleted (field))
1966 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1969 size = mono_type_size (field->type, &align);
1970 align = class->packing_size ? MIN (class->packing_size, align): align;
1971 class->min_align = MAX (align, class->min_align);
1974 * When we get here, field->offset is already set by the
1975 * loader (for either runtime fields or fields loaded from metadata).
1976 * The offset is from the start of the object: this works for both
1977 * classes and valuetypes.
1979 field->offset += sizeof (MonoObject);
1980 ftype = mono_type_get_underlying_type (field->type);
1981 ftype = mono_type_get_basic_type_from_generic (ftype);
1982 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1983 if (field->offset % sizeof (gpointer)) {
1984 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1991 real_size = MAX (real_size, size + field->offset);
1994 if (class->has_references) {
1995 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1997 /* Check for overlapping reference and non-reference fields */
1998 for (i = 0; i < top; i++) {
2001 field = &class->fields [i];
2003 if (mono_field_is_deleted (field))
2005 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2007 ftype = mono_type_get_underlying_type (field->type);
2008 if (MONO_TYPE_IS_REFERENCE (ftype))
2009 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2011 for (i = 0; i < top; i++) {
2012 field = &class->fields [i];
2014 if (mono_field_is_deleted (field))
2016 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2019 // FIXME: Too much code does this
2021 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2022 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);
2023 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2027 g_free (ref_bitmap);
2030 class->instance_size = MAX (real_size, class->instance_size);
2031 if (class->instance_size & (class->min_align - 1)) {
2032 class->instance_size += class->min_align - 1;
2033 class->instance_size &= ~(class->min_align - 1);
2039 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2041 * For small structs, set min_align to at least the struct size to improve
2042 * performance, and since the JIT memset/memcpy code assumes this and generates
2043 * unaligned accesses otherwise. See #78990 for a testcase.
2045 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2046 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2049 mono_memory_barrier ();
2050 class->size_inited = 1;
2053 * Compute static field layout and size
2055 for (i = 0; i < top; i++){
2059 field = &class->fields [i];
2061 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2063 if (mono_field_is_deleted (field))
2066 if (mono_type_has_exceptions (field->type)) {
2067 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2071 has_static_fields = TRUE;
2073 size = mono_type_size (field->type, &align);
2074 field->offset = class->sizes.class_size;
2075 /*align is always non-zero here*/
2076 field->offset += align - 1;
2077 field->offset &= ~(align - 1);
2078 class->sizes.class_size = field->offset + size;
2081 if (has_static_fields && class->sizes.class_size == 0)
2082 /* Simplify code which depends on class_size != 0 if the class has static fields */
2083 class->sizes.class_size = 8;
2087 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2091 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2092 method->klass = class;
2093 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2094 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2095 method->signature = sig;
2096 method->name = name;
2099 if (name [0] == '.') {
2100 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2102 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2108 * mono_class_setup_methods:
2111 * Initializes the 'methods' array in CLASS.
2112 * Calling this method should be avoided if possible since it allocates a lot
2113 * of long-living MonoMethod structures.
2114 * Methods belonging to an interface are assigned a sequential slot starting
2117 * On failure this function sets class->exception_type
2120 mono_class_setup_methods (MonoClass *class)
2123 MonoMethod **methods;
2128 if (class->generic_class) {
2130 MonoClass *gklass = class->generic_class->container_class;
2132 mono_class_init (gklass);
2133 if (!gklass->exception_type)
2134 mono_class_setup_methods (gklass);
2135 if (gklass->exception_type) {
2136 /* FIXME make exception_data less opaque so it's possible to dup it here */
2137 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2141 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2142 count = gklass->method.count;
2143 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2145 for (i = 0; i < count; i++) {
2146 methods [i] = mono_class_inflate_generic_method_full_checked (
2147 gklass->methods [i], class, mono_class_get_context (class), &error);
2148 if (!mono_error_ok (&error)) {
2149 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2150 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)));
2153 mono_error_cleanup (&error);
2157 } else if (class->rank) {
2159 MonoMethod *amethod;
2160 MonoMethodSignature *sig;
2161 int count_generic = 0, first_generic = 0;
2163 gboolean jagged_ctor = FALSE;
2165 count = 3 + (class->rank > 1? 2: 1);
2167 mono_class_setup_interfaces (class, &error);
2168 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2170 if (class->rank == 1 && class->element_class->rank) {
2172 class->method.count ++;
2175 if (class->interface_count) {
2176 count_generic = generic_array_methods (class);
2177 first_generic = count;
2178 count += class->interface_count * count_generic;
2181 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2183 sig = mono_metadata_signature_alloc (class->image, class->rank);
2184 sig->ret = &mono_defaults.void_class->byval_arg;
2185 sig->pinvoke = TRUE;
2186 sig->hasthis = TRUE;
2187 for (i = 0; i < class->rank; ++i)
2188 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2190 amethod = create_array_method (class, ".ctor", sig);
2191 methods [method_num++] = amethod;
2192 if (class->rank > 1) {
2193 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2194 sig->ret = &mono_defaults.void_class->byval_arg;
2195 sig->pinvoke = TRUE;
2196 sig->hasthis = TRUE;
2197 for (i = 0; i < class->rank * 2; ++i)
2198 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2200 amethod = create_array_method (class, ".ctor", sig);
2201 methods [method_num++] = amethod;
2205 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2206 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2207 sig->ret = &mono_defaults.void_class->byval_arg;
2208 sig->pinvoke = TRUE;
2209 sig->hasthis = TRUE;
2210 for (i = 0; i < class->rank + 1; ++i)
2211 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2212 amethod = create_array_method (class, ".ctor", sig);
2213 methods [method_num++] = amethod;
2216 /* element Get (idx11, [idx2, ...]) */
2217 sig = mono_metadata_signature_alloc (class->image, class->rank);
2218 sig->ret = &class->element_class->byval_arg;
2219 sig->pinvoke = TRUE;
2220 sig->hasthis = TRUE;
2221 for (i = 0; i < class->rank; ++i)
2222 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2223 amethod = create_array_method (class, "Get", sig);
2224 methods [method_num++] = amethod;
2225 /* element& Address (idx11, [idx2, ...]) */
2226 sig = mono_metadata_signature_alloc (class->image, class->rank);
2227 sig->ret = &class->element_class->this_arg;
2228 sig->pinvoke = TRUE;
2229 sig->hasthis = TRUE;
2230 for (i = 0; i < class->rank; ++i)
2231 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2232 amethod = create_array_method (class, "Address", sig);
2233 methods [method_num++] = amethod;
2234 /* void Set (idx11, [idx2, ...], element) */
2235 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2236 sig->ret = &mono_defaults.void_class->byval_arg;
2237 sig->pinvoke = TRUE;
2238 sig->hasthis = TRUE;
2239 for (i = 0; i < class->rank; ++i)
2240 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2241 sig->params [i] = &class->element_class->byval_arg;
2242 amethod = create_array_method (class, "Set", sig);
2243 methods [method_num++] = amethod;
2245 for (i = 0; i < class->interface_count; i++)
2246 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2250 count = class->method.count;
2251 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2252 for (i = 0; i < count; ++i) {
2253 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2254 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2256 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)));
2257 mono_error_cleanup (&error);
2262 if (MONO_CLASS_IS_INTERFACE (class)) {
2264 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2265 for (i = 0; i < count; ++i) {
2266 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2267 methods [i]->slot = slot++;
2271 mono_image_lock (class->image);
2273 if (!class->methods) {
2274 class->method.count = count;
2276 /* Needed because of the double-checking locking pattern */
2277 mono_memory_barrier ();
2279 class->methods = methods;
2282 mono_image_unlock (class->image);
2286 * mono_class_get_method_by_index:
2288 * Returns class->methods [index], initializing class->methods if neccesary.
2290 * LOCKING: Acquires the loader lock.
2293 mono_class_get_method_by_index (MonoClass *class, int index)
2296 /* Avoid calling setup_methods () if possible */
2297 if (class->generic_class && !class->methods) {
2298 MonoClass *gklass = class->generic_class->container_class;
2301 m = mono_class_inflate_generic_method_full_checked (
2302 gklass->methods [index], class, mono_class_get_context (class), &error);
2303 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2305 * If setup_methods () is called later for this class, no duplicates are created,
2306 * since inflate_generic_method guarantees that only one instance of a method
2307 * is created for each context.
2310 mono_class_setup_methods (class);
2311 g_assert (m == class->methods [index]);
2315 mono_class_setup_methods (class);
2316 if (class->exception_type) /*FIXME do proper error handling*/
2318 g_assert (index >= 0 && index < class->method.count);
2319 return class->methods [index];
2324 * mono_class_get_inflated_method:
2326 * Given an inflated class CLASS and a method METHOD which should be a method of
2327 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2330 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2332 MonoClass *gklass = class->generic_class->container_class;
2335 g_assert (method->klass == gklass);
2337 mono_class_setup_methods (gklass);
2338 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2340 for (i = 0; i < gklass->method.count; ++i) {
2341 if (gklass->methods [i] == method) {
2342 if (class->methods) {
2343 return class->methods [i];
2346 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2347 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2357 * mono_class_get_vtable_entry:
2359 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2360 * LOCKING: Acquires the loader lock.
2363 mono_class_get_vtable_entry (MonoClass *class, int offset)
2367 if (class->rank == 1) {
2369 * szarrays do not overwrite any methods of Array, so we can avoid
2370 * initializing their vtables in some cases.
2372 mono_class_setup_vtable (class->parent);
2373 if (offset < class->parent->vtable_size)
2374 return class->parent->vtable [offset];
2377 if (class->generic_class) {
2379 MonoClass *gklass = class->generic_class->container_class;
2380 mono_class_setup_vtable (gklass);
2381 m = gklass->vtable [offset];
2383 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2384 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2386 mono_class_setup_vtable (class);
2387 if (class->exception_type)
2389 m = class->vtable [offset];
2396 * mono_class_get_vtable_size:
2398 * Return the vtable size for KLASS.
2401 mono_class_get_vtable_size (MonoClass *klass)
2403 mono_class_setup_vtable (klass);
2405 return klass->vtable_size;
2409 * mono_class_setup_properties:
2411 * Initialize class->ext.property and class->ext.properties.
2413 * This method can fail the class.
2416 mono_class_setup_properties (MonoClass *class)
2418 guint startm, endm, i, j;
2419 guint32 cols [MONO_PROPERTY_SIZE];
2420 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2421 MonoProperty *properties;
2425 if (class->ext && class->ext->properties)
2428 if (class->generic_class) {
2429 MonoClass *gklass = class->generic_class->container_class;
2431 mono_class_init (gklass);
2432 mono_class_setup_properties (gklass);
2433 if (gklass->exception_type) {
2434 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2438 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2440 for (i = 0; i < gklass->ext->property.count; i++) {
2442 MonoProperty *prop = &properties [i];
2444 *prop = gklass->ext->properties [i];
2447 prop->get = mono_class_inflate_generic_method_full_checked (
2448 prop->get, class, mono_class_get_context (class), &error);
2450 prop->set = mono_class_inflate_generic_method_full_checked (
2451 prop->set, class, mono_class_get_context (class), &error);
2453 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2454 prop->parent = class;
2457 first = gklass->ext->property.first;
2458 count = gklass->ext->property.count;
2460 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2461 count = last - first;
2464 mono_class_setup_methods (class);
2465 if (class->exception_type)
2469 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2470 for (i = first; i < last; ++i) {
2471 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2472 properties [i - first].parent = class;
2473 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2474 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2476 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2477 for (j = startm; j < endm; ++j) {
2480 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2482 if (class->image->uncompressed_metadata) {
2484 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2485 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2486 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2488 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2491 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2492 case METHOD_SEMANTIC_SETTER:
2493 properties [i - first].set = method;
2495 case METHOD_SEMANTIC_GETTER:
2496 properties [i - first].get = method;
2505 mono_class_alloc_ext (class);
2507 mono_image_lock (class->image);
2509 if (class->ext->properties) {
2510 /* We leak 'properties' which was allocated from the image mempool */
2511 mono_image_unlock (class->image);
2515 class->ext->property.first = first;
2516 class->ext->property.count = count;
2518 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2519 mono_memory_barrier ();
2521 /* Leave this assignment as the last op in the function */
2522 class->ext->properties = properties;
2524 mono_image_unlock (class->image);
2528 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2530 MonoMethod **om, **retval;
2533 for (om = methods, count = 0; *om; ++om, ++count)
2536 retval = g_new0 (MonoMethod*, count + 1);
2538 for (om = methods, count = 0; *om; ++om, ++count) {
2540 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2541 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2547 /*This method can fail the class.*/
2549 mono_class_setup_events (MonoClass *class)
2552 guint startm, endm, i, j;
2553 guint32 cols [MONO_EVENT_SIZE];
2554 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2558 if (class->ext && class->ext->events)
2561 if (class->generic_class) {
2562 MonoClass *gklass = class->generic_class->container_class;
2563 MonoGenericContext *context = NULL;
2565 mono_class_setup_events (gklass);
2566 if (gklass->exception_type) {
2567 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2571 first = gklass->ext->event.first;
2572 count = gklass->ext->event.count;
2574 events = mono_class_new0 (class, MonoEvent, count);
2577 context = mono_class_get_context (class);
2579 for (i = 0; i < count; i++) {
2581 MonoEvent *event = &events [i];
2582 MonoEvent *gevent = &gklass->ext->events [i];
2584 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2586 event->parent = class;
2587 event->name = gevent->name;
2588 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2589 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2590 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2591 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2592 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2593 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2595 #ifndef MONO_SMALL_CONFIG
2596 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2598 event->attrs = gevent->attrs;
2601 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2602 count = last - first;
2605 mono_class_setup_methods (class);
2606 if (class->exception_type) {
2607 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2612 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2613 for (i = first; i < last; ++i) {
2614 MonoEvent *event = &events [i - first];
2616 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2617 event->parent = class;
2618 event->attrs = cols [MONO_EVENT_FLAGS];
2619 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2621 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2622 for (j = startm; j < endm; ++j) {
2625 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2627 if (class->image->uncompressed_metadata) {
2629 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2630 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2631 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2633 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2636 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2637 case METHOD_SEMANTIC_ADD_ON:
2638 event->add = method;
2640 case METHOD_SEMANTIC_REMOVE_ON:
2641 event->remove = method;
2643 case METHOD_SEMANTIC_FIRE:
2644 event->raise = method;
2646 case METHOD_SEMANTIC_OTHER: {
2647 #ifndef MONO_SMALL_CONFIG
2650 if (event->other == NULL) {
2651 event->other = g_new0 (MonoMethod*, 2);
2653 while (event->other [n])
2655 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2657 event->other [n] = method;
2658 /* NULL terminated */
2659 event->other [n + 1] = NULL;
2670 mono_class_alloc_ext (class);
2672 mono_image_lock (class->image);
2674 if (class->ext->events) {
2675 mono_image_unlock (class->image);
2679 class->ext->event.first = first;
2680 class->ext->event.count = count;
2682 /* Flush any pending writes as we do double checked locking on class->ext.events */
2683 mono_memory_barrier ();
2685 /* Leave this assignment as the last op in the function */
2686 class->ext->events = events;
2688 mono_image_unlock (class->image);
2692 * Global pool of interface IDs, represented as a bitset.
2693 * LOCKING: Protected by the classes lock.
2695 static MonoBitSet *global_interface_bitset = NULL;
2698 * mono_unload_interface_ids:
2699 * @bitset: bit set of interface IDs
2701 * When an image is unloaded, the interface IDs associated with
2702 * the image are put back in the global pool of IDs so the numbers
2706 mono_unload_interface_ids (MonoBitSet *bitset)
2709 mono_bitset_sub (global_interface_bitset, bitset);
2714 mono_unload_interface_id (MonoClass *class)
2716 if (global_interface_bitset && class->interface_id) {
2718 mono_bitset_clear (global_interface_bitset, class->interface_id);
2724 * mono_get_unique_iid:
2727 * Assign a unique integer ID to the interface represented by @class.
2728 * The ID will positive and as small as possible.
2729 * LOCKING: Acquires the classes lock.
2730 * Returns: the new ID.
2733 mono_get_unique_iid (MonoClass *class)
2737 g_assert (MONO_CLASS_IS_INTERFACE (class));
2741 if (!global_interface_bitset) {
2742 global_interface_bitset = mono_bitset_new (128, 0);
2745 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2747 int old_size = mono_bitset_size (global_interface_bitset);
2748 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2749 mono_bitset_free (global_interface_bitset);
2750 global_interface_bitset = new_set;
2753 mono_bitset_set (global_interface_bitset, iid);
2754 /* set the bit also in the per-image set */
2755 if (!class->generic_class) {
2756 if (class->image->interface_bitset) {
2757 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2758 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2759 mono_bitset_free (class->image->interface_bitset);
2760 class->image->interface_bitset = new_set;
2763 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2765 mono_bitset_set (class->image->interface_bitset, iid);
2770 #ifndef MONO_SMALL_CONFIG
2771 if (mono_print_vtable) {
2773 char *type_name = mono_type_full_name (&class->byval_arg);
2774 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2775 generic_id = class->generic_class->context.class_inst->id;
2776 g_assert (generic_id != 0);
2780 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2785 g_assert (iid <= 65535);
2790 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2795 mono_class_setup_interfaces (klass, error);
2796 if (!mono_error_ok (error))
2799 for (i = 0; i < klass->interface_count; i++) {
2800 ic = klass->interfaces [i];
2803 *res = g_ptr_array_new ();
2804 g_ptr_array_add (*res, ic);
2805 mono_class_init (ic);
2806 if (ic->exception_type) {
2807 mono_error_set_type_load_class (error, ic, "Error Loading class");
2811 collect_implemented_interfaces_aux (ic, res, error);
2812 if (!mono_error_ok (error))
2818 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2820 GPtrArray *res = NULL;
2822 collect_implemented_interfaces_aux (klass, &res, error);
2823 if (!mono_error_ok (error)) {
2825 g_ptr_array_free (res, TRUE);
2832 compare_interface_ids (const void *p_key, const void *p_element) {
2833 const MonoClass *key = p_key;
2834 const MonoClass *element = *(MonoClass**) p_element;
2836 return (key->interface_id - element->interface_id);
2839 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2841 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2842 MonoClass **result = mono_binary_search (
2844 klass->interfaces_packed,
2845 klass->interface_offsets_count,
2846 sizeof (MonoClass *),
2847 compare_interface_ids);
2849 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2856 * mono_class_interface_offset_with_variance:
2858 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2859 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2861 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2863 * FIXME figure out MS disambiguation rules and fix this function.
2866 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2867 int i = mono_class_interface_offset (klass, itf);
2868 *non_exact_match = FALSE;
2872 if (!mono_class_has_variant_generic_params (itf))
2875 for (i = 0; i < klass->interface_offsets_count; i++) {
2876 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2877 *non_exact_match = TRUE;
2878 return klass->interface_offsets_packed [i];
2886 print_implemented_interfaces (MonoClass *klass) {
2889 GPtrArray *ifaces = NULL;
2891 int ancestor_level = 0;
2893 name = mono_type_get_full_name (klass);
2894 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2897 for (i = 0; i < klass->interface_offsets_count; i++)
2898 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2899 klass->interfaces_packed [i]->interface_id,
2900 klass->interface_offsets_packed [i],
2901 klass->interfaces_packed [i]->method.count,
2902 klass->interfaces_packed [i]->name_space,
2903 klass->interfaces_packed [i]->name );
2904 printf ("Interface flags: ");
2905 for (i = 0; i <= klass->max_interface_id; i++)
2906 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2907 printf ("(%d,T)", i);
2909 printf ("(%d,F)", i);
2911 printf ("Dump interface flags:");
2912 #ifdef COMPRESSED_INTERFACE_BITMAP
2914 const uint8_t* p = klass->interface_bitmap;
2915 i = klass->max_interface_id;
2917 printf (" %d x 00 %02X", p [0], p [1]);
2923 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2924 printf (" %02X", klass->interface_bitmap [i]);
2927 while (klass != NULL) {
2928 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2929 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2930 if (!mono_error_ok (&error)) {
2931 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2932 mono_error_cleanup (&error);
2933 } else if (ifaces) {
2934 for (i = 0; i < ifaces->len; i++) {
2935 MonoClass *ic = g_ptr_array_index (ifaces, i);
2936 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2937 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2939 mono_class_interface_offset (klass, ic),
2944 g_ptr_array_free (ifaces, TRUE);
2947 klass = klass->parent;
2952 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2955 args [0] = &arg0->byval_arg;
2957 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2961 array_class_get_if_rank (MonoClass *class, guint rank)
2963 return rank ? mono_array_class_get (class, rank) : class;
2967 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2969 valuetype_types [0] = eclass;
2970 if (eclass == mono_defaults.int16_class)
2971 valuetype_types [1] = mono_defaults.uint16_class;
2972 else if (eclass == mono_defaults.uint16_class)
2973 valuetype_types [1] = mono_defaults.int16_class;
2974 else if (eclass == mono_defaults.int32_class)
2975 valuetype_types [1] = mono_defaults.uint32_class;
2976 else if (eclass == mono_defaults.uint32_class)
2977 valuetype_types [1] = mono_defaults.int32_class;
2978 else if (eclass == mono_defaults.int64_class)
2979 valuetype_types [1] = mono_defaults.uint64_class;
2980 else if (eclass == mono_defaults.uint64_class)
2981 valuetype_types [1] = mono_defaults.int64_class;
2982 else if (eclass == mono_defaults.byte_class)
2983 valuetype_types [1] = mono_defaults.sbyte_class;
2984 else if (eclass == mono_defaults.sbyte_class)
2985 valuetype_types [1] = mono_defaults.byte_class;
2986 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2987 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2990 /* this won't be needed once bug #325495 is completely fixed
2991 * though we'll need something similar to know which interfaces to allow
2992 * in arrays when they'll be lazyly created
2994 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2995 * MS returns diferrent types based on which instance is called. For example:
2996 * object obj = new byte[10][];
2997 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2998 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3001 * Fixing this should kill quite some code, save some bits and improve compatibility.
3004 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3006 MonoClass *eclass = class->element_class;
3007 static MonoClass* generic_icollection_class = NULL;
3008 static MonoClass* generic_ienumerable_class = NULL;
3009 static MonoClass* generic_ienumerator_class = NULL;
3010 static MonoClass* generic_ireadonlylist_class = NULL;
3011 static MonoClass* generic_ireadonlycollection_class = NULL;
3012 MonoClass *valuetype_types[2] = { NULL, NULL };
3013 MonoClass **interfaces = NULL;
3014 int i, nifaces, interface_count, real_count, original_rank;
3016 gboolean internal_enumerator;
3017 gboolean eclass_is_valuetype;
3019 if (!mono_defaults.generic_ilist_class) {
3023 internal_enumerator = FALSE;
3024 eclass_is_valuetype = FALSE;
3025 original_rank = eclass->rank;
3026 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3027 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3029 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3031 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3032 original_rank = eclass->rank;
3034 eclass = eclass->element_class;
3035 internal_enumerator = TRUE;
3036 *is_enumerator = TRUE;
3044 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3045 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3047 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3049 if (!generic_icollection_class) {
3050 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3051 "System.Collections.Generic", "ICollection`1");
3052 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3053 "System.Collections.Generic", "IEnumerable`1");
3054 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3055 "System.Collections.Generic", "IEnumerator`1");
3056 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3057 "System.Collections.Generic", "IReadOnlyList`1");
3058 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3059 "System.Collections.Generic", "IReadOnlyCollection`1");
3062 mono_class_init (eclass);
3065 * Arrays in 2.0 need to implement a number of generic interfaces
3066 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3067 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3068 * We collect the types needed to build the
3069 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3070 * the generic interfaces needed to implement.
3072 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3073 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3075 if (eclass->valuetype) {
3076 nifaces = generic_ireadonlylist_class ? 5 : 3;
3077 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3079 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3080 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3081 if (internal_enumerator) {
3083 if (valuetype_types [1])
3087 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3088 interfaces [0] = valuetype_types [0];
3089 if (valuetype_types [1])
3090 interfaces [nifaces] = valuetype_types [1];
3092 eclass_is_valuetype = TRUE;
3095 int idepth = eclass->idepth;
3096 if (!internal_enumerator)
3098 nifaces = generic_ireadonlylist_class ? 2 : 3;
3100 // FIXME: This doesn't seem to work/required for generic params
3101 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3102 mono_class_setup_interface_offsets (eclass);
3104 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3105 /* we add object for interfaces and the supertypes for the other
3106 * types. The last of the supertypes is the element class itself which we
3107 * already created the explicit interfaces for (so we include it for IEnumerator
3108 * and exclude it for arrays).
3110 if (MONO_CLASS_IS_INTERFACE (eclass))
3113 interface_count += idepth;
3114 if (eclass->rank && eclass->element_class->valuetype) {
3115 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3116 if (valuetype_types [1])
3119 /* IList, ICollection, IEnumerable, IReadOnlyList */
3120 interface_count *= nifaces;
3121 real_count = interface_count;
3122 if (internal_enumerator) {
3123 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3124 if (valuetype_types [1])
3127 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3128 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3129 interfaces [0] = mono_defaults.object_class;
3133 for (i = 0; i < idepth; i++) {
3134 mono_class_init (eclass->supertypes [i]);
3135 interfaces [j] = eclass->supertypes [i];
3139 if (all_interfaces) {
3140 for (i = 0; i < eclass->interface_offsets_count; i++) {
3141 interfaces [j] = eclass->interfaces_packed [i];
3145 for (i = 0; i < eclass->interface_count; i++) {
3146 interfaces [j] = eclass->interfaces [i];
3150 if (valuetype_types [1]) {
3151 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3156 /* instantiate the generic interfaces */
3157 for (i = 0; i < interface_count; i += nifaces) {
3158 MonoClass *iface = interfaces [i];
3160 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3161 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3163 if (eclass->valuetype) {
3164 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3165 if (generic_ireadonlylist_class) {
3166 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3167 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3170 if (!generic_ireadonlylist_class)
3171 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3174 if (internal_enumerator) {
3176 /* instantiate IEnumerator<iface> */
3177 for (i = 0; i < interface_count; i++) {
3178 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3180 j = interface_count;
3181 if (!eclass_is_valuetype) {
3182 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3183 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3186 for (i = 0; i < eclass->idepth; i++) {
3187 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3191 for (i = 0; i < eclass->interface_offsets_count; i++) {
3192 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3196 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3198 if (valuetype_types [1])
3199 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3203 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3204 for (i = 0; i < real_count; ++i) {
3205 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3206 g_print ("%s implements %s\n", type_name, name);
3217 find_array_interface (MonoClass *klass, const char *name)
3220 for (i = 0; i < klass->interface_count; ++i) {
3221 if (strcmp (klass->interfaces [i]->name, name) == 0)
3228 * Return the number of virtual methods.
3229 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3230 * Return -1 on failure.
3231 * FIXME It would be nice if this information could be cached somewhere.
3234 count_virtual_methods (MonoClass *class)
3238 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3240 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3241 mono_class_setup_methods (class);
3242 if (class->exception_type)
3245 for (i = 0; i < class->method.count; ++i) {
3246 flags = class->methods [i]->flags;
3247 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3251 for (i = 0; i < class->method.count; ++i) {
3252 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3254 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3262 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3270 m = (l + num_ifaces) / 2;
3271 if (interfaces_full [m] == ic)
3273 if (l == num_ifaces)
3275 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3284 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3286 int i = find_interface (num_ifaces, interfaces_full, ic);
3288 return interface_offsets_full [i];
3293 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3295 int i = find_interface (num_ifaces, interfaces_full, ic);
3299 interface_offsets_full [i] = offset;
3302 for (i = 0; i < num_ifaces; ++i) {
3303 if (interfaces_full [i]) {
3305 if (interfaces_full [i]->interface_id < ic->interface_id)
3308 while (end < num_ifaces && interfaces_full [end]) end++;
3309 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3310 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3312 interfaces_full [i] = ic;
3313 interface_offsets_full [i] = offset;
3319 #ifdef COMPRESSED_INTERFACE_BITMAP
3322 * Compressed interface bitmap design.
3324 * Interface bitmaps take a large amount of memory, because their size is
3325 * linear with the maximum interface id assigned in the process (each interface
3326 * is assigned a unique id as it is loaded). The number of interface classes
3327 * is high because of the many implicit interfaces implemented by arrays (we'll
3328 * need to lazy-load them in the future).
3329 * Most classes implement a very small number of interfaces, so the bitmap is
3330 * sparse. This bitmap needs to be checked by interface casts, so access to the
3331 * needed bit must be fast and doable with few jit instructions.
3333 * The current compression format is as follows:
3334 * *) it is a sequence of one or more two-byte elements
3335 * *) the first byte in the element is the count of empty bitmap bytes
3336 * at the current bitmap position
3337 * *) the second byte in the element is an actual bitmap byte at the current
3340 * As an example, the following compressed bitmap bytes:
3341 * 0x07 0x01 0x00 0x7
3342 * correspond to the following bitmap:
3343 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3345 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3346 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3347 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3351 * mono_compress_bitmap:
3352 * @dest: destination buffer
3353 * @bitmap: bitmap buffer
3354 * @size: size of @bitmap in bytes
3356 * This is a mono internal function.
3357 * The @bitmap data is compressed into a format that is small but
3358 * still searchable in few instructions by the JIT and runtime.
3359 * The compressed data is stored in the buffer pointed to by the
3360 * @dest array. Passing a #NULL value for @dest allows to just compute
3361 * the size of the buffer.
3362 * This compression algorithm assumes the bits set in the bitmap are
3363 * few and far between, like in interface bitmaps.
3364 * Returns: the size of the compressed bitmap in bytes.
3367 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3371 const uint8_t *end = bitmap + size;
3372 while (bitmap < end) {
3373 if (*bitmap || numz == 255) {
3397 * mono_class_interface_match:
3398 * @bitmap: a compressed bitmap buffer
3399 * @id: the index to check in the bitmap
3401 * This is a mono internal function.
3402 * Checks if a bit is set in a compressed interface bitmap. @id must
3403 * be already checked for being smaller than the maximum id encoded in the
3406 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3410 mono_class_interface_match (const uint8_t *bitmap, int id)
3413 id -= bitmap [0] * 8;
3417 return bitmap [1] & (1 << id);
3426 * LOCKING: this is supposed to be called with the loader lock held.
3427 * Return -1 on failure and set exception_type
3430 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3434 int i, j, max_iid, num_ifaces;
3435 MonoClass **interfaces_full = NULL;
3436 int *interface_offsets_full = NULL;
3438 GPtrArray **ifaces_array = NULL;
3439 int interface_offsets_count;
3440 MonoClass **array_interfaces = NULL;
3441 int num_array_interfaces;
3442 int is_enumerator = FALSE;
3444 mono_class_setup_supertypes (class);
3446 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3447 * implicit interfaces have the property that they are assigned the same slot in the
3448 * vtables for compatible interfaces
3450 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3452 /* compute maximum number of slots and maximum interface id */
3454 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3455 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3456 for (j = 0; j < class->idepth; j++) {
3457 k = class->supertypes [j];
3458 num_ifaces += k->interface_count;
3459 for (i = 0; i < k->interface_count; i++) {
3460 ic = k->interfaces [i];
3463 mono_class_init (ic);
3465 if (max_iid < ic->interface_id)
3466 max_iid = ic->interface_id;
3468 ifaces = mono_class_get_implemented_interfaces (k, &error);
3469 if (!mono_error_ok (&error)) {
3470 char *name = mono_type_get_full_name (k);
3471 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)));
3473 mono_error_cleanup (&error);
3478 num_ifaces += ifaces->len;
3479 for (i = 0; i < ifaces->len; ++i) {
3480 ic = g_ptr_array_index (ifaces, i);
3481 if (max_iid < ic->interface_id)
3482 max_iid = ic->interface_id;
3484 ifaces_array [j] = ifaces;
3488 for (i = 0; i < num_array_interfaces; ++i) {
3489 ic = array_interfaces [i];
3490 mono_class_init (ic);
3491 if (max_iid < ic->interface_id)
3492 max_iid = ic->interface_id;
3495 if (MONO_CLASS_IS_INTERFACE (class)) {
3497 if (max_iid < class->interface_id)
3498 max_iid = class->interface_id;
3500 class->max_interface_id = max_iid;
3501 /* compute vtable offset for interfaces */
3502 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3503 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3505 for (i = 0; i < num_ifaces; i++) {
3506 interface_offsets_full [i] = -1;
3509 /* skip the current class */
3510 for (j = 0; j < class->idepth - 1; j++) {
3511 k = class->supertypes [j];
3512 ifaces = ifaces_array [j];
3515 for (i = 0; i < ifaces->len; ++i) {
3517 ic = g_ptr_array_index (ifaces, i);
3519 /*Force the sharing of interface offsets between parent and subtypes.*/
3520 io = mono_class_interface_offset (k, ic);
3522 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3527 g_assert (class == class->supertypes [class->idepth - 1]);
3528 ifaces = ifaces_array [class->idepth - 1];
3530 for (i = 0; i < ifaces->len; ++i) {
3532 ic = g_ptr_array_index (ifaces, i);
3533 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3535 count = count_virtual_methods (ic);
3537 char *name = mono_type_get_full_name (ic);
3538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3547 if (MONO_CLASS_IS_INTERFACE (class))
3548 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3550 if (num_array_interfaces) {
3551 if (is_enumerator) {
3552 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3553 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3554 g_assert (ienumerator_offset >= 0);
3555 for (i = 0; i < num_array_interfaces; ++i) {
3556 ic = array_interfaces [i];
3557 if (strcmp (ic->name, "IEnumerator`1") == 0)
3558 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3560 g_assert_not_reached ();
3561 /*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);*/
3564 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3565 int ilist_iface_idx = find_array_interface (class, "IList`1");
3566 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3567 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3568 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3569 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3570 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3571 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3572 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3573 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3574 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3575 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3576 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3577 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3578 for (i = 0; i < num_array_interfaces; ++i) {
3580 ic = array_interfaces [i];
3581 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3582 offset = ilist_offset;
3583 else if (strcmp (ic->name, "ICollection`1") == 0)
3584 offset = icollection_offset;
3585 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3586 offset = ienumerable_offset;
3587 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3588 offset = ireadonlylist_offset;
3589 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3590 offset = ireadonlycollection_offset;
3592 g_assert_not_reached ();
3593 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3594 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3599 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3600 if (interface_offsets_full [i] != -1) {
3601 interface_offsets_count ++;
3606 * We might get called multiple times:
3607 * - mono_class_init ()
3608 * - mono_class_setup_vtable ().
3609 * - mono_class_setup_interface_offsets ().
3610 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3611 * means we have to overwrite those when called from other places (#4440).
3613 if (class->interfaces_packed && !overwrite) {
3614 g_assert (class->interface_offsets_count == interface_offsets_count);
3618 class->interface_offsets_count = interface_offsets_count;
3619 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3620 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3621 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3622 #ifdef COMPRESSED_INTERFACE_BITMAP
3623 bitmap = g_malloc0 (bsize);
3625 bitmap = mono_class_alloc0 (class, bsize);
3627 for (i = 0; i < interface_offsets_count; i++) {
3628 int id = interfaces_full [i]->interface_id;
3629 bitmap [id >> 3] |= (1 << (id & 7));
3630 class->interfaces_packed [i] = interfaces_full [i];
3631 class->interface_offsets_packed [i] = interface_offsets_full [i];
3632 /*if (num_array_interfaces)
3633 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]);*/
3635 #ifdef COMPRESSED_INTERFACE_BITMAP
3636 i = mono_compress_bitmap (NULL, bitmap, bsize);
3637 class->interface_bitmap = mono_class_alloc0 (class, i);
3638 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3641 class->interface_bitmap = bitmap;
3646 g_free (interfaces_full);
3647 g_free (interface_offsets_full);
3648 g_free (array_interfaces);
3649 for (i = 0; i < class->idepth; i++) {
3650 ifaces = ifaces_array [i];
3652 g_ptr_array_free (ifaces, TRUE);
3654 g_free (ifaces_array);
3656 //printf ("JUST DONE: ");
3657 //print_implemented_interfaces (class);
3663 * Setup interface offsets for interfaces.
3665 * - class->max_interface_id
3666 * - class->interface_offsets_count
3667 * - class->interfaces_packed
3668 * - class->interface_offsets_packed
3669 * - class->interface_bitmap
3671 * This function can fail @class.
3674 mono_class_setup_interface_offsets (MonoClass *class)
3676 mono_loader_lock ();
3678 setup_interface_offsets (class, 0, FALSE);
3680 mono_loader_unlock ();
3683 /*Checks if @klass has @parent as one of it's parents type gtd
3687 * Bar<T> : Foo<Bar<Bar<T>>>
3691 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3693 klass = mono_class_get_generic_type_definition (klass);
3694 parent = mono_class_get_generic_type_definition (parent);
3695 mono_class_setup_supertypes (klass);
3696 mono_class_setup_supertypes (parent);
3698 return klass->idepth >= parent->idepth &&
3699 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3703 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3705 MonoGenericInst *ginst;
3707 if (!class->generic_class) {
3708 mono_class_setup_vtable_full (class, in_setup);
3709 return class->exception_type == 0;
3712 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3713 if (class->generic_class->container_class->exception_type) {
3714 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3718 ginst = class->generic_class->context.class_inst;
3719 for (i = 0; i < ginst->type_argc; ++i) {
3721 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3723 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3724 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3725 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3727 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3728 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3736 * mono_class_setup_vtable:
3738 * Creates the generic vtable of CLASS.
3739 * Initializes the following fields in MonoClass:
3742 * Plus all the fields initialized by setup_interface_offsets ().
3743 * If there is an error during vtable construction, class->exception_type is set.
3745 * LOCKING: Acquires the loader lock.
3748 mono_class_setup_vtable (MonoClass *class)
3750 mono_class_setup_vtable_full (class, NULL);
3754 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3756 MonoMethod **overrides;
3757 MonoGenericContext *context;
3765 if (MONO_CLASS_IS_INTERFACE (class)) {
3766 /* This sets method->slot for all methods if this is an interface */
3767 mono_class_setup_methods (class);
3771 if (class->exception_type)
3774 if (g_list_find (in_setup, class))
3777 mono_loader_lock ();
3779 if (class->vtable) {
3780 mono_loader_unlock ();
3784 mono_stats.generic_vtable_count ++;
3785 in_setup = g_list_prepend (in_setup, class);
3787 if (class->generic_class) {
3788 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3789 mono_loader_unlock ();
3790 g_list_remove (in_setup, class);
3794 context = mono_class_get_context (class);
3795 type_token = class->generic_class->container_class->type_token;
3797 context = (MonoGenericContext *) class->generic_container;
3798 type_token = class->type_token;
3801 if (image_is_dynamic (class->image)) {
3802 /* Generic instances can have zero method overrides without causing any harm.
3803 * This is true since we don't do layout all over again for them, we simply inflate
3804 * the layout of the parent.
3806 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3808 /* The following call fails if there are missing methods in the type */
3809 /* FIXME it's probably a good idea to avoid this for generic instances. */
3810 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3814 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3816 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3820 mono_loader_unlock ();
3821 g_list_remove (in_setup, class);
3826 #define DEBUG_INTERFACE_VTABLE_CODE 0
3827 #define TRACE_INTERFACE_VTABLE_CODE 0
3828 #define VERIFY_INTERFACE_VTABLE_CODE 0
3829 #define VTABLE_SELECTOR (1)
3831 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3832 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3833 if (!(VTABLE_SELECTOR)) break; \
3837 #define DEBUG_INTERFACE_VTABLE(stmt)
3840 #if TRACE_INTERFACE_VTABLE_CODE
3841 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3842 if (!(VTABLE_SELECTOR)) break; \
3846 #define TRACE_INTERFACE_VTABLE(stmt)
3849 #if VERIFY_INTERFACE_VTABLE_CODE
3850 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3851 if (!(VTABLE_SELECTOR)) break; \
3855 #define VERIFY_INTERFACE_VTABLE(stmt)
3859 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3861 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3865 GString *res = g_string_new ("");
3867 g_string_append_c (res, '(');
3868 for (i = 0; i < sig->param_count; ++i) {
3870 g_string_append_c (res, ',');
3871 mono_type_get_desc (res, sig->params [i], include_namespace);
3873 g_string_append (res, ")=>");
3874 if (sig->ret != NULL) {
3875 mono_type_get_desc (res, sig->ret, include_namespace);
3877 g_string_append (res, "NULL");
3880 g_string_free (res, FALSE);
3884 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3885 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3886 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3887 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3895 is_wcf_hack_disabled (void)
3897 static gboolean disabled;
3898 static gboolean inited = FALSE;
3900 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3907 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
3908 MonoMethodSignature *cmsig, *imsig;
3909 if (strcmp (im->name, cm->name) == 0) {
3910 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3911 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3914 if (! slot_is_empty) {
3915 if (require_newslot) {
3916 if (! interface_is_explicitly_implemented_by_class) {
3917 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3920 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3921 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3925 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3928 cmsig = mono_method_signature (cm);
3929 imsig = mono_method_signature (im);
3930 if (!cmsig || !imsig) {
3931 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3935 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3936 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3937 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3938 TRACE_INTERFACE_VTABLE (printf ("]"));
3941 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3942 /* CAS - SecurityAction.InheritanceDemand on interface */
3943 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3944 mono_secman_inheritancedemand_method (cm, im);
3947 if (mono_security_core_clr_enabled ())
3948 mono_security_core_clr_check_override (class, cm, im);
3950 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3951 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3952 char *body_name = mono_method_full_name (cm, TRUE);
3953 char *decl_name = mono_method_full_name (im, TRUE);
3954 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));
3962 MonoClass *ic = im->klass;
3963 const char *ic_name_space = ic->name_space;
3964 const char *ic_name = ic->name;
3967 if (! require_newslot) {
3968 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3971 if (cm->klass->rank == 0) {
3972 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3975 cmsig = mono_method_signature (cm);
3976 imsig = mono_method_signature (im);
3977 if (!cmsig || !imsig) {
3978 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3982 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3983 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3984 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3985 TRACE_INTERFACE_VTABLE (printf ("]"));
3988 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3989 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3992 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3993 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3996 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))) {
3997 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4001 subname = strstr (cm->name, ic_name_space);
4002 if (subname != cm->name) {
4003 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4006 subname += strlen (ic_name_space);
4007 if (subname [0] != '.') {
4008 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4012 if (strstr (subname, ic_name) != subname) {
4013 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4016 subname += strlen (ic_name);
4017 if (subname [0] != '.') {
4018 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4022 if (strcmp (subname, im->name) != 0) {
4023 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4027 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4028 /* CAS - SecurityAction.InheritanceDemand on interface */
4029 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4030 mono_secman_inheritancedemand_method (cm, im);
4033 if (mono_security_core_clr_enabled ())
4034 mono_security_core_clr_check_override (class, cm, im);
4036 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4037 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4038 char *body_name = mono_method_full_name (cm, TRUE);
4039 char *decl_name = mono_method_full_name (im, TRUE);
4040 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));
4050 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4052 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4053 MonoMethod *method = key;
4054 MonoMethod *override = value;
4055 MonoClass *method_class = mono_method_get_class (method);
4056 MonoClass *override_class = mono_method_get_class (override);
4058 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4059 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4060 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4063 print_overrides (GHashTable *override_map, const char *message) {
4065 printf ("Override map \"%s\" START:\n", message);
4066 g_hash_table_foreach (override_map, foreach_override, NULL);
4067 printf ("Override map \"%s\" END.\n", message);
4069 printf ("Override map \"%s\" EMPTY.\n", message);
4073 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4074 char *full_name = mono_type_full_name (&class->byval_arg);
4078 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4080 if (print_interfaces) {
4081 print_implemented_interfaces (class);
4082 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4085 if (class->parent) {
4086 parent_size = class->parent->vtable_size;
4090 for (i = 0; i < size; ++i) {
4091 MonoMethod *cm = vtable [i];
4092 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4093 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4095 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4103 #if VERIFY_INTERFACE_VTABLE_CODE
4105 mono_method_try_get_vtable_index (MonoMethod *method)
4107 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4108 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4109 if (imethod->declaring->is_generic)
4110 return imethod->declaring->slot;
4112 return method->slot;
4116 mono_class_verify_vtable (MonoClass *class)
4119 char *full_name = mono_type_full_name (&class->byval_arg);
4121 printf ("*** Verifying VTable of class '%s' \n", full_name);
4125 if (!class->methods)
4128 for (i = 0; i < class->method.count; ++i) {
4129 MonoMethod *cm = class->methods [i];
4132 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4136 full_name = mono_method_full_name (cm, TRUE);
4138 slot = mono_method_try_get_vtable_index (cm);
4140 if (slot >= class->vtable_size) {
4141 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4145 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4146 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4147 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4148 g_free (other_name);
4151 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4158 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4160 char *method_signature;
4163 for (index = 0; index < onum; ++index) {
4164 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4165 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4167 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4168 type_name = mono_type_full_name (&class->byval_arg);
4169 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4170 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4171 g_free (method_signature);
4173 mono_class_setup_methods (class);
4174 if (class->exception_type) {
4175 char *name = mono_type_get_full_name (class);
4176 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4180 for (index = 0; index < class->method.count; ++index) {
4181 MonoMethod *cm = class->methods [index];
4182 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4184 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4185 g_free (method_signature);
4190 mono_method_get_method_definition (MonoMethod *method)
4192 while (method->is_inflated)
4193 method = ((MonoMethodInflated*)method)->declaring;
4198 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4202 for (i = 0; i < onum; ++i) {
4203 MonoMethod *decl = overrides [i * 2];
4204 MonoMethod *body = overrides [i * 2 + 1];
4206 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4207 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4211 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4212 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4213 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4215 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4219 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4220 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4221 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4223 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4227 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4228 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4232 body = mono_method_get_method_definition (body);
4233 decl = mono_method_get_method_definition (decl);
4235 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4236 char *body_name = mono_method_full_name (body, TRUE);
4237 char *decl_name = mono_method_full_name (decl, TRUE);
4238 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));
4248 mono_class_need_stelemref_method (MonoClass *class)
4250 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4254 * LOCKING: this is supposed to be called with the loader lock held.
4257 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4261 MonoMethod **vtable;
4262 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4263 GPtrArray *ifaces = NULL;
4264 GHashTable *override_map = NULL;
4265 gboolean security_enabled = mono_security_enabled ();
4267 gpointer class_iter;
4268 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4269 int first_non_interface_slot;
4271 GSList *virt_methods = NULL, *l;
4272 int stelemref_slot = 0;
4277 if (overrides && !verify_class_overrides (class, overrides, onum))
4280 ifaces = mono_class_get_implemented_interfaces (class, &error);
4281 if (!mono_error_ok (&error)) {
4282 char *name = mono_type_get_full_name (class);
4283 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)));
4285 mono_error_cleanup (&error);
4287 } else if (ifaces) {
4288 for (i = 0; i < ifaces->len; i++) {
4289 MonoClass *ic = g_ptr_array_index (ifaces, i);
4290 max_vtsize += ic->method.count;
4292 g_ptr_array_free (ifaces, TRUE);
4296 if (class->parent) {
4297 mono_class_init (class->parent);
4298 mono_class_setup_vtable_full (class->parent, in_setup);
4300 if (class->parent->exception_type) {
4301 char *name = mono_type_get_full_name (class->parent);
4302 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4307 max_vtsize += class->parent->vtable_size;
4308 cur_slot = class->parent->vtable_size;
4311 max_vtsize += class->method.count;
4313 /*Array have a slot for stelemref*/
4314 if (mono_class_need_stelemref_method (class)) {
4315 stelemref_slot = cur_slot;
4320 vtable = alloca (sizeof (gpointer) * max_vtsize);
4321 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4323 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4325 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4326 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4329 max_iid = class->max_interface_id;
4330 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4332 /* Optimized version for generic instances */
4333 if (class->generic_class) {
4335 MonoClass *gklass = class->generic_class->container_class;
4338 mono_class_setup_vtable_full (gklass, in_setup);
4339 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4340 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4344 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4345 class->vtable_size = gklass->vtable_size;
4346 for (i = 0; i < gklass->vtable_size; ++i)
4347 if (gklass->vtable [i]) {
4348 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4349 if (!mono_error_ok (&error)) {
4350 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4351 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4353 mono_error_cleanup (&error);
4357 tmp [i]->slot = gklass->vtable [i]->slot;
4359 mono_memory_barrier ();
4360 class->vtable = tmp;
4362 /* Have to set method->slot for abstract virtual methods */
4363 if (class->methods && gklass->methods) {
4364 for (i = 0; i < class->method.count; ++i)
4365 if (class->methods [i]->slot == -1)
4366 class->methods [i]->slot = gklass->methods [i]->slot;
4372 if (class->parent && class->parent->vtable_size) {
4373 MonoClass *parent = class->parent;
4376 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4378 // Also inherit parent interface vtables, just as a starting point.
4379 // This is needed otherwise bug-77127.exe fails when the property methods
4380 // have different names in the iterface and the class, because for child
4381 // classes the ".override" information is not used anymore.
4382 for (i = 0; i < parent->interface_offsets_count; i++) {
4383 MonoClass *parent_interface = parent->interfaces_packed [i];
4384 int interface_offset = mono_class_interface_offset (class, parent_interface);
4385 /*FIXME this is now dead code as this condition will never hold true.
4386 Since interface offsets are inherited then the offset of an interface implemented
4387 by a parent will never be the out of it's vtable boundary.
4389 if (interface_offset >= parent->vtable_size) {
4390 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4393 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4394 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4395 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4396 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4397 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4398 parent_interface_offset + j, parent_interface_offset, j,
4399 interface_offset + j, interface_offset, j));
4406 /*Array have a slot for stelemref*/
4407 if (mono_class_need_stelemref_method (class)) {
4408 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4410 method->slot = stelemref_slot;
4412 g_assert (method->slot == stelemref_slot);
4414 vtable [stelemref_slot] = method;
4417 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4418 /* override interface methods */
4419 for (i = 0; i < onum; i++) {
4420 MonoMethod *decl = overrides [i*2];
4421 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4423 dslot = mono_method_get_vtable_slot (decl);
4425 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4429 dslot += mono_class_interface_offset (class, decl->klass);
4430 vtable [dslot] = overrides [i*2 + 1];
4431 vtable [dslot]->slot = dslot;
4433 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4435 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4437 if (mono_security_core_clr_enabled ())
4438 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4441 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4442 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4445 * Create a list of virtual methods to avoid calling
4446 * mono_class_get_virtual_methods () which is slow because of the metadata
4450 gpointer iter = NULL;
4453 virt_methods = NULL;
4454 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4455 virt_methods = g_slist_prepend (virt_methods, cm);
4457 if (class->exception_type)
4461 // Loop on all implemented interfaces...
4462 for (i = 0; i < class->interface_offsets_count; i++) {
4463 MonoClass *parent = class->parent;
4465 gboolean interface_is_explicitly_implemented_by_class;
4468 ic = class->interfaces_packed [i];
4469 ic_offset = mono_class_interface_offset (class, ic);
4471 mono_class_setup_methods (ic);
4472 if (ic->exception_type)
4475 // Check if this interface is explicitly implemented (instead of just inherited)
4476 if (parent != NULL) {
4477 int implemented_interfaces_index;
4478 interface_is_explicitly_implemented_by_class = FALSE;
4479 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4480 if (ic == class->interfaces [implemented_interfaces_index]) {
4481 interface_is_explicitly_implemented_by_class = TRUE;
4486 interface_is_explicitly_implemented_by_class = TRUE;
4489 // Loop on all interface methods...
4490 for (im_index = 0; im_index < ic->method.count; im_index++) {
4491 MonoMethod *im = ic->methods [im_index];
4492 int im_slot = ic_offset + im->slot;
4493 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4495 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4498 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4500 // If there is an explicit implementation, just use it right away,
4501 // otherwise look for a matching method
4502 if (override_im == NULL) {
4507 // First look for a suitable method among the class methods
4509 for (l = virt_methods; l; l = l->next) {
4511 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)));
4512 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4513 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4514 vtable [im_slot] = cm;
4515 /* Why do we need this? */
4520 TRACE_INTERFACE_VTABLE (printf ("\n"));
4521 if (class->exception_type) /*Might be set by check_interface_method_override*/
4525 // If the slot is still empty, look in all the inherited virtual methods...
4526 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4527 MonoClass *parent = class->parent;
4528 // Reverse order, so that last added methods are preferred
4529 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4530 MonoMethod *cm = parent->vtable [cm_index];
4532 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));
4533 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4534 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4535 vtable [im_slot] = cm;
4536 /* Why do we need this? */
4542 if (class->exception_type) /*Might be set by check_interface_method_override*/
4544 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4548 g_assert (vtable [im_slot] == override_im);
4553 // If the class is not abstract, check that all its interface slots are full.
4554 // The check is done here and not directly at the end of the loop above because
4555 // it can happen (for injected generic array interfaces) that the same slot is
4556 // processed multiple times (those interfaces have overlapping slots), and it
4557 // will not always be the first pass the one that fills the slot.
4558 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4559 for (i = 0; i < class->interface_offsets_count; i++) {
4563 ic = class->interfaces_packed [i];
4564 ic_offset = mono_class_interface_offset (class, ic);
4566 for (im_index = 0; im_index < ic->method.count; im_index++) {
4567 MonoMethod *im = ic->methods [im_index];
4568 int im_slot = ic_offset + im->slot;
4570 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4573 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4574 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4575 if (vtable [im_slot] == NULL) {
4576 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4583 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4585 for (l = virt_methods; l; l = l->next) {
4588 * If the method is REUSE_SLOT, we must check in the
4589 * base class for a method to override.
4591 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4593 for (k = class->parent; k ; k = k->parent) {
4598 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4599 MonoMethodSignature *cmsig, *m1sig;
4601 cmsig = mono_method_signature (cm);
4602 m1sig = mono_method_signature (m1);
4604 if (!cmsig || !m1sig) {
4605 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4609 if (!strcmp(cm->name, m1->name) &&
4610 mono_metadata_signature_equal (cmsig, m1sig)) {
4612 /* CAS - SecurityAction.InheritanceDemand */
4613 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4614 mono_secman_inheritancedemand_method (cm, m1);
4617 if (mono_security_core_clr_enabled ())
4618 mono_security_core_clr_check_override (class, cm, m1);
4620 slot = mono_method_get_vtable_slot (m1);
4624 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4625 char *body_name = mono_method_full_name (cm, TRUE);
4626 char *decl_name = mono_method_full_name (m1, TRUE);
4627 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));
4633 g_assert (cm->slot < max_vtsize);
4635 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4636 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4637 mono_method_full_name (m1, 1), m1,
4638 mono_method_full_name (cm, 1), cm));
4639 g_hash_table_insert (override_map, m1, cm);
4643 if (k->exception_type)
4653 /*Non final newslot methods must be given a non-interface vtable slot*/
4654 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4658 cm->slot = cur_slot++;
4660 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4661 vtable [cm->slot] = cm;
4664 /* override non interface methods */
4665 for (i = 0; i < onum; i++) {
4666 MonoMethod *decl = overrides [i*2];
4667 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4668 g_assert (decl->slot != -1);
4669 vtable [decl->slot] = overrides [i*2 + 1];
4670 overrides [i * 2 + 1]->slot = decl->slot;
4672 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4673 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4674 mono_method_full_name (decl, 1), decl,
4675 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4676 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4678 if (mono_security_core_clr_enabled ())
4679 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4684 * If a method occupies more than one place in the vtable, and it is
4685 * overriden, then change the other occurances too.
4690 for (i = 0; i < max_vtsize; ++i)
4692 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4694 cm = g_hash_table_lookup (override_map, vtable [i]);
4699 g_hash_table_destroy (override_map);
4700 override_map = NULL;
4703 g_slist_free (virt_methods);
4704 virt_methods = NULL;
4706 /* Ensure that all vtable slots are filled with concrete instance methods */
4707 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4708 for (i = 0; i < cur_slot; ++i) {
4709 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4710 char *type_name = mono_type_get_full_name (class);
4711 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4712 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));
4714 g_free (method_name);
4720 if (class->generic_class) {
4721 MonoClass *gklass = class->generic_class->container_class;
4723 mono_class_init (gklass);
4725 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4727 /* Check that the vtable_size value computed in mono_class_init () is correct */
4728 if (class->vtable_size)
4729 g_assert (cur_slot == class->vtable_size);
4730 class->vtable_size = cur_slot;
4733 /* Try to share the vtable with our parent. */
4734 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4735 mono_memory_barrier ();
4736 class->vtable = class->parent->vtable;
4738 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4739 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4740 mono_memory_barrier ();
4741 class->vtable = tmp;
4744 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4745 if (mono_print_vtable) {
4748 print_implemented_interfaces (class);
4750 for (i = 0; i <= max_iid; i++)
4751 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4754 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4755 class->vtable_size, icount);
4757 for (i = 0; i < cur_slot; ++i) {
4762 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4763 mono_method_full_name (cm, TRUE));
4769 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4770 class->name, max_iid);
4772 for (i = 0; i < class->interface_count; i++) {
4773 ic = class->interfaces [i];
4774 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4775 mono_class_interface_offset (class, ic),
4776 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4779 for (k = class->parent; k ; k = k->parent) {
4780 for (i = 0; i < k->interface_count; i++) {
4781 ic = k->interfaces [i];
4782 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4783 mono_class_interface_offset (class, ic),
4784 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4790 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4795 char *name = mono_type_get_full_name (class);
4796 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4799 g_hash_table_destroy (override_map);
4801 g_slist_free (virt_methods);
4806 * mono_method_get_vtable_slot:
4808 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4809 * LOCKING: Acquires the loader lock.
4811 * FIXME Use proper MonoError machinery here.
4814 mono_method_get_vtable_slot (MonoMethod *method)
4816 if (method->slot == -1) {
4817 mono_class_setup_vtable (method->klass);
4818 if (method->klass->exception_type)
4820 if (method->slot == -1) {
4824 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4825 g_assert (method->klass->generic_class);
4826 gklass = method->klass->generic_class->container_class;
4827 mono_class_setup_methods (method->klass);
4828 g_assert (method->klass->methods);
4829 for (i = 0; i < method->klass->method.count; ++i) {
4830 if (method->klass->methods [i] == method)
4833 g_assert (i < method->klass->method.count);
4834 g_assert (gklass->methods);
4835 method->slot = gklass->methods [i]->slot;
4837 g_assert (method->slot != -1);
4839 return method->slot;
4843 * mono_method_get_vtable_index:
4846 * Returns the index into the runtime vtable to access the method or,
4847 * in the case of a virtual generic method, the virtual generic method
4848 * thunk. Returns -1 on failure.
4850 * FIXME Use proper MonoError machinery here.
4853 mono_method_get_vtable_index (MonoMethod *method)
4855 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4856 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4857 if (imethod->declaring->is_generic)
4858 return mono_method_get_vtable_slot (imethod->declaring);
4860 return mono_method_get_vtable_slot (method);
4863 static MonoMethod *default_ghc = NULL;
4864 static MonoMethod *default_finalize = NULL;
4865 static int finalize_slot = -1;
4866 static int ghc_slot = -1;
4869 initialize_object_slots (MonoClass *class)
4874 if (class == mono_defaults.object_class) {
4875 mono_class_setup_vtable (class);
4876 for (i = 0; i < class->vtable_size; ++i) {
4877 MonoMethod *cm = class->vtable [i];
4879 if (!strcmp (cm->name, "GetHashCode"))
4881 else if (!strcmp (cm->name, "Finalize"))
4885 g_assert (ghc_slot > 0);
4886 default_ghc = class->vtable [ghc_slot];
4888 g_assert (finalize_slot > 0);
4889 default_finalize = class->vtable [finalize_slot];
4894 MonoMethod *array_method;
4896 } GenericArrayMethodInfo;
4898 static int generic_array_method_num = 0;
4899 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4902 generic_array_methods (MonoClass *class)
4904 int i, count_generic = 0;
4905 GList *list = NULL, *tmp;
4906 if (generic_array_method_num)
4907 return generic_array_method_num;
4908 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4909 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4910 for (i = 0; i < class->parent->method.count; i++) {
4911 MonoMethod *m = class->parent->methods [i];
4912 if (!strncmp (m->name, "InternalArray__", 15)) {
4914 list = g_list_prepend (list, m);
4917 list = g_list_reverse (list);
4918 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4920 for (tmp = list; tmp; tmp = tmp->next) {
4921 const char *mname, *iname;
4923 MonoMethod *m = tmp->data;
4924 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4925 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4927 generic_array_method_info [i].array_method = m;
4928 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4929 iname = "System.Collections.Generic.ICollection`1.";
4930 mname = m->name + 27;
4931 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4932 iname = "System.Collections.Generic.IEnumerable`1.";
4933 mname = m->name + 27;
4934 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4935 iname = "System.Collections.Generic.IReadOnlyList`1.";
4936 mname = m->name + strlen (ireadonlylist_prefix);
4937 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4938 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4939 mname = m->name + strlen (ireadonlycollection_prefix);
4940 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4941 iname = "System.Collections.Generic.IList`1.";
4942 mname = m->name + 15;
4944 g_assert_not_reached ();
4947 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4948 strcpy (name, iname);
4949 strcpy (name + strlen (iname), mname);
4950 generic_array_method_info [i].name = name;
4953 /*g_print ("array generic methods: %d\n", count_generic);*/
4955 generic_array_method_num = count_generic;
4957 return generic_array_method_num;
4961 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4963 MonoGenericContext tmp_context;
4966 tmp_context.class_inst = NULL;
4967 tmp_context.method_inst = iface->generic_class->context.class_inst;
4968 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4970 for (i = 0; i < generic_array_method_num; i++) {
4972 MonoMethod *m = generic_array_method_info [i].array_method;
4973 MonoMethod *inflated;
4975 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4976 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4977 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4982 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4984 int null_length = strlen ("(null)");
4985 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4986 char *s = mono_image_alloc (image, len);
4989 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4990 g_assert (result == len - 1);
4996 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4998 gpointer exception_data = NULL;
5000 switch (error->exception_type) {
5001 case MONO_EXCEPTION_TYPE_LOAD:
5002 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5005 case MONO_EXCEPTION_MISSING_METHOD:
5006 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5009 case MONO_EXCEPTION_MISSING_FIELD: {
5010 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5011 const char *class_name;
5014 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5016 class_name = error->klass->name;
5018 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5021 g_free ((void*)class_name);
5025 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5028 if (error->ref_only)
5029 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.";
5031 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5033 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5037 case MONO_EXCEPTION_BAD_IMAGE:
5038 exception_data = error->msg;
5042 g_assert_not_reached ();
5045 mono_class_set_failure (class, error->exception_type, exception_data);
5050 * @class: the class to initialize
5052 * Compute the instance_size, class_size and other infos that cannot be
5053 * computed at mono_class_get() time. Also compute vtable_size if possible.
5054 * Returns TRUE on success or FALSE if there was a problem in loading
5055 * the type (incorrect assemblies, missing assemblies, methods, etc).
5057 * LOCKING: Acquires the loader lock.
5060 mono_class_init (MonoClass *class)
5063 MonoCachedClassInfo cached_info;
5064 gboolean has_cached_info;
5068 /* Double-checking locking pattern */
5069 if (class->inited || class->exception_type)
5070 return class->exception_type == MONO_EXCEPTION_NONE;
5072 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5074 /* We do everything inside the lock to prevent races */
5075 mono_loader_lock ();
5077 if (class->inited || class->exception_type) {
5078 mono_loader_unlock ();
5079 /* Somebody might have gotten in before us */
5080 return class->exception_type == MONO_EXCEPTION_NONE;
5083 if (class->init_pending) {
5084 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5088 class->init_pending = 1;
5090 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5091 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5096 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5097 MonoClass *element_class = class->element_class;
5098 if (!element_class->inited)
5099 mono_class_init (element_class);
5100 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5101 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5106 /* CAS - SecurityAction.InheritanceDemand */
5107 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5108 mono_secman_inheritancedemand_class (class, class->parent);
5111 mono_stats.initialized_class_count++;
5113 if (class->generic_class && !class->generic_class->is_dynamic) {
5114 MonoClass *gklass = class->generic_class->container_class;
5116 mono_stats.generic_class_count++;
5118 class->method = gklass->method;
5119 class->field = gklass->field;
5121 mono_class_init (gklass);
5122 // FIXME: Why is this needed ?
5123 if (!gklass->exception_type)
5124 mono_class_setup_methods (gklass);
5125 if (gklass->exception_type) {
5126 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5130 if (MONO_CLASS_IS_INTERFACE (class))
5131 class->interface_id = mono_get_unique_iid (class);
5134 if (class->parent && !class->parent->inited)
5135 mono_class_init (class->parent);
5137 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5139 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5140 class->nested_classes_inited = TRUE;
5143 * Computes the size used by the fields, and their locations
5145 if (has_cached_info) {
5146 class->instance_size = cached_info.instance_size;
5147 class->sizes.class_size = cached_info.class_size;
5148 class->packing_size = cached_info.packing_size;
5149 class->min_align = cached_info.min_align;
5150 class->blittable = cached_info.blittable;
5151 class->has_references = cached_info.has_references;
5152 class->has_static_refs = cached_info.has_static_refs;
5153 class->no_special_static_fields = cached_info.no_special_static_fields;
5156 if (!class->size_inited){
5157 mono_class_setup_fields (class);
5158 if (class->exception_type || mono_loader_get_last_error ())
5162 /* Initialize arrays */
5164 class->method.count = 3 + (class->rank > 1? 2: 1);
5166 if (class->interface_count) {
5167 int count_generic = generic_array_methods (class);
5168 class->method.count += class->interface_count * count_generic;
5172 mono_class_setup_supertypes (class);
5175 initialize_object_slots (class);
5178 * Initialize the rest of the data without creating a generic vtable if possible.
5179 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5180 * also avoid computing a generic vtable.
5182 if (has_cached_info) {
5184 class->vtable_size = cached_info.vtable_size;
5185 class->has_finalize = cached_info.has_finalize;
5186 class->has_finalize_inited = TRUE;
5187 class->ghcimpl = cached_info.ghcimpl;
5188 class->has_cctor = cached_info.has_cctor;
5189 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5190 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5191 * The first slot if for array with.
5193 static int szarray_vtable_size[2] = { 0 };
5195 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5198 if (!szarray_vtable_size [slot]) {
5199 mono_class_setup_vtable (class);
5200 szarray_vtable_size [slot] = class->vtable_size;
5202 class->vtable_size = szarray_vtable_size[slot];
5204 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5205 MonoClass *gklass = class->generic_class->container_class;
5207 /* Generic instance case */
5208 class->ghcimpl = gklass->ghcimpl;
5209 class->has_cctor = gklass->has_cctor;
5211 mono_class_setup_vtable (gklass);
5212 if (gklass->exception_type) {
5213 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5217 class->vtable_size = gklass->vtable_size;
5221 /* ghcimpl is not currently used
5223 if (class->parent) {
5224 MonoMethod *cmethod = class->vtable [ghc_slot];
5225 if (cmethod->is_inflated)
5226 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5227 if (cmethod == default_ghc) {
5233 /* C# doesn't allow interfaces to have cctors */
5234 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5235 MonoMethod *cmethod = NULL;
5237 if (class->type_token) {
5238 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5239 /* The find_method function ignores the 'flags' argument */
5240 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5241 class->has_cctor = 1;
5243 mono_class_setup_methods (class);
5244 if (class->exception_type)
5247 for (i = 0; i < class->method.count; ++i) {
5248 MonoMethod *method = class->methods [i];
5249 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5250 (strcmp (".cctor", method->name) == 0)) {
5251 class->has_cctor = 1;
5259 if (class->parent) {
5260 int first_iface_slot;
5261 /* This will compute class->parent->vtable_size for some classes */
5262 mono_class_init (class->parent);
5263 if (class->parent->exception_type) {
5264 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5267 if (mono_loader_get_last_error ())
5269 if (!class->parent->vtable_size) {
5270 /* FIXME: Get rid of this somehow */
5271 mono_class_setup_vtable (class->parent);
5272 if (class->parent->exception_type) {
5273 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5276 if (mono_loader_get_last_error ())
5279 first_iface_slot = class->parent->vtable_size;
5280 if (mono_class_need_stelemref_method (class))
5282 setup_interface_offsets (class, first_iface_slot, TRUE);
5284 setup_interface_offsets (class, 0, TRUE);
5287 if (mono_security_core_clr_enabled ())
5288 mono_security_core_clr_check_inheritance (class);
5290 if (mono_loader_get_last_error ()) {
5291 if (class->exception_type == MONO_EXCEPTION_NONE) {
5292 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5294 mono_loader_clear_error ();
5297 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5298 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5303 /* Because of the double-checking locking pattern */
5304 mono_memory_barrier ();
5306 class->init_pending = 0;
5308 mono_loader_unlock ();
5310 return class->exception_type == MONO_EXCEPTION_NONE;
5314 * mono_class_has_finalizer:
5316 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5320 mono_class_has_finalizer (MonoClass *klass)
5322 MonoClass *class = klass;
5323 gboolean has_finalize = FALSE;
5325 if (klass->has_finalize_inited)
5326 return klass->has_finalize;
5328 /* Interfaces and valuetypes are not supposed to have finalizers */
5329 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5330 MonoMethod *cmethod = NULL;
5332 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5333 } else if (class->generic_class) {
5334 MonoClass *gklass = class->generic_class->container_class;
5336 has_finalize = mono_class_has_finalizer (gklass);
5337 } else if (class->parent && class->parent->has_finalize) {
5338 has_finalize = TRUE;
5340 if (class->parent) {
5342 * Can't search in metadata for a method named Finalize, because that
5343 * ignores overrides.
5345 mono_class_setup_vtable (class);
5346 if (class->exception_type || mono_loader_get_last_error ())
5349 cmethod = class->vtable [finalize_slot];
5353 g_assert (class->vtable_size > finalize_slot);
5355 if (class->parent) {
5356 if (cmethod->is_inflated)
5357 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5358 if (cmethod != default_finalize)
5359 has_finalize = TRUE;
5365 mono_image_lock (klass->image);
5367 if (!klass->has_finalize_inited) {
5368 klass->has_finalize = has_finalize ? 1 : 0;
5370 mono_memory_barrier ();
5371 klass->has_finalize_inited = TRUE;
5374 mono_image_unlock (klass->image);
5376 return klass->has_finalize;
5380 mono_is_corlib_image (MonoImage *image)
5382 /* FIXME: allow the dynamic case for our compilers and with full trust */
5383 if (image_is_dynamic (image))
5384 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5386 return image == mono_defaults.corlib;
5390 * LOCKING: this assumes the loader lock is held
5393 mono_class_setup_mono_type (MonoClass *class)
5395 const char *name = class->name;
5396 const char *nspace = class->name_space;
5397 gboolean is_corlib = mono_is_corlib_image (class->image);
5399 class->this_arg.byref = 1;
5400 class->this_arg.data.klass = class;
5401 class->this_arg.type = MONO_TYPE_CLASS;
5402 class->byval_arg.data.klass = class;
5403 class->byval_arg.type = MONO_TYPE_CLASS;
5405 if (is_corlib && !strcmp (nspace, "System")) {
5406 if (!strcmp (name, "ValueType")) {
5408 * do not set the valuetype bit for System.ValueType.
5409 * class->valuetype = 1;
5411 class->blittable = TRUE;
5412 } else if (!strcmp (name, "Enum")) {
5414 * do not set the valuetype bit for System.Enum.
5415 * class->valuetype = 1;
5417 class->valuetype = 0;
5418 class->enumtype = 0;
5419 } else if (!strcmp (name, "Object")) {
5420 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5421 } else if (!strcmp (name, "String")) {
5422 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5423 } else if (!strcmp (name, "TypedReference")) {
5424 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5428 if (class->valuetype) {
5429 int t = MONO_TYPE_VALUETYPE;
5431 if (is_corlib && !strcmp (nspace, "System")) {
5434 if (!strcmp (name, "Boolean")) {
5435 t = MONO_TYPE_BOOLEAN;
5436 } else if (!strcmp(name, "Byte")) {
5438 class->blittable = TRUE;
5442 if (!strcmp (name, "Char")) {
5447 if (!strcmp (name, "Double")) {
5449 class->blittable = TRUE;
5453 if (!strcmp (name, "Int32")) {
5455 class->blittable = TRUE;
5456 } else if (!strcmp(name, "Int16")) {
5458 class->blittable = TRUE;
5459 } else if (!strcmp(name, "Int64")) {
5461 class->blittable = TRUE;
5462 } else if (!strcmp(name, "IntPtr")) {
5464 class->blittable = TRUE;
5468 if (!strcmp (name, "Single")) {
5470 class->blittable = TRUE;
5471 } else if (!strcmp(name, "SByte")) {
5473 class->blittable = TRUE;
5477 if (!strcmp (name, "UInt32")) {
5479 class->blittable = TRUE;
5480 } else if (!strcmp(name, "UInt16")) {
5482 class->blittable = TRUE;
5483 } else if (!strcmp(name, "UInt64")) {
5485 class->blittable = TRUE;
5486 } else if (!strcmp(name, "UIntPtr")) {
5488 class->blittable = TRUE;
5492 if (!strcmp (name, "TypedReference")) {
5493 t = MONO_TYPE_TYPEDBYREF;
5494 class->blittable = TRUE;
5498 if (!strcmp (name, "Void")) {
5506 class->this_arg.type = class->byval_arg.type = t;
5509 if (MONO_CLASS_IS_INTERFACE (class))
5510 class->interface_id = mono_get_unique_iid (class);
5516 * COM initialization is delayed until needed.
5517 * However when a [ComImport] attribute is present on a type it will trigger
5518 * the initialization. This is not a problem unless the BCL being executed
5519 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5522 init_com_from_comimport (MonoClass *class)
5524 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5525 if (mono_security_core_clr_enabled ()) {
5526 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5527 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5528 /* but it can not be made available for application (i.e. user code) since all COM calls
5529 * are considered native calls. In this case we fail with a TypeLoadException (just like
5530 * Silverlight 2 does */
5531 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5536 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5538 #endif /*DISABLE_COM*/
5541 * LOCKING: this assumes the loader lock is held
5544 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5546 gboolean system_namespace;
5547 gboolean is_corlib = mono_is_corlib_image (class->image);
5549 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5551 /* if root of the hierarchy */
5552 if (system_namespace && !strcmp (class->name, "Object")) {
5553 class->parent = NULL;
5554 class->instance_size = sizeof (MonoObject);
5557 if (!strcmp (class->name, "<Module>")) {
5558 class->parent = NULL;
5559 class->instance_size = 0;
5563 if (!MONO_CLASS_IS_INTERFACE (class)) {
5564 /* Imported COM Objects always derive from __ComObject. */
5566 if (MONO_CLASS_IS_IMPORT (class)) {
5567 init_com_from_comimport (class);
5568 if (parent == mono_defaults.object_class)
5569 parent = mono_class_get_com_object_class ();
5573 /* set the parent to something useful and safe, but mark the type as broken */
5574 parent = mono_defaults.object_class;
5575 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5578 class->parent = parent;
5580 if (parent->generic_class && !parent->name) {
5582 * If the parent is a generic instance, we may get
5583 * called before it is fully initialized, especially
5584 * before it has its name.
5589 #ifndef DISABLE_REMOTING
5590 class->marshalbyref = parent->marshalbyref;
5591 class->contextbound = parent->contextbound;
5594 class->delegate = parent->delegate;
5596 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5597 mono_class_set_is_com_object (class);
5599 if (system_namespace) {
5600 #ifndef DISABLE_REMOTING
5601 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5602 class->marshalbyref = 1;
5604 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5605 class->contextbound = 1;
5607 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5608 class->delegate = 1;
5611 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5612 (strcmp (class->parent->name_space, "System") == 0)))
5613 class->valuetype = 1;
5614 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5615 class->valuetype = class->enumtype = 1;
5617 /*class->enumtype = class->parent->enumtype; */
5619 /* initialize com types if COM interfaces are present */
5621 if (MONO_CLASS_IS_IMPORT (class))
5622 init_com_from_comimport (class);
5624 class->parent = NULL;
5630 * mono_class_setup_supertypes:
5633 * Build the data structure needed to make fast type checks work.
5634 * This currently sets two fields in @class:
5635 * - idepth: distance between @class and System.Object in the type
5637 * - supertypes: array of classes: each element has a class in the hierarchy
5638 * starting from @class up to System.Object
5640 * LOCKING: This function is atomic, in case of contention we waste memory.
5643 mono_class_setup_supertypes (MonoClass *class)
5646 MonoClass **supertypes;
5648 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5652 if (class->parent && !class->parent->supertypes)
5653 mono_class_setup_supertypes (class->parent);
5655 class->idepth = class->parent->idepth + 1;
5659 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5660 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5662 if (class->parent) {
5663 supertypes [class->idepth - 1] = class;
5664 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5666 supertypes [0] = class;
5669 mono_atomic_store_release (&class->supertypes, supertypes);
5673 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5675 MonoClass *gtd = (MonoClass*)user_data;
5676 /* Only try to fix generic instances of @gtd */
5677 if (gclass->generic_class->container_class != gtd)
5680 /* Check if the generic instance has no parent. */
5681 if (gtd->parent && !gclass->parent)
5682 mono_generic_class_setup_parent (gclass, gtd);
5688 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5690 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5691 mono_error_set_type_load_class (error, class, msg);
5695 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5697 MonoLoaderError *lerror = mono_loader_get_last_error ();
5700 set_failure_from_loader_error (class, lerror);
5701 mono_error_set_from_loader_error (error);
5705 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5706 mono_error_set_type_load_class (error, class, msg);
5711 * mono_class_create_from_typedef:
5712 * @image: image where the token is valid
5713 * @type_token: typedef token
5714 * @error: used to return any error found while creating the type
5716 * Create the MonoClass* representing the specified type token.
5717 * @type_token must be a TypeDef token.
5719 * FIXME: don't return NULL on failure, just the the caller figure it out.
5722 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5724 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5725 MonoClass *class, *parent = NULL;
5726 guint32 cols [MONO_TYPEDEF_SIZE];
5727 guint32 cols_next [MONO_TYPEDEF_SIZE];
5728 guint tidx = mono_metadata_token_index (type_token);
5729 MonoGenericContext *context = NULL;
5730 const char *name, *nspace;
5732 MonoClass **interfaces;
5733 guint32 field_last, method_last;
5734 guint32 nesting_tokeen;
5736 mono_error_init (error);
5738 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5739 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5740 g_assert (!mono_loader_get_last_error ());
5744 mono_loader_lock ();
5746 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5747 mono_loader_unlock ();
5748 g_assert (!mono_loader_get_last_error ());
5752 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5754 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5755 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5757 class = mono_image_alloc0 (image, sizeof (MonoClass));
5760 class->name_space = nspace;
5762 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5764 class->image = image;
5765 class->type_token = type_token;
5766 class->flags = cols [MONO_TYPEDEF_FLAGS];
5768 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5770 classes_size += sizeof (MonoClass);
5773 * Check whether we're a generic type definition.
5775 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5776 if (class->generic_container) {
5777 class->is_generic = 1;
5778 class->generic_container->owner.klass = class;
5779 context = &class->generic_container->context;
5782 if (class->generic_container)
5783 enable_gclass_recording ();
5785 if (cols [MONO_TYPEDEF_EXTENDS]) {
5787 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5789 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5790 /*WARNING: this must satisfy mono_metadata_type_hash*/
5791 class->this_arg.byref = 1;
5792 class->this_arg.data.klass = class;
5793 class->this_arg.type = MONO_TYPE_CLASS;
5794 class->byval_arg.data.klass = class;
5795 class->byval_arg.type = MONO_TYPE_CLASS;
5797 parent = mono_class_get_checked (image, parent_token, error);
5798 if (parent && context) /* Always inflate */
5799 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5801 if (parent == NULL) {
5802 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5803 goto parent_failure;
5806 for (tmp = parent; tmp; tmp = tmp->parent) {
5808 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5809 goto parent_failure;
5811 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5812 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5813 goto parent_failure;
5818 mono_class_setup_parent (class, parent);
5820 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5821 mono_class_setup_mono_type (class);
5823 if (class->generic_container)
5824 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5827 * This might access class->byval_arg for recursion generated by generic constraints,
5828 * so it has to come after setup_mono_type ().
5830 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5831 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5832 if (!mono_error_ok (error)) {
5833 /*FIXME implement a mono_class_set_failure_from_mono_error */
5834 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5835 mono_loader_unlock ();
5836 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5837 g_assert (!mono_loader_get_last_error ());
5842 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5846 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5850 class->cast_class = class->element_class = class;
5852 if (!class->enumtype) {
5853 if (!mono_metadata_interfaces_from_typedef_full (
5854 image, type_token, &interfaces, &icount, FALSE, context, error)){
5856 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5857 mono_loader_unlock ();
5858 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5862 class->interfaces = interfaces;
5863 class->interface_count = icount;
5864 class->interfaces_inited = 1;
5867 /*g_print ("Load class %s\n", name);*/
5870 * Compute the field and method lists
5872 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5873 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5875 if (tt->rows > tidx){
5876 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5877 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5878 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5880 field_last = image->tables [MONO_TABLE_FIELD].rows;
5881 method_last = image->tables [MONO_TABLE_METHOD].rows;
5884 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5885 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5886 class->field.count = field_last - class->field.first;
5888 class->field.count = 0;
5890 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5891 class->method.count = method_last - class->method.first;
5893 class->method.count = 0;
5895 /* reserve space to store vector pointer in arrays */
5896 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5897 class->instance_size += 2 * sizeof (gpointer);
5898 g_assert (class->field.count == 0);
5901 if (class->enumtype) {
5902 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5903 if (!enum_basetype) {
5904 /*set it to a default value as the whole runtime can't handle this to be null*/
5905 class->cast_class = class->element_class = mono_defaults.int32_class;
5906 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5907 mono_loader_unlock ();
5908 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5909 g_assert (!mono_loader_get_last_error ());
5912 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5916 * If we're a generic type definition, load the constraints.
5917 * We must do this after the class has been constructed to make certain recursive scenarios
5920 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5921 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)));
5922 mono_loader_unlock ();
5923 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5924 g_assert (!mono_loader_get_last_error ());
5928 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5929 if (!strncmp (name, "Vector", 6))
5930 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");
5933 mono_loader_unlock ();
5935 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5936 g_assert (!mono_loader_get_last_error ());
5941 mono_class_setup_mono_type (class);
5942 mono_loader_unlock ();
5943 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5944 g_assert (!mono_loader_get_last_error ());
5948 /** is klass Nullable<T>? */
5950 mono_class_is_nullable (MonoClass *klass)
5952 return klass->generic_class != NULL &&
5953 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5957 /** if klass is T? return T */
5959 mono_class_get_nullable_param (MonoClass *klass)
5961 g_assert (mono_class_is_nullable (klass));
5962 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5966 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5970 MonoGenericClass *gclass = klass->generic_class;
5972 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5973 if (!mono_error_ok (&error)) {
5974 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5975 klass->parent = mono_defaults.object_class;
5976 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5977 mono_error_cleanup (&error);
5981 mono_class_setup_parent (klass, klass->parent);
5983 if (klass->enumtype) {
5984 klass->cast_class = gtd->cast_class;
5985 klass->element_class = gtd->element_class;
5991 * Create the `MonoClass' for an instantiation of a generic type.
5992 * We only do this if we actually need it.
5995 mono_generic_class_get_class (MonoGenericClass *gclass)
5997 MonoClass *klass, *gklass;
5999 if (gclass->cached_class)
6000 return gclass->cached_class;
6002 mono_loader_lock ();
6003 if (gclass->cached_class) {
6004 mono_loader_unlock ();
6005 return gclass->cached_class;
6008 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6010 gklass = gclass->container_class;
6012 if (record_gclass_instantiation > 0)
6013 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6015 if (gklass->nested_in) {
6016 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6017 klass->nested_in = gklass->nested_in;
6020 klass->name = gklass->name;
6021 klass->name_space = gklass->name_space;
6023 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6025 klass->image = gklass->image;
6026 klass->flags = gklass->flags;
6027 klass->type_token = gklass->type_token;
6028 klass->field.count = gklass->field.count;
6030 klass->is_inflated = 1;
6031 klass->generic_class = gclass;
6033 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6034 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6035 klass->this_arg.byref = TRUE;
6036 klass->enumtype = gklass->enumtype;
6037 klass->valuetype = gklass->valuetype;
6039 klass->cast_class = klass->element_class = klass;
6041 if (mono_class_is_nullable (klass))
6042 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6045 * We're not interested in the nested classes of a generic instance.
6046 * We use the generic type definition to look for nested classes.
6049 mono_generic_class_setup_parent (klass, gklass);
6051 if (gclass->is_dynamic) {
6054 mono_class_setup_supertypes (klass);
6056 if (klass->enumtype) {
6058 * For enums, gklass->fields might not been set, but instance_size etc. is
6059 * already set in mono_reflection_create_internal_class (). For non-enums,
6060 * these will be computed normally in mono_class_layout_fields ().
6062 klass->instance_size = gklass->instance_size;
6063 klass->sizes.class_size = gklass->sizes.class_size;
6064 mono_memory_barrier ();
6065 klass->size_inited = 1;
6069 mono_memory_barrier ();
6070 gclass->cached_class = klass;
6072 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6074 inflated_classes ++;
6075 inflated_classes_size += sizeof (MonoClass);
6077 mono_loader_unlock ();
6083 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6085 MonoClass *klass, **ptr;
6087 MonoGenericContainer *container = mono_generic_param_owner (param);
6091 image = mono_defaults.corlib;
6093 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6094 classes_size += sizeof (MonoClass);
6097 klass->name = pinfo->name;
6099 int n = mono_generic_param_num (param);
6100 klass->name = mono_image_alloc0 (image, 16);
6101 sprintf ((char*)klass->name, "%d", n);
6106 MonoMethod *omethod = container->owner.method;
6107 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6109 MonoClass *oklass = container->owner.klass;
6110 klass->name_space = oklass ? oklass->name_space : "";
6113 klass->name_space = "";
6116 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6120 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6124 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6125 klass->parent = pinfo->constraints [0];
6127 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6128 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6130 klass->parent = mono_defaults.object_class;
6133 if (count - pos > 0) {
6134 klass->interface_count = count - pos;
6135 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6136 klass->interfaces_inited = TRUE;
6137 for (i = pos; i < count; i++)
6138 klass->interfaces [i - pos] = pinfo->constraints [i];
6141 klass->image = image;
6143 klass->inited = TRUE;
6144 klass->cast_class = klass->element_class = klass;
6145 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6147 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6148 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6149 klass->this_arg.byref = TRUE;
6151 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6152 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6154 /*Init these fields to sane values*/
6155 klass->min_align = 1;
6156 klass->instance_size = sizeof (gpointer);
6157 mono_memory_barrier ();
6158 klass->size_inited = 1;
6160 mono_class_setup_supertypes (klass);
6162 if (count - pos > 0) {
6163 mono_class_setup_vtable (klass->parent);
6164 if (klass->parent->exception_type)
6165 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6167 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6173 #define FAST_CACHE_SIZE 16
6176 * LOCKING: Takes the image lock depending on @take_lock.
6179 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6181 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6182 MonoImage *image = param->image;
6187 if (n < FAST_CACHE_SIZE) {
6189 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6191 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6193 MonoClass *klass = NULL;
6194 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6197 mono_image_lock (image);
6198 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6200 mono_image_unlock (image);
6207 * LOCKING: Image lock (param->image) must be held
6210 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6212 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6213 MonoImage *image = param->image;
6217 if (n < FAST_CACHE_SIZE) {
6219 /* Requires locking to avoid droping an already published class */
6220 if (!image->mvar_cache_fast)
6221 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6222 image->mvar_cache_fast [n] = klass;
6224 if (!image->var_cache_fast)
6225 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6226 image->var_cache_fast [n] = klass;
6229 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6231 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6233 ht = g_hash_table_new (NULL, NULL);
6234 mono_memory_barrier ();
6236 image->mvar_cache_slow = ht;
6238 image->var_cache_slow = ht;
6241 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6246 * LOCKING: Acquires the image lock (@image).
6249 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6251 MonoGenericContainer *container = mono_generic_param_owner (param);
6252 MonoGenericParamInfo *pinfo = NULL;
6253 MonoClass *klass, *klass2;
6256 pinfo = mono_generic_param_info (param);
6257 klass = pinfo->pklass;
6260 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6265 if (!image && container) {
6267 MonoMethod *method = container->owner.method;
6268 image = (method && method->klass) ? method->klass->image : NULL;
6270 MonoClass *klass = container->owner.klass;
6271 // FIXME: 'klass' should not be null
6272 // But, monodis creates GenericContainers without associating a owner to it
6273 image = klass ? klass->image : NULL;
6277 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6279 mono_memory_barrier ();
6281 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6282 image = mono_defaults.corlib;
6284 mono_image_lock (image);
6286 klass2 = pinfo->pklass;
6288 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6294 pinfo->pklass = klass;
6296 set_anon_gparam_class (param, is_mvar, klass);
6298 mono_image_unlock (image);
6300 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6302 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6304 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6310 mono_ptr_class_get (MonoType *type)
6313 MonoClass *el_class;
6317 el_class = mono_class_from_mono_type (type);
6318 image = el_class->image;
6320 mono_image_lock (image);
6321 if (image->ptr_cache) {
6322 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6323 mono_image_unlock (image);
6327 mono_image_unlock (image);
6329 result = mono_image_alloc0 (image, sizeof (MonoClass));
6331 classes_size += sizeof (MonoClass);
6333 result->parent = NULL; /* no parent for PTR types */
6334 result->name_space = el_class->name_space;
6335 name = g_strdup_printf ("%s*", el_class->name);
6336 result->name = mono_image_strdup (image, name);
6339 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6341 result->image = el_class->image;
6342 result->inited = TRUE;
6343 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6344 /* Can pointers get boxed? */
6345 result->instance_size = sizeof (gpointer);
6346 result->cast_class = result->element_class = el_class;
6347 result->blittable = TRUE;
6349 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6350 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6351 result->this_arg.byref = TRUE;
6353 mono_class_setup_supertypes (result);
6355 mono_image_lock (image);
6356 if (image->ptr_cache) {
6358 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6359 mono_image_unlock (image);
6360 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6364 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6366 g_hash_table_insert (image->ptr_cache, el_class, result);
6367 mono_image_unlock (image);
6369 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6375 mono_fnptr_class_get (MonoMethodSignature *sig)
6378 static GHashTable *ptr_hash = NULL;
6380 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6382 mono_loader_lock ();
6385 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6387 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6388 mono_loader_unlock ();
6391 result = g_new0 (MonoClass, 1);
6393 result->parent = NULL; /* no parent for PTR types */
6394 result->name_space = "System";
6395 result->name = "MonoFNPtrFakeClass";
6397 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6399 result->image = mono_defaults.corlib; /* need to fix... */
6400 result->inited = TRUE;
6401 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6402 /* Can pointers get boxed? */
6403 result->instance_size = sizeof (gpointer);
6404 result->cast_class = result->element_class = result;
6405 result->blittable = TRUE;
6407 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6408 result->this_arg.data.method = result->byval_arg.data.method = sig;
6409 result->this_arg.byref = TRUE;
6410 result->blittable = TRUE;
6412 mono_class_setup_supertypes (result);
6414 g_hash_table_insert (ptr_hash, sig, result);
6416 mono_loader_unlock ();
6418 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6424 mono_class_from_mono_type (MonoType *type)
6426 switch (type->type) {
6427 case MONO_TYPE_OBJECT:
6428 return type->data.klass? type->data.klass: mono_defaults.object_class;
6429 case MONO_TYPE_VOID:
6430 return type->data.klass? type->data.klass: mono_defaults.void_class;
6431 case MONO_TYPE_BOOLEAN:
6432 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6433 case MONO_TYPE_CHAR:
6434 return type->data.klass? type->data.klass: mono_defaults.char_class;
6436 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6438 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6440 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6442 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6444 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6446 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6448 return type->data.klass? type->data.klass: mono_defaults.int_class;
6450 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6452 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6454 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6456 return type->data.klass? type->data.klass: mono_defaults.single_class;
6458 return type->data.klass? type->data.klass: mono_defaults.double_class;
6459 case MONO_TYPE_STRING:
6460 return type->data.klass? type->data.klass: mono_defaults.string_class;
6461 case MONO_TYPE_TYPEDBYREF:
6462 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6463 case MONO_TYPE_ARRAY:
6464 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6466 return mono_ptr_class_get (type->data.type);
6467 case MONO_TYPE_FNPTR:
6468 return mono_fnptr_class_get (type->data.method);
6469 case MONO_TYPE_SZARRAY:
6470 return mono_array_class_get (type->data.klass, 1);
6471 case MONO_TYPE_CLASS:
6472 case MONO_TYPE_VALUETYPE:
6473 return type->data.klass;
6474 case MONO_TYPE_GENERICINST:
6475 return mono_generic_class_get_class (type->data.generic_class);
6477 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6478 case MONO_TYPE_MVAR:
6479 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6481 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6482 g_assert_not_reached ();
6489 * mono_type_retrieve_from_typespec
6490 * @image: context where the image is created
6491 * @type_spec: typespec token
6492 * @context: the generic context used to evaluate generic instantiations in
6495 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6497 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6499 *did_inflate = FALSE;
6504 if (context && (context->class_inst || context->method_inst)) {
6505 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6507 if (!mono_error_ok (error)) {
6508 g_assert (!mono_loader_get_last_error ());
6514 *did_inflate = TRUE;
6521 * mono_class_create_from_typespec
6522 * @image: context where the image is created
6523 * @type_spec: typespec token
6524 * @context: the generic context used to evaluate generic instantiations in
6527 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6530 gboolean inflated = FALSE;
6531 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6532 if (!mono_error_ok (error))
6534 ret = mono_class_from_mono_type (t);
6536 mono_metadata_free_type (t);
6541 * mono_bounded_array_class_get:
6542 * @element_class: element class
6543 * @rank: the dimension of the array class
6544 * @bounded: whenever the array has non-zero bounds
6546 * Returns: a class object describing the array with element type @element_type and
6550 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6554 MonoClass *parent = NULL;
6555 GSList *list, *rootlist = NULL;
6558 gboolean corlib_type = FALSE;
6560 g_assert (rank <= 255);
6563 /* bounded only matters for one-dimensional arrays */
6566 image = eclass->image;
6568 if (rank == 1 && !bounded) {
6570 * This case is very frequent not just during compilation because of calls
6571 * from mono_class_from_mono_type (), mono_array_new (),
6572 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6574 mono_mutex_lock (&image->szarray_cache_lock);
6575 if (!image->szarray_cache)
6576 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6577 class = g_hash_table_lookup (image->szarray_cache, eclass);
6578 mono_mutex_unlock (&image->szarray_cache_lock);
6582 mono_loader_lock ();
6584 mono_loader_lock ();
6586 if (!image->array_cache)
6587 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6589 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6590 for (; list; list = list->next) {
6592 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6593 mono_loader_unlock ();
6600 /* for the building corlib use System.Array from it */
6601 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6602 parent = mono_class_from_name (image, "System", "Array");
6605 parent = mono_defaults.array_class;
6606 if (!parent->inited)
6607 mono_class_init (parent);
6610 class = mono_image_alloc0 (image, sizeof (MonoClass));
6612 class->image = image;
6613 class->name_space = eclass->name_space;
6614 nsize = strlen (eclass->name);
6615 name = g_malloc (nsize + 2 + rank + 1);
6616 memcpy (name, eclass->name, nsize);
6619 memset (name + nsize + 1, ',', rank - 1);
6621 name [nsize + rank] = '*';
6622 name [nsize + rank + bounded] = ']';
6623 name [nsize + rank + bounded + 1] = 0;
6624 class->name = mono_image_strdup (image, name);
6627 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6629 classes_size += sizeof (MonoClass);
6631 class->type_token = 0;
6632 /* all arrays are marked serializable and sealed, bug #42779 */
6633 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6634 class->parent = parent;
6635 class->instance_size = mono_class_instance_size (class->parent);
6637 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6638 /*Arrays of those two types are invalid.*/
6639 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6640 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6641 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6642 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6643 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6645 /* element_size -1 is ok as this is not an instantitable type*/
6646 class->sizes.element_size = -1;
6648 class->sizes.element_size = mono_class_array_element_size (eclass);
6650 mono_class_setup_supertypes (class);
6652 if (eclass->generic_class)
6653 mono_class_init (eclass);
6654 if (!eclass->size_inited)
6655 mono_class_setup_fields (eclass);
6656 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6657 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6659 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6663 if (eclass->enumtype)
6664 class->cast_class = eclass->element_class;
6666 class->cast_class = eclass;
6668 switch (class->cast_class->byval_arg.type) {
6670 class->cast_class = mono_defaults.byte_class;
6673 class->cast_class = mono_defaults.int16_class;
6676 #if SIZEOF_VOID_P == 4
6680 class->cast_class = mono_defaults.int32_class;
6683 #if SIZEOF_VOID_P == 8
6687 class->cast_class = mono_defaults.int64_class;
6691 class->element_class = eclass;
6693 if ((rank > 1) || bounded) {
6694 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6695 class->byval_arg.type = MONO_TYPE_ARRAY;
6696 class->byval_arg.data.array = at;
6697 at->eklass = eclass;
6699 /* FIXME: complete.... */
6701 class->byval_arg.type = MONO_TYPE_SZARRAY;
6702 class->byval_arg.data.klass = eclass;
6704 class->this_arg = class->byval_arg;
6705 class->this_arg.byref = 1;
6710 class->generic_container = eclass->generic_container;
6712 if (rank == 1 && !bounded) {
6713 MonoClass *prev_class;
6715 mono_mutex_lock (&image->szarray_cache_lock);
6716 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6718 /* Someone got in before us */
6721 g_hash_table_insert (image->szarray_cache, eclass, class);
6722 mono_mutex_unlock (&image->szarray_cache_lock);
6724 list = g_slist_append (rootlist, class);
6725 g_hash_table_insert (image->array_cache, eclass, list);
6728 mono_loader_unlock ();
6730 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6736 * mono_array_class_get:
6737 * @element_class: element class
6738 * @rank: the dimension of the array class
6740 * Returns: a class object describing the array with element type @element_type and
6744 mono_array_class_get (MonoClass *eclass, guint32 rank)
6746 return mono_bounded_array_class_get (eclass, rank, FALSE);
6750 * mono_class_instance_size:
6753 * Returns: the size of an object instance
6756 mono_class_instance_size (MonoClass *klass)
6758 if (!klass->size_inited)
6759 mono_class_init (klass);
6761 return klass->instance_size;
6765 * mono_class_min_align:
6768 * Returns: minimm alignment requirements
6771 mono_class_min_align (MonoClass *klass)
6773 if (!klass->size_inited)
6774 mono_class_init (klass);
6776 return klass->min_align;
6780 * mono_class_value_size:
6783 * This function is used for value types, and return the
6784 * space and the alignment to store that kind of value object.
6786 * Returns: the size of a value of kind @klass
6789 mono_class_value_size (MonoClass *klass, guint32 *align)
6793 /* fixme: check disable, because we still have external revereces to
6794 * mscorlib and Dummy Objects
6796 /*g_assert (klass->valuetype);*/
6798 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6801 *align = klass->min_align;
6807 * mono_class_data_size:
6810 * Returns: the size of the static class data
6813 mono_class_data_size (MonoClass *klass)
6816 mono_class_init (klass);
6817 /* This can happen with dynamically created types */
6818 if (!klass->fields_inited)
6819 mono_class_setup_fields_locking (klass);
6821 /* in arrays, sizes.class_size is unioned with element_size
6822 * and arrays have no static fields
6826 return klass->sizes.class_size;
6830 * Auxiliary routine to mono_class_get_field
6832 * Takes a field index instead of a field token.
6834 static MonoClassField *
6835 mono_class_get_field_idx (MonoClass *class, int idx)
6837 mono_class_setup_fields_locking (class);
6838 if (class->exception_type)
6842 if (class->image->uncompressed_metadata) {
6844 * class->field.first points to the FieldPtr table, while idx points into the
6845 * Field table, so we have to do a search.
6847 /*FIXME this is broken for types with multiple fields with the same name.*/
6848 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6851 for (i = 0; i < class->field.count; ++i)
6852 if (mono_field_get_name (&class->fields [i]) == name)
6853 return &class->fields [i];
6854 g_assert_not_reached ();
6856 if (class->field.count) {
6857 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6858 return &class->fields [idx - class->field.first];
6862 class = class->parent;
6868 * mono_class_get_field:
6869 * @class: the class to lookup the field.
6870 * @field_token: the field token
6872 * Returns: A MonoClassField representing the type and offset of
6873 * the field, or a NULL value if the field does not belong to this
6877 mono_class_get_field (MonoClass *class, guint32 field_token)
6879 int idx = mono_metadata_token_index (field_token);
6881 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6883 return mono_class_get_field_idx (class, idx - 1);
6887 * mono_class_get_field_from_name:
6888 * @klass: the class to lookup the field.
6889 * @name: the field name
6891 * Search the class @klass and it's parents for a field with the name @name.
6893 * Returns: the MonoClassField pointer of the named field or NULL
6896 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6898 return mono_class_get_field_from_name_full (klass, name, NULL);
6902 * mono_class_get_field_from_name_full:
6903 * @klass: the class to lookup the field.
6904 * @name: the field name
6905 * @type: the type of the fields. This optional.
6907 * Search the class @klass and it's parents for a field with the name @name and type @type.
6909 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6910 * of its generic type definition.
6912 * Returns: the MonoClassField pointer of the named field or NULL
6915 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6919 mono_class_setup_fields_locking (klass);
6920 if (klass->exception_type)
6924 for (i = 0; i < klass->field.count; ++i) {
6925 MonoClassField *field = &klass->fields [i];
6927 if (strcmp (name, mono_field_get_name (field)) != 0)
6931 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6932 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6937 klass = klass->parent;
6943 * mono_class_get_field_token:
6944 * @field: the field we need the token of
6946 * Get the token of a field. Note that the tokesn is only valid for the image
6947 * the field was loaded from. Don't use this function for fields in dynamic types.
6949 * Returns: the token representing the field in the image it was loaded from.
6952 mono_class_get_field_token (MonoClassField *field)
6954 MonoClass *klass = field->parent;
6957 mono_class_setup_fields_locking (klass);
6962 for (i = 0; i < klass->field.count; ++i) {
6963 if (&klass->fields [i] == field) {
6964 int idx = klass->field.first + i + 1;
6966 if (klass->image->uncompressed_metadata)
6967 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6968 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6971 klass = klass->parent;
6974 g_assert_not_reached ();
6979 mono_field_get_index (MonoClassField *field)
6981 int index = field - field->parent->fields;
6983 g_assert (index >= 0 && index < field->parent->field.count);
6989 * mono_class_get_field_default_value:
6991 * Return the default value of the field as a pointer into the metadata blob.
6994 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6997 guint32 constant_cols [MONO_CONSTANT_SIZE];
6999 MonoClass *klass = field->parent;
7001 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7003 if (!klass->ext || !klass->ext->field_def_values) {
7004 MonoFieldDefaultValue *def_values;
7006 mono_class_alloc_ext (klass);
7008 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7010 mono_image_lock (klass->image);
7011 mono_memory_barrier ();
7012 if (!klass->ext->field_def_values)
7013 klass->ext->field_def_values = def_values;
7014 mono_image_unlock (klass->image);
7017 field_index = mono_field_get_index (field);
7019 if (!klass->ext->field_def_values [field_index].data) {
7020 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7024 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7026 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7027 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7028 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7031 *def_type = klass->ext->field_def_values [field_index].def_type;
7032 return klass->ext->field_def_values [field_index].data;
7036 mono_property_get_index (MonoProperty *prop)
7038 int index = prop - prop->parent->ext->properties;
7040 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7046 * mono_class_get_property_default_value:
7048 * Return the default value of the field as a pointer into the metadata blob.
7051 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7054 guint32 constant_cols [MONO_CONSTANT_SIZE];
7055 MonoClass *klass = property->parent;
7057 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7059 * We don't cache here because it is not used by C# so it's quite rare, but
7060 * we still do the lookup in klass->ext because that is where the data
7061 * is stored for dynamic assemblies.
7064 if (image_is_dynamic (klass->image)) {
7065 int prop_index = mono_property_get_index (property);
7066 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7067 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7068 return klass->ext->prop_def_values [prop_index].data;
7072 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7076 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7077 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7078 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7082 mono_class_get_event_token (MonoEvent *event)
7084 MonoClass *klass = event->parent;
7089 for (i = 0; i < klass->ext->event.count; ++i) {
7090 if (&klass->ext->events [i] == event)
7091 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7094 klass = klass->parent;
7097 g_assert_not_reached ();
7102 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7106 gpointer iter = NULL;
7107 while ((p = mono_class_get_properties (klass, &iter))) {
7108 if (! strcmp (name, p->name))
7111 klass = klass->parent;
7117 mono_class_get_property_token (MonoProperty *prop)
7119 MonoClass *klass = prop->parent;
7123 gpointer iter = NULL;
7124 while ((p = mono_class_get_properties (klass, &iter))) {
7125 if (&klass->ext->properties [i] == prop)
7126 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7130 klass = klass->parent;
7133 g_assert_not_reached ();
7138 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7140 const char *name, *nspace;
7141 if (image_is_dynamic (image))
7142 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7144 switch (type_token & 0xff000000){
7145 case MONO_TOKEN_TYPE_DEF: {
7146 guint32 cols [MONO_TYPEDEF_SIZE];
7147 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7148 guint tidx = mono_metadata_token_index (type_token);
7150 if (tidx > tt->rows)
7151 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7153 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7154 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7155 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7156 if (strlen (nspace) == 0)
7157 return g_strdup_printf ("%s", name);
7159 return g_strdup_printf ("%s.%s", nspace, name);
7162 case MONO_TOKEN_TYPE_REF: {
7164 guint32 cols [MONO_TYPEREF_SIZE];
7165 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7166 guint tidx = mono_metadata_token_index (type_token);
7169 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7171 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7172 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7173 mono_error_cleanup (&error);
7177 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7178 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7179 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7180 if (strlen (nspace) == 0)
7181 return g_strdup_printf ("%s", name);
7183 return g_strdup_printf ("%s.%s", nspace, name);
7186 case MONO_TOKEN_TYPE_SPEC:
7187 return g_strdup_printf ("Typespec 0x%08x", type_token);
7189 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7194 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7196 if (image_is_dynamic (image))
7197 return g_strdup_printf ("DynamicAssembly %s", image->name);
7199 switch (type_token & 0xff000000){
7200 case MONO_TOKEN_TYPE_DEF:
7201 if (image->assembly)
7202 return mono_stringify_assembly_name (&image->assembly->aname);
7203 else if (image->assembly_name)
7204 return g_strdup (image->assembly_name);
7205 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7206 case MONO_TOKEN_TYPE_REF: {
7208 MonoAssemblyName aname;
7209 guint32 cols [MONO_TYPEREF_SIZE];
7210 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7211 guint32 idx = mono_metadata_token_index (type_token);
7214 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7216 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7217 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7218 mono_error_cleanup (&error);
7221 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7223 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7224 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7225 case MONO_RESOLUTION_SCOPE_MODULE:
7227 return g_strdup ("");
7228 case MONO_RESOLUTION_SCOPE_MODULEREF:
7230 return g_strdup ("");
7231 case MONO_RESOLUTION_SCOPE_TYPEREF:
7233 return g_strdup ("");
7234 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7235 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7236 return mono_stringify_assembly_name (&aname);
7238 g_assert_not_reached ();
7242 case MONO_TOKEN_TYPE_SPEC:
7244 return g_strdup ("");
7246 g_assert_not_reached ();
7253 * mono_class_get_full:
7254 * @image: the image where the class resides
7255 * @type_token: the token for the class
7256 * @context: the generic context used to evaluate generic instantiations in
7257 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7259 * Returns: the MonoClass that represents @type_token in @image
7262 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7266 class = mono_class_get_checked (image, type_token, &error);
7268 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7269 class = mono_class_inflate_generic_class_checked (class, context, &error);
7271 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7277 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7281 mono_error_init (error);
7282 class = mono_class_get_checked (image, type_token, error);
7284 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7285 class = mono_class_inflate_generic_class_checked (class, context, error);
7290 * mono_class_get_checked:
7291 * @image: the image where the class resides
7292 * @type_token: the token for the class
7293 * @error: error object to return any error
7295 * Returns: the MonoClass that represents @type_token in @image
7298 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7300 MonoClass *class = NULL;
7302 mono_error_init (error);
7304 if (image_is_dynamic (image)) {
7305 int table = mono_metadata_token_table (type_token);
7307 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7308 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7311 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7315 switch (type_token & 0xff000000){
7316 case MONO_TOKEN_TYPE_DEF:
7317 class = mono_class_create_from_typedef (image, type_token, error);
7319 case MONO_TOKEN_TYPE_REF:
7320 class = mono_class_from_typeref_checked (image, type_token, error);
7322 case MONO_TOKEN_TYPE_SPEC:
7323 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7326 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7330 /* Generic case, should be avoided for when a better error is possible. */
7331 if (!class && mono_error_ok (error)) {
7332 char *name = mono_class_name_from_token (image, type_token);
7333 char *assembly = mono_assembly_name_from_token (image, type_token);
7334 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7342 * mono_type_get_checked:
7343 * @image: the image where the type resides
7344 * @type_token: the token for the type
7345 * @context: the generic context used to evaluate generic instantiations in
7346 * @error: Error handling context
7348 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7350 * Returns: the MonoType that represents @type_token in @image
7353 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7355 MonoType *type = NULL;
7356 gboolean inflated = FALSE;
7358 mono_error_init (error);
7360 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7361 if (image_is_dynamic (image))
7362 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7364 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7365 MonoClass *class = mono_class_get_checked (image, type_token, error);
7368 g_assert (!mono_loader_get_last_error ());
7373 return mono_class_get_type (class);
7376 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7379 g_assert (!mono_loader_get_last_error ());
7384 MonoType *tmp = type;
7385 type = mono_class_get_type (mono_class_from_mono_type (type));
7386 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7387 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7388 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7390 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7392 if (type->type != tmp->type)
7395 mono_metadata_free_type (tmp);
7402 mono_class_get (MonoImage *image, guint32 type_token)
7404 return mono_class_get_full (image, type_token, NULL);
7408 * mono_image_init_name_cache:
7410 * Initializes the class name cache stored in image->name_cache.
7412 * LOCKING: Acquires the corresponding image lock.
7415 mono_image_init_name_cache (MonoImage *image)
7417 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7418 guint32 cols [MONO_TYPEDEF_SIZE];
7421 guint32 i, visib, nspace_index;
7422 GHashTable *name_cache2, *nspace_table;
7424 mono_image_lock (image);
7426 if (image->name_cache) {
7427 mono_image_unlock (image);
7431 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7433 if (image_is_dynamic (image)) {
7434 mono_image_unlock (image);
7438 /* Temporary hash table to avoid lookups in the nspace_table */
7439 name_cache2 = g_hash_table_new (NULL, NULL);
7441 for (i = 1; i <= t->rows; ++i) {
7442 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7443 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7445 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7446 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7448 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7450 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7451 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7453 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7454 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7455 if (!nspace_table) {
7456 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7457 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7458 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7461 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7464 /* Load type names from EXPORTEDTYPES table */
7466 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7467 guint32 cols [MONO_EXP_TYPE_SIZE];
7470 for (i = 0; i < t->rows; ++i) {
7471 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7472 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7473 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7475 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7476 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7477 if (!nspace_table) {
7478 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7479 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7480 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7483 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7487 g_hash_table_destroy (name_cache2);
7488 mono_image_unlock (image);
7491 /*FIXME Only dynamic assemblies should allow this operation.*/
7493 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7494 const char *name, guint32 index)
7496 GHashTable *nspace_table;
7497 GHashTable *name_cache;
7500 mono_image_lock (image);
7502 if (!image->name_cache)
7503 mono_image_init_name_cache (image);
7505 name_cache = image->name_cache;
7506 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7507 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7508 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7511 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7512 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7514 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7516 mono_image_unlock (image);
7525 find_nocase (gpointer key, gpointer value, gpointer user_data)
7527 char *name = (char*)key;
7528 FindUserData *data = (FindUserData*)user_data;
7530 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7531 data->value = value;
7535 * mono_class_from_name_case:
7536 * @image: The MonoImage where the type is looked up in
7537 * @name_space: the type namespace
7538 * @name: the type short name.
7539 * @deprecated: use the _checked variant
7541 * Obtains a MonoClass with a given namespace and a given name which
7542 * is located in the given MonoImage. The namespace and name
7543 * lookups are case insensitive.
7546 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7549 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7550 g_assert (!mono_error_ok (&error));
7555 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7557 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7558 guint32 cols [MONO_TYPEDEF_SIZE];
7563 mono_error_init (error);
7565 if (image_is_dynamic (image)) {
7567 FindUserData user_data;
7569 mono_image_lock (image);
7571 if (!image->name_cache)
7572 mono_image_init_name_cache (image);
7574 user_data.key = name_space;
7575 user_data.value = NULL;
7576 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7578 if (user_data.value) {
7579 GHashTable *nspace_table = (GHashTable*)user_data.value;
7581 user_data.key = name;
7582 user_data.value = NULL;
7584 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7586 if (user_data.value)
7587 token = GPOINTER_TO_UINT (user_data.value);
7590 mono_image_unlock (image);
7593 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7599 /* add a cache if needed */
7600 for (i = 1; i <= t->rows; ++i) {
7601 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7602 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7604 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7605 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7607 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7609 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7610 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7611 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7612 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7618 return_nested_in (MonoClass *class, char *nested)
7621 char *s = strchr (nested, '/');
7622 gpointer iter = NULL;
7629 while ((found = mono_class_get_nested_types (class, &iter))) {
7630 if (strcmp (found->name, nested) == 0) {
7632 return return_nested_in (found, s);
7640 search_modules (MonoImage *image, const char *name_space, const char *name)
7642 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7643 MonoImage *file_image;
7648 * The EXPORTEDTYPES table only contains public types, so have to search the
7650 * Note: image->modules contains the contents of the MODULEREF table, while
7651 * the real module list is in the FILE table.
7653 for (i = 0; i < file_table->rows; i++) {
7654 guint32 cols [MONO_FILE_SIZE];
7655 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7656 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7659 file_image = mono_image_load_file_for_image (image, i + 1);
7661 class = mono_class_from_name (file_image, name_space, name);
7671 * mono_class_from_name:
7672 * @image: The MonoImage where the type is looked up in
7673 * @name_space: the type namespace
7674 * @name: the type short name.
7676 * Obtains a MonoClass with a given namespace and a given name which
7677 * is located in the given MonoImage.
7679 * To reference nested classes, use the "/" character as a separator.
7680 * For example use "Foo/Bar" to reference the class Bar that is nested
7681 * inside Foo, like this: "class Foo { class Bar {} }".
7684 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7687 GHashTable *nspace_table;
7688 MonoImage *loaded_image;
7695 if ((nested = strchr (name, '/'))) {
7696 int pos = nested - name;
7697 int len = strlen (name);
7700 memcpy (buf, name, len + 1);
7702 nested = buf + pos + 1;
7706 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7707 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7708 gboolean res = get_class_from_name (image, name_space, name, &class);
7711 class = search_modules (image, name_space, name);
7713 return class ? return_nested_in (class, nested) : NULL;
7719 mono_image_lock (image);
7721 if (!image->name_cache)
7722 mono_image_init_name_cache (image);
7724 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7727 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7729 mono_image_unlock (image);
7731 if (!token && image_is_dynamic (image) && image->modules) {
7732 /* Search modules as well */
7733 for (i = 0; i < image->module_count; ++i) {
7734 MonoImage *module = image->modules [i];
7736 class = mono_class_from_name (module, name_space, name);
7743 class = search_modules (image, name_space, name);
7751 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7752 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7753 guint32 cols [MONO_EXP_TYPE_SIZE];
7756 idx = mono_metadata_token_index (token);
7758 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7760 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7761 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7762 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7765 class = mono_class_from_name (loaded_image, name_space, name);
7767 return return_nested_in (class, nested);
7769 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7770 guint32 assembly_idx;
7772 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7774 mono_assembly_load_reference (image, assembly_idx - 1);
7775 g_assert (image->references [assembly_idx - 1]);
7776 if (image->references [assembly_idx - 1] == (gpointer)-1)
7779 /* FIXME: Cycle detection */
7780 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7782 g_error ("not yet implemented");
7786 token = MONO_TOKEN_TYPE_DEF | token;
7788 class = mono_class_get_checked (image, token, &error);
7789 if (!mono_error_ok (&error)) {
7790 mono_loader_set_error_from_mono_error (&error);
7791 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7794 return return_nested_in (class, nested);
7799 * mono_class_is_subclass_of:
7800 * @klass: class to probe if it is a subclass of another one
7801 * @klassc: the class we suspect is the base class
7802 * @check_interfaces: whether we should perform interface checks
7804 * This method determines whether @klass is a subclass of @klassc.
7806 * If the @check_interfaces flag is set, then if @klassc is an interface
7807 * this method return true if the @klass implements the interface or
7808 * if @klass is an interface, if one of its base classes is @klass.
7810 * If @check_interfaces is false then, then if @klass is not an interface
7811 * then it returns true if the @klass is a subclass of @klassc.
7813 * if @klass is an interface and @klassc is System.Object, then this function
7818 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7819 gboolean check_interfaces)
7821 /*FIXME test for interfaces with variant generic arguments*/
7823 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7824 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7826 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7829 for (i = 0; i < klass->interface_count; i ++) {
7830 MonoClass *ic = klass->interfaces [i];
7835 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7840 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7843 if (klassc == mono_defaults.object_class)
7850 mono_type_is_generic_argument (MonoType *type)
7852 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7856 mono_class_has_variant_generic_params (MonoClass *klass)
7859 MonoGenericContainer *container;
7861 if (!klass->generic_class)
7864 container = klass->generic_class->container_class->generic_container;
7866 for (i = 0; i < container->type_argc; ++i)
7867 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7874 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7876 if (target == candidate)
7879 if (check_for_reference_conv &&
7880 mono_type_is_generic_argument (&target->byval_arg) &&
7881 mono_type_is_generic_argument (&candidate->byval_arg)) {
7882 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7883 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7885 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7888 if (!mono_class_is_assignable_from (target, candidate))
7894 * @container the generic container from the GTD
7895 * @klass: the class to be assigned to
7896 * @oklass: the source class
7898 * Both klass and oklass must be instances of the same generic interface.
7899 * Return true if @klass can be assigned to a @klass variable
7902 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7905 MonoType **klass_argv, **oklass_argv;
7906 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7907 MonoGenericContainer *container = klass_gtd->generic_container;
7909 if (klass == oklass)
7912 /*Viable candidates are instances of the same generic interface*/
7913 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7916 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7917 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7919 for (j = 0; j < container->type_argc; ++j) {
7920 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7921 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7923 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7927 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7928 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7930 if (param1_class != param2_class) {
7931 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7932 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7934 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7935 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7945 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7947 MonoGenericParam *gparam, *ogparam;
7948 MonoGenericParamInfo *tinfo, *cinfo;
7949 MonoClass **candidate_class;
7950 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7953 if (target == candidate)
7955 if (target->byval_arg.type != candidate->byval_arg.type)
7958 gparam = target->byval_arg.data.generic_param;
7959 ogparam = candidate->byval_arg.data.generic_param;
7960 tinfo = mono_generic_param_info (gparam);
7961 cinfo = mono_generic_param_info (ogparam);
7963 class_constraint_satisfied = FALSE;
7964 valuetype_constraint_satisfied = FALSE;
7966 /*candidate must have a super set of target's special constraints*/
7967 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7968 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7970 if (cinfo->constraints) {
7971 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7972 MonoClass *cc = *candidate_class;
7974 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7975 class_constraint_satisfied = TRUE;
7976 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7977 valuetype_constraint_satisfied = TRUE;
7980 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7981 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7983 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7985 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7987 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7988 valuetype_constraint_satisfied)) {
7993 /*candidate type constraints must be a superset of target's*/
7994 if (tinfo->constraints) {
7995 MonoClass **target_class;
7996 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7997 MonoClass *tc = *target_class;
8000 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8001 * check it's constraints since it satisfy the constraint by itself.
8003 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8006 if (!cinfo->constraints)
8009 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8010 MonoClass *cc = *candidate_class;
8012 if (mono_class_is_assignable_from (tc, cc))
8016 * This happens when we have the following:
8018 * Bar<K> where K : IFace
8019 * Foo<T, U> where T : U where U : IFace
8021 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8024 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8025 if (mono_gparam_is_assignable_from (target, cc))
8029 if (!*candidate_class)
8034 /*candidate itself must have a constraint that satisfy target*/
8035 if (cinfo->constraints) {
8036 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8037 MonoClass *cc = *candidate_class;
8038 if (mono_class_is_assignable_from (target, cc))
8046 * mono_class_is_assignable_from:
8047 * @klass: the class to be assigned to
8048 * @oklass: the source class
8050 * Return: true if an instance of object oklass can be assigned to an
8051 * instance of object @klass
8054 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8056 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8058 mono_class_init (klass);
8060 if (!oklass->inited)
8061 mono_class_init (oklass);
8063 if (klass->exception_type || oklass->exception_type)
8066 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8067 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8069 return mono_gparam_is_assignable_from (klass, oklass);
8072 if (MONO_CLASS_IS_INTERFACE (klass)) {
8073 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8074 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8075 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8079 for (i = 0; constraints [i]; ++i) {
8080 if (mono_class_is_assignable_from (klass, constraints [i]))
8088 /* interface_offsets might not be set for dynamic classes */
8089 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8091 * oklass might be a generic type parameter but they have
8092 * interface_offsets set.
8094 return mono_reflection_call_is_assignable_to (oklass, klass);
8095 if (!oklass->interface_bitmap)
8096 /* Happens with generic instances of not-yet created dynamic types */
8098 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8101 if (mono_class_has_variant_generic_params (klass)) {
8104 mono_class_setup_interfaces (oklass, &error);
8105 if (!mono_error_ok (&error)) {
8106 mono_error_cleanup (&error);
8110 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8111 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8112 MonoClass *iface = oklass->interfaces_packed [i];
8114 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8119 } else if (klass->delegate) {
8120 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8122 }else if (klass->rank) {
8123 MonoClass *eclass, *eoclass;
8125 if (oklass->rank != klass->rank)
8128 /* vectors vs. one dimensional arrays */
8129 if (oklass->byval_arg.type != klass->byval_arg.type)
8132 eclass = klass->cast_class;
8133 eoclass = oklass->cast_class;
8136 * a is b does not imply a[] is b[] when a is a valuetype, and
8137 * b is a reference type.
8140 if (eoclass->valuetype) {
8141 if ((eclass == mono_defaults.enum_class) ||
8142 (eclass == mono_defaults.enum_class->parent) ||
8143 (eclass == mono_defaults.object_class))
8147 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8148 } else if (mono_class_is_nullable (klass)) {
8149 if (mono_class_is_nullable (oklass))
8150 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8152 return mono_class_is_assignable_from (klass->cast_class, oklass);
8153 } else if (klass == mono_defaults.object_class)
8156 return mono_class_has_parent (oklass, klass);
8159 /*Check if @oklass is variant compatible with @klass.*/
8161 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8164 MonoType **klass_argv, **oklass_argv;
8165 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8166 MonoGenericContainer *container = klass_gtd->generic_container;
8168 /*Viable candidates are instances of the same generic interface*/
8169 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8172 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8173 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8175 for (j = 0; j < container->type_argc; ++j) {
8176 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8177 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8179 if (param1_class->valuetype != param2_class->valuetype)
8183 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8184 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8186 if (param1_class != param2_class) {
8187 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8188 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8190 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8191 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8199 /*Check if @candidate implements the interface @target*/
8201 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8205 gboolean is_variant = mono_class_has_variant_generic_params (target);
8207 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8208 if (mono_class_is_variant_compatible_slow (target, candidate))
8213 if (candidate == target)
8216 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8217 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8218 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8220 if (tb && tb->interfaces) {
8221 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8222 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8223 MonoClass *iface_class;
8225 /* we can't realize the type here since it can do pretty much anything. */
8228 iface_class = mono_class_from_mono_type (iface->type);
8229 if (iface_class == target)
8231 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8233 if (mono_class_implement_interface_slow (target, iface_class))
8238 /*setup_interfaces don't mono_class_init anything*/
8239 /*FIXME this doesn't handle primitive type arrays.
8240 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8241 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8243 mono_class_setup_interfaces (candidate, &error);
8244 if (!mono_error_ok (&error)) {
8245 mono_error_cleanup (&error);
8249 for (i = 0; i < candidate->interface_count; ++i) {
8250 if (candidate->interfaces [i] == target)
8253 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8256 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8260 candidate = candidate->parent;
8261 } while (candidate);
8267 * Check if @oklass can be assigned to @klass.
8268 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8271 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8273 if (candidate == target)
8275 if (target == mono_defaults.object_class)
8278 if (mono_class_has_parent (candidate, target))
8281 /*If target is not an interface there is no need to check them.*/
8282 if (MONO_CLASS_IS_INTERFACE (target))
8283 return mono_class_implement_interface_slow (target, candidate);
8285 if (target->delegate && mono_class_has_variant_generic_params (target))
8286 return mono_class_is_variant_compatible (target, candidate, FALSE);
8289 MonoClass *eclass, *eoclass;
8291 if (target->rank != candidate->rank)
8294 /* vectors vs. one dimensional arrays */
8295 if (target->byval_arg.type != candidate->byval_arg.type)
8298 eclass = target->cast_class;
8299 eoclass = candidate->cast_class;
8302 * a is b does not imply a[] is b[] when a is a valuetype, and
8303 * b is a reference type.
8306 if (eoclass->valuetype) {
8307 if ((eclass == mono_defaults.enum_class) ||
8308 (eclass == mono_defaults.enum_class->parent) ||
8309 (eclass == mono_defaults.object_class))
8313 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8315 /*FIXME properly handle nullables */
8316 /*FIXME properly handle (M)VAR */
8321 * mono_class_get_cctor:
8322 * @klass: A MonoClass pointer
8324 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8327 mono_class_get_cctor (MonoClass *klass)
8329 MonoCachedClassInfo cached_info;
8331 if (image_is_dynamic (klass->image)) {
8333 * has_cctor is not set for these classes because mono_class_init () is
8336 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8339 if (!klass->has_cctor)
8342 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8344 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8345 if (!mono_error_ok (&error))
8346 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8350 if (klass->generic_class && !klass->methods)
8351 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8353 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8357 * mono_class_get_finalizer:
8358 * @klass: The MonoClass pointer
8360 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8363 mono_class_get_finalizer (MonoClass *klass)
8365 MonoCachedClassInfo cached_info;
8368 mono_class_init (klass);
8369 if (!mono_class_has_finalizer (klass))
8372 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8374 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8375 if (!mono_error_ok (&error))
8376 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8379 mono_class_setup_vtable (klass);
8380 return klass->vtable [finalize_slot];
8385 * mono_class_needs_cctor_run:
8386 * @klass: the MonoClass pointer
8387 * @caller: a MonoMethod describing the caller
8389 * Determines whenever the class has a static constructor and whenever it
8390 * needs to be called when executing CALLER.
8393 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8397 method = mono_class_get_cctor (klass);
8399 return (method == caller) ? FALSE : TRUE;
8405 * mono_class_array_element_size:
8408 * Returns: the number of bytes an element of type @klass
8409 * uses when stored into an array.
8412 mono_class_array_element_size (MonoClass *klass)
8414 MonoType *type = &klass->byval_arg;
8417 switch (type->type) {
8420 case MONO_TYPE_BOOLEAN:
8424 case MONO_TYPE_CHAR:
8433 case MONO_TYPE_CLASS:
8434 case MONO_TYPE_STRING:
8435 case MONO_TYPE_OBJECT:
8436 case MONO_TYPE_SZARRAY:
8437 case MONO_TYPE_ARRAY:
8438 return sizeof (gpointer);
8443 case MONO_TYPE_VALUETYPE:
8444 if (type->data.klass->enumtype) {
8445 type = mono_class_enum_basetype (type->data.klass);
8446 klass = klass->element_class;
8449 return mono_class_instance_size (klass) - sizeof (MonoObject);
8450 case MONO_TYPE_GENERICINST:
8451 type = &type->data.generic_class->container_class->byval_arg;
8454 case MONO_TYPE_MVAR: {
8457 return mono_type_size (type, &align);
8459 case MONO_TYPE_VOID:
8463 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8469 * mono_array_element_size:
8470 * @ac: pointer to a #MonoArrayClass
8472 * Returns: the size of single array element.
8475 mono_array_element_size (MonoClass *ac)
8477 g_assert (ac->rank);
8478 return ac->sizes.element_size;
8482 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8483 MonoGenericContext *context)
8486 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8487 g_assert (mono_error_ok (&error));
8492 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8493 MonoGenericContext *context, MonoError *error)
8495 mono_error_init (error);
8497 if (image_is_dynamic (image)) {
8498 MonoClass *tmp_handle_class;
8499 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8501 g_assert (tmp_handle_class);
8503 *handle_class = tmp_handle_class;
8505 if (tmp_handle_class == mono_defaults.typehandle_class)
8506 return &((MonoClass*)obj)->byval_arg;
8511 switch (token & 0xff000000) {
8512 case MONO_TOKEN_TYPE_DEF:
8513 case MONO_TOKEN_TYPE_REF:
8514 case MONO_TOKEN_TYPE_SPEC: {
8517 *handle_class = mono_defaults.typehandle_class;
8518 type = mono_type_get_checked (image, token, context, error);
8522 mono_class_init (mono_class_from_mono_type (type));
8523 /* We return a MonoType* as handle */
8526 case MONO_TOKEN_FIELD_DEF: {
8528 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8530 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8534 *handle_class = mono_defaults.fieldhandle_class;
8535 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8539 mono_class_init (class);
8540 return mono_class_get_field (class, token);
8542 case MONO_TOKEN_METHOD_DEF:
8543 case MONO_TOKEN_METHOD_SPEC: {
8545 meth = mono_get_method_checked (image, token, NULL, context, error);
8547 *handle_class = mono_defaults.methodhandle_class;
8553 case MONO_TOKEN_MEMBER_REF: {
8554 guint32 cols [MONO_MEMBERREF_SIZE];
8556 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8557 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8558 mono_metadata_decode_blob_size (sig, &sig);
8559 if (*sig == 0x6) { /* it's a field */
8561 MonoClassField *field;
8562 field = mono_field_from_token_checked (image, token, &klass, context, error);
8564 *handle_class = mono_defaults.fieldhandle_class;
8568 meth = mono_get_method_checked (image, token, NULL, context, error);
8570 *handle_class = mono_defaults.methodhandle_class;
8575 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8581 * This function might need to call runtime functions so it can't be part
8582 * of the metadata library.
8584 static MonoLookupDynamicToken lookup_dynamic = NULL;
8587 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8589 lookup_dynamic = func;
8593 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8595 MonoClass *handle_class;
8597 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8601 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8603 return lookup_dynamic (image, token, valid_token, handle_class, context);
8606 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8609 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8611 get_cached_class_info = func;
8615 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8617 if (!get_cached_class_info)
8620 return get_cached_class_info (klass, res);
8624 mono_install_get_class_from_name (MonoGetClassFromName func)
8626 get_class_from_name = func;
8630 mono_class_get_image (MonoClass *klass)
8632 return klass->image;
8636 * mono_class_get_element_class:
8637 * @klass: the MonoClass to act on
8639 * Returns: the element class of an array or an enumeration.
8642 mono_class_get_element_class (MonoClass *klass)
8644 return klass->element_class;
8648 * mono_class_is_valuetype:
8649 * @klass: the MonoClass to act on
8651 * Returns: true if the MonoClass represents a ValueType.
8654 mono_class_is_valuetype (MonoClass *klass)
8656 return klass->valuetype;
8660 * mono_class_is_enum:
8661 * @klass: the MonoClass to act on
8663 * Returns: true if the MonoClass represents an enumeration.
8666 mono_class_is_enum (MonoClass *klass)
8668 return klass->enumtype;
8672 * mono_class_enum_basetype:
8673 * @klass: the MonoClass to act on
8675 * Returns: the underlying type representation for an enumeration.
8678 mono_class_enum_basetype (MonoClass *klass)
8680 if (klass->element_class == klass)
8681 /* SRE or broken types */
8684 return &klass->element_class->byval_arg;
8688 * mono_class_get_parent
8689 * @klass: the MonoClass to act on
8691 * Returns: the parent class for this class.
8694 mono_class_get_parent (MonoClass *klass)
8696 return klass->parent;
8700 * mono_class_get_nesting_type;
8701 * @klass: the MonoClass to act on
8703 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8706 mono_class_get_nesting_type (MonoClass *klass)
8708 return klass->nested_in;
8712 * mono_class_get_rank:
8713 * @klass: the MonoClass to act on
8715 * Returns: the rank for the array (the number of dimensions).
8718 mono_class_get_rank (MonoClass *klass)
8724 * mono_class_get_flags:
8725 * @klass: the MonoClass to act on
8727 * The type flags from the TypeDef table from the metadata.
8728 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8731 * Returns: the flags from the TypeDef table.
8734 mono_class_get_flags (MonoClass *klass)
8736 return klass->flags;
8740 * mono_class_get_name
8741 * @klass: the MonoClass to act on
8743 * Returns: the name of the class.
8746 mono_class_get_name (MonoClass *klass)
8752 * mono_class_get_namespace:
8753 * @klass: the MonoClass to act on
8755 * Returns: the namespace of the class.
8758 mono_class_get_namespace (MonoClass *klass)
8760 return klass->name_space;
8764 * mono_class_get_type:
8765 * @klass: the MonoClass to act on
8767 * This method returns the internal Type representation for the class.
8769 * Returns: the MonoType from the class.
8772 mono_class_get_type (MonoClass *klass)
8774 return &klass->byval_arg;
8778 * mono_class_get_type_token
8779 * @klass: the MonoClass to act on
8781 * This method returns type token for the class.
8783 * Returns: the type token for the class.
8786 mono_class_get_type_token (MonoClass *klass)
8788 return klass->type_token;
8792 * mono_class_get_byref_type:
8793 * @klass: the MonoClass to act on
8798 mono_class_get_byref_type (MonoClass *klass)
8800 return &klass->this_arg;
8804 * mono_class_num_fields:
8805 * @klass: the MonoClass to act on
8807 * Returns: the number of static and instance fields in the class.
8810 mono_class_num_fields (MonoClass *klass)
8812 return klass->field.count;
8816 * mono_class_num_methods:
8817 * @klass: the MonoClass to act on
8819 * Returns: the number of methods in the class.
8822 mono_class_num_methods (MonoClass *klass)
8824 return klass->method.count;
8828 * mono_class_num_properties
8829 * @klass: the MonoClass to act on
8831 * Returns: the number of properties in the class.
8834 mono_class_num_properties (MonoClass *klass)
8836 mono_class_setup_properties (klass);
8838 return klass->ext->property.count;
8842 * mono_class_num_events:
8843 * @klass: the MonoClass to act on
8845 * Returns: the number of events in the class.
8848 mono_class_num_events (MonoClass *klass)
8850 mono_class_setup_events (klass);
8852 return klass->ext->event.count;
8856 * mono_class_get_fields:
8857 * @klass: the MonoClass to act on
8859 * This routine is an iterator routine for retrieving the fields in a class.
8861 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8862 * iterate over all of the elements. When no more values are
8863 * available, the return value is NULL.
8865 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8868 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8870 MonoClassField* field;
8874 mono_class_setup_fields_locking (klass);
8875 if (klass->exception_type)
8877 /* start from the first */
8878 if (klass->field.count) {
8879 return *iter = &klass->fields [0];
8887 if (field < &klass->fields [klass->field.count]) {
8888 return *iter = field;
8894 * mono_class_get_methods
8895 * @klass: the MonoClass to act on
8897 * This routine is an iterator routine for retrieving the fields in a class.
8899 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8900 * iterate over all of the elements. When no more values are
8901 * available, the return value is NULL.
8903 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8906 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8908 MonoMethod** method;
8912 mono_class_setup_methods (klass);
8915 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8916 * FIXME we should better report this error to the caller
8918 if (!klass->methods)
8920 /* start from the first */
8921 if (klass->method.count) {
8922 *iter = &klass->methods [0];
8923 return klass->methods [0];
8931 if (method < &klass->methods [klass->method.count]) {
8939 * mono_class_get_virtual_methods:
8941 * Iterate over the virtual methods of KLASS.
8943 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8946 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8948 MonoMethod** method;
8951 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8953 mono_class_setup_methods (klass);
8955 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8956 * FIXME we should better report this error to the caller
8958 if (!klass->methods)
8960 /* start from the first */
8961 method = &klass->methods [0];
8966 while (method < &klass->methods [klass->method.count]) {
8967 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8971 if (method < &klass->methods [klass->method.count]) {
8978 /* Search directly in metadata to avoid calling setup_methods () */
8979 MonoMethod *res = NULL;
8985 start_index = GPOINTER_TO_UINT (*iter);
8988 for (i = start_index; i < klass->method.count; ++i) {
8991 /* class->method.first points into the methodptr table */
8992 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8994 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8998 if (i < klass->method.count) {
9000 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9001 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9003 /* Add 1 here so the if (*iter) check fails */
9004 *iter = GUINT_TO_POINTER (i + 1);
9013 * mono_class_get_properties:
9014 * @klass: the MonoClass to act on
9016 * This routine is an iterator routine for retrieving the properties in a class.
9018 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9019 * iterate over all of the elements. When no more values are
9020 * available, the return value is NULL.
9022 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9025 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9027 MonoProperty* property;
9031 mono_class_setup_properties (klass);
9032 /* start from the first */
9033 if (klass->ext->property.count) {
9034 return *iter = &klass->ext->properties [0];
9042 if (property < &klass->ext->properties [klass->ext->property.count]) {
9043 return *iter = property;
9049 * mono_class_get_events:
9050 * @klass: the MonoClass to act on
9052 * This routine is an iterator routine for retrieving the properties in a class.
9054 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9055 * iterate over all of the elements. When no more values are
9056 * available, the return value is NULL.
9058 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9061 mono_class_get_events (MonoClass* klass, gpointer *iter)
9067 mono_class_setup_events (klass);
9068 /* start from the first */
9069 if (klass->ext->event.count) {
9070 return *iter = &klass->ext->events [0];
9078 if (event < &klass->ext->events [klass->ext->event.count]) {
9079 return *iter = event;
9085 * mono_class_get_interfaces
9086 * @klass: the MonoClass to act on
9088 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9090 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9091 * iterate over all of the elements. When no more values are
9092 * available, the return value is NULL.
9094 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9097 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9105 mono_class_init (klass);
9106 if (!klass->interfaces_inited) {
9107 mono_class_setup_interfaces (klass, &error);
9108 if (!mono_error_ok (&error)) {
9109 mono_error_cleanup (&error);
9113 /* start from the first */
9114 if (klass->interface_count) {
9115 *iter = &klass->interfaces [0];
9116 return klass->interfaces [0];
9124 if (iface < &klass->interfaces [klass->interface_count]) {
9132 setup_nested_types (MonoClass *klass)
9135 GList *classes, *nested_classes, *l;
9138 if (klass->nested_classes_inited)
9141 if (!klass->type_token)
9142 klass->nested_classes_inited = TRUE;
9144 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9148 guint32 cols [MONO_NESTED_CLASS_SIZE];
9149 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9150 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9151 if (!mono_error_ok (&error)) {
9152 /*FIXME don't swallow the error message*/
9153 mono_error_cleanup (&error);
9155 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9159 classes = g_list_prepend (classes, nclass);
9161 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9164 mono_class_alloc_ext (klass);
9166 nested_classes = NULL;
9167 for (l = classes; l; l = l->next)
9168 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9169 g_list_free (classes);
9171 mono_image_lock (klass->image);
9173 mono_memory_barrier ();
9174 if (!klass->nested_classes_inited) {
9175 klass->ext->nested_classes = nested_classes;
9176 mono_memory_barrier ();
9177 klass->nested_classes_inited = TRUE;
9180 mono_image_unlock (klass->image);
9184 * mono_class_get_nested_types
9185 * @klass: the MonoClass to act on
9187 * This routine is an iterator routine for retrieving the nested types of a class.
9188 * This works only if @klass is non-generic, or a generic type definition.
9190 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9191 * iterate over all of the elements. When no more values are
9192 * available, the return value is NULL.
9194 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9197 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9203 if (!klass->nested_classes_inited)
9204 setup_nested_types (klass);
9207 /* start from the first */
9208 if (klass->ext && klass->ext->nested_classes) {
9209 *iter = klass->ext->nested_classes;
9210 return klass->ext->nested_classes->data;
9212 /* no nested types */
9227 * mono_class_is_delegate
9228 * @klass: the MonoClass to act on
9230 * Returns: true if the MonoClass represents a System.Delegate.
9233 mono_class_is_delegate (MonoClass *klass)
9235 return klass->delegate;
9239 * mono_class_implements_interface
9240 * @klass: The MonoClass to act on
9241 * @interface: The interface to check if @klass implements.
9243 * Returns: true if @klass implements @interface.
9246 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9248 return mono_class_is_assignable_from (iface, klass);
9252 * mono_field_get_name:
9253 * @field: the MonoClassField to act on
9255 * Returns: the name of the field.
9258 mono_field_get_name (MonoClassField *field)
9264 * mono_field_get_type:
9265 * @field: the MonoClassField to act on
9267 * Returns: MonoType of the field.
9270 mono_field_get_type (MonoClassField *field)
9273 MonoType *type = mono_field_get_type_checked (field, &error);
9274 if (!mono_error_ok (&error)) {
9275 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9276 mono_error_cleanup (&error);
9283 * mono_field_get_type_checked:
9284 * @field: the MonoClassField to act on
9285 * @error: used to return any erro found while retrieving @field type
9287 * Returns: MonoType of the field.
9290 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9292 mono_error_init (error);
9294 mono_field_resolve_type (field, error);
9299 * mono_field_get_parent:
9300 * @field: the MonoClassField to act on
9302 * Returns: MonoClass where the field was defined.
9305 mono_field_get_parent (MonoClassField *field)
9307 return field->parent;
9311 * mono_field_get_flags;
9312 * @field: the MonoClassField to act on
9314 * The metadata flags for a field are encoded using the
9315 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9317 * Returns: the flags for the field.
9320 mono_field_get_flags (MonoClassField *field)
9323 return mono_field_resolve_flags (field);
9324 return field->type->attrs;
9328 * mono_field_get_offset;
9329 * @field: the MonoClassField to act on
9331 * Returns: the field offset.
9334 mono_field_get_offset (MonoClassField *field)
9336 return field->offset;
9340 mono_field_get_rva (MonoClassField *field)
9344 MonoClass *klass = field->parent;
9345 MonoFieldDefaultValue *field_def_values;
9347 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9349 if (!klass->ext || !klass->ext->field_def_values) {
9350 mono_class_alloc_ext (klass);
9352 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9354 mono_image_lock (klass->image);
9355 if (!klass->ext->field_def_values)
9356 klass->ext->field_def_values = field_def_values;
9357 mono_image_unlock (klass->image);
9360 field_index = mono_field_get_index (field);
9362 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9363 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9365 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9366 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9369 return klass->ext->field_def_values [field_index].data;
9373 * mono_field_get_data;
9374 * @field: the MonoClassField to act on
9376 * Returns: pointer to the metadata constant value or to the field
9377 * data if it has an RVA flag.
9380 mono_field_get_data (MonoClassField *field)
9382 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9383 MonoTypeEnum def_type;
9385 return mono_class_get_field_default_value (field, &def_type);
9386 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9387 return mono_field_get_rva (field);
9394 * mono_property_get_name:
9395 * @prop: the MonoProperty to act on
9397 * Returns: the name of the property
9400 mono_property_get_name (MonoProperty *prop)
9406 * mono_property_get_set_method
9407 * @prop: the MonoProperty to act on.
9409 * Returns: the setter method of the property (A MonoMethod)
9412 mono_property_get_set_method (MonoProperty *prop)
9418 * mono_property_get_get_method
9419 * @prop: the MonoProperty to act on.
9421 * Returns: the setter method of the property (A MonoMethod)
9424 mono_property_get_get_method (MonoProperty *prop)
9430 * mono_property_get_parent:
9431 * @prop: the MonoProperty to act on.
9433 * Returns: the MonoClass where the property was defined.
9436 mono_property_get_parent (MonoProperty *prop)
9438 return prop->parent;
9442 * mono_property_get_flags:
9443 * @prop: the MonoProperty to act on.
9445 * The metadata flags for a property are encoded using the
9446 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9448 * Returns: the flags for the property.
9451 mono_property_get_flags (MonoProperty *prop)
9457 * mono_event_get_name:
9458 * @event: the MonoEvent to act on
9460 * Returns: the name of the event.
9463 mono_event_get_name (MonoEvent *event)
9469 * mono_event_get_add_method:
9470 * @event: The MonoEvent to act on.
9472 * Returns: the @add' method for the event (a MonoMethod).
9475 mono_event_get_add_method (MonoEvent *event)
9481 * mono_event_get_remove_method:
9482 * @event: The MonoEvent to act on.
9484 * Returns: the @remove method for the event (a MonoMethod).
9487 mono_event_get_remove_method (MonoEvent *event)
9489 return event->remove;
9493 * mono_event_get_raise_method:
9494 * @event: The MonoEvent to act on.
9496 * Returns: the @raise method for the event (a MonoMethod).
9499 mono_event_get_raise_method (MonoEvent *event)
9501 return event->raise;
9505 * mono_event_get_parent:
9506 * @event: the MonoEvent to act on.
9508 * Returns: the MonoClass where the event is defined.
9511 mono_event_get_parent (MonoEvent *event)
9513 return event->parent;
9517 * mono_event_get_flags
9518 * @event: the MonoEvent to act on.
9520 * The metadata flags for an event are encoded using the
9521 * EVENT_* constants. See the tabledefs.h file for details.
9523 * Returns: the flags for the event.
9526 mono_event_get_flags (MonoEvent *event)
9528 return event->attrs;
9532 * mono_class_get_method_from_name:
9533 * @klass: where to look for the method
9534 * @name: name of the method
9535 * @param_count: number of parameters. -1 for any number.
9537 * Obtains a MonoMethod with a given name and number of parameters.
9538 * It only works if there are no multiple signatures for any given method name.
9541 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9543 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9547 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9549 MonoMethod *res = NULL;
9552 /* Search directly in the metadata to avoid calling setup_methods () */
9553 for (i = 0; i < klass->method.count; ++i) {
9555 guint32 cols [MONO_METHOD_SIZE];
9557 MonoMethodSignature *sig;
9559 /* class->method.first points into the methodptr table */
9560 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9562 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9563 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9565 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9568 if (param_count == -1) {
9572 sig = mono_method_signature_checked (method, &error);
9574 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9577 if (sig->param_count == param_count) {
9588 * mono_class_get_method_from_name_flags:
9589 * @klass: where to look for the method
9590 * @name_space: name of the method
9591 * @param_count: number of parameters. -1 for any number.
9592 * @flags: flags which must be set in the method
9594 * Obtains a MonoMethod with a given name and number of parameters.
9595 * It only works if there are no multiple signatures for any given method name.
9598 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9600 MonoMethod *res = NULL;
9603 mono_class_init (klass);
9605 if (klass->generic_class && !klass->methods) {
9606 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9609 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9610 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9615 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9616 mono_class_setup_methods (klass);
9618 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9619 See mono/tests/array_load_exception.il
9620 FIXME we should better report this error to the caller
9622 if (!klass->methods)
9624 for (i = 0; i < klass->method.count; ++i) {
9625 MonoMethod *method = klass->methods [i];
9627 if (method->name[0] == name [0] &&
9628 !strcmp (name, method->name) &&
9629 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9630 ((method->flags & flags) == flags)) {
9637 res = find_method_in_metadata (klass, name, param_count, flags);
9644 * mono_class_set_failure:
9645 * @klass: class in which the failure was detected
9646 * @ex_type: the kind of exception/error to be thrown (later)
9647 * @ex_data: exception data (specific to each type of exception/error)
9649 * Keep a detected failure informations in the class for later processing.
9650 * Note that only the first failure is kept.
9652 * LOCKING: Acquires the loader lock.
9655 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9657 if (klass->exception_type)
9660 mono_loader_lock ();
9661 klass->exception_type = ex_type;
9663 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9664 mono_loader_unlock ();
9670 * mono_class_get_exception_data:
9672 * Return the exception_data property of KLASS.
9674 * LOCKING: Acquires the loader lock.
9677 mono_class_get_exception_data (MonoClass *klass)
9679 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9683 * mono_classes_init:
9685 * Initialize the resources used by this module.
9688 mono_classes_init (void)
9690 mono_mutex_init (&classes_mutex);
9692 mono_counters_register ("Inflated methods size",
9693 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9694 mono_counters_register ("Inflated classes",
9695 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9696 mono_counters_register ("Inflated classes size",
9697 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9698 mono_counters_register ("MonoClass size",
9699 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9700 mono_counters_register ("MonoClassExt size",
9701 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9705 * mono_classes_cleanup:
9707 * Free the resources used by this module.
9710 mono_classes_cleanup (void)
9712 if (global_interface_bitset)
9713 mono_bitset_free (global_interface_bitset);
9714 global_interface_bitset = NULL;
9715 mono_mutex_destroy (&classes_mutex);
9719 * mono_class_get_exception_for_failure:
9720 * @klass: class in which the failure was detected
9722 * Return a constructed MonoException than the caller can then throw
9723 * using mono_raise_exception - or NULL if no failure is present (or
9724 * doesn't result in an exception).
9727 mono_class_get_exception_for_failure (MonoClass *klass)
9729 gpointer exception_data = mono_class_get_exception_data (klass);
9731 switch (klass->exception_type) {
9732 #ifndef DISABLE_SECURITY
9733 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9734 MonoDomain *domain = mono_domain_get ();
9735 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9736 MonoMethod *method = exception_data;
9737 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9738 MonoObject *exc = NULL;
9742 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9743 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9744 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9746 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9747 return (MonoException*) exc;
9750 case MONO_EXCEPTION_TYPE_LOAD: {
9753 char *str = mono_type_get_full_name (klass);
9754 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9755 name = mono_string_new (mono_domain_get (), str);
9757 ex = mono_get_exception_type_load (name, astr);
9761 case MONO_EXCEPTION_MISSING_METHOD: {
9762 char *class_name = exception_data;
9763 char *assembly_name = class_name + strlen (class_name) + 1;
9765 return mono_get_exception_missing_method (class_name, assembly_name);
9767 case MONO_EXCEPTION_MISSING_FIELD: {
9768 char *class_name = exception_data;
9769 char *member_name = class_name + strlen (class_name) + 1;
9771 return mono_get_exception_missing_field (class_name, member_name);
9773 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9774 char *msg_format = exception_data;
9775 char *assembly_name = msg_format + strlen (msg_format) + 1;
9776 char *msg = g_strdup_printf (msg_format, assembly_name);
9779 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9785 case MONO_EXCEPTION_BAD_IMAGE: {
9786 return mono_get_exception_bad_image_format (exception_data);
9789 MonoLoaderError *error;
9792 error = mono_loader_get_last_error ();
9794 ex = mono_loader_error_prepare_exception (error);
9798 /* TODO - handle other class related failures */
9805 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9807 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9808 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9810 if (outer_klass == inner_klass)
9812 inner_klass = inner_klass->nested_in;
9813 } while (inner_klass);
9818 mono_class_get_generic_type_definition (MonoClass *klass)
9820 return klass->generic_class ? klass->generic_class->container_class : klass;
9824 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9826 * Generic instantiations are ignored for all super types of @klass.
9828 * Visibility checks ignoring generic instantiations.
9831 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9834 klass = mono_class_get_generic_type_definition (klass);
9835 parent = mono_class_get_generic_type_definition (parent);
9836 mono_class_setup_supertypes (klass);
9838 for (i = 0; i < klass->idepth; ++i) {
9839 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9845 * Subtype can only access parent members with family protection if the site object
9846 * is subclass of Subtype. For example:
9847 * class A { protected int x; }
9849 * void valid_access () {
9853 * void invalid_access () {
9860 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9862 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9865 if (context_klass == NULL)
9867 /*if access_klass is not member_klass context_klass must be type compat*/
9868 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9874 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9877 if (accessing == accessed)
9879 if (!accessed || !accessing)
9882 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9883 * anywhere so untrusted friends are not safe to access platform's code internals */
9884 if (mono_security_core_clr_enabled ()) {
9885 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9889 mono_assembly_load_friends (accessed);
9890 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9891 MonoAssemblyName *friend = tmp->data;
9892 /* Be conservative with checks */
9895 if (strcmp (accessing->aname.name, friend->name))
9897 if (friend->public_key_token [0]) {
9898 if (!accessing->aname.public_key_token [0])
9900 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9909 * If klass is a generic type or if it is derived from a generic type, return the
9910 * MonoClass of the generic definition
9911 * Returns NULL if not found
9914 get_generic_definition_class (MonoClass *klass)
9917 if (klass->generic_class && klass->generic_class->container_class)
9918 return klass->generic_class->container_class;
9919 klass = klass->parent;
9925 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9928 for (i = 0; i < ginst->type_argc; ++i) {
9929 MonoType *type = ginst->type_argv[i];
9930 switch (type->type) {
9931 case MONO_TYPE_SZARRAY:
9932 if (!can_access_type (access_klass, type->data.klass))
9935 case MONO_TYPE_ARRAY:
9936 if (!can_access_type (access_klass, type->data.array->eklass))
9940 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9943 case MONO_TYPE_CLASS:
9944 case MONO_TYPE_VALUETYPE:
9945 case MONO_TYPE_GENERICINST:
9946 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9954 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9958 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9961 if (access_klass->element_class && !access_klass->enumtype)
9962 access_klass = access_klass->element_class;
9964 if (member_klass->element_class && !member_klass->enumtype)
9965 member_klass = member_klass->element_class;
9967 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9969 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9972 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9975 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9978 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9981 /*Non nested type with nested visibility. We just fail it.*/
9982 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9985 switch (access_level) {
9986 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9987 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9989 case TYPE_ATTRIBUTE_PUBLIC:
9992 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9995 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9996 return is_nesting_type (member_klass, access_klass);
9998 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9999 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10001 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10002 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10004 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10005 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10006 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10008 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10009 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10010 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10015 /* FIXME: check visibility of type, too */
10017 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10019 MonoClass *member_generic_def;
10020 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10023 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10024 access_klass->generic_container) &&
10025 (member_generic_def = get_generic_definition_class (member_klass))) {
10026 MonoClass *access_container;
10028 if (access_klass->generic_container)
10029 access_container = access_klass;
10031 access_container = access_klass->generic_class->container_class;
10033 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10037 /* Partition I 8.5.3.2 */
10038 /* the access level values are the same for fields and methods */
10039 switch (access_level) {
10040 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10041 /* same compilation unit */
10042 return access_klass->image == member_klass->image;
10043 case FIELD_ATTRIBUTE_PRIVATE:
10044 return access_klass == member_klass;
10045 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10046 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10047 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10050 case FIELD_ATTRIBUTE_ASSEMBLY:
10051 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10052 case FIELD_ATTRIBUTE_FAMILY:
10053 if (is_valid_family_access (access_klass, member_klass, context_klass))
10056 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10057 if (is_valid_family_access (access_klass, member_klass, context_klass))
10059 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10060 case FIELD_ATTRIBUTE_PUBLIC:
10067 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10069 /* FIXME: check all overlapping fields */
10070 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10072 MonoClass *nested = method->klass->nested_in;
10074 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10077 nested = nested->nested_in;
10084 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10086 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10088 MonoClass *nested = method->klass->nested_in;
10090 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10093 nested = nested->nested_in;
10098 * with generics calls to explicit interface implementations can be expressed
10099 * directly: the method is private, but we must allow it. This may be opening
10100 * a hole or the generics code should handle this differently.
10101 * Maybe just ensure the interface type is public.
10103 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10109 * mono_method_can_access_method_full:
10110 * @method: The caller method
10111 * @called: The called method
10112 * @context_klass: The static type on stack of the owner @called object used
10114 * This function must be used with instance calls, as they have more strict family accessibility.
10115 * It can be used with static methods, but context_klass should be NULL.
10117 * Returns: TRUE if caller have proper visibility and acessibility to @called
10120 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10122 MonoClass *access_class = method->klass;
10123 MonoClass *member_class = called->klass;
10124 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10126 MonoClass *nested = access_class->nested_in;
10128 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10131 nested = nested->nested_in;
10138 can = can_access_type (access_class, member_class);
10140 MonoClass *nested = access_class->nested_in;
10142 can = can_access_type (nested, member_class);
10145 nested = nested->nested_in;
10152 if (called->is_inflated) {
10153 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10154 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10163 * mono_method_can_access_field_full:
10164 * @method: The caller method
10165 * @field: The accessed field
10166 * @context_klass: The static type on stack of the owner @field object used
10168 * This function must be used with instance fields, as they have more strict family accessibility.
10169 * It can be used with static fields, but context_klass should be NULL.
10171 * Returns: TRUE if caller have proper visibility and acessibility to @field
10174 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10176 MonoClass *access_class = method->klass;
10177 MonoClass *member_class = field->parent;
10178 /* FIXME: check all overlapping fields */
10179 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10181 MonoClass *nested = access_class->nested_in;
10183 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10186 nested = nested->nested_in;
10193 can = can_access_type (access_class, member_class);
10195 MonoClass *nested = access_class->nested_in;
10197 can = can_access_type (nested, member_class);
10200 nested = nested->nested_in;
10210 * mono_class_can_access_class:
10211 * @source_class: The source class
10212 * @target_class: The accessed class
10214 * This function returns is @target_class is visible to @source_class
10216 * Returns: TRUE if source have proper visibility and acessibility to target
10219 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10221 return can_access_type (source_class, target_class);
10225 * mono_type_is_valid_enum_basetype:
10226 * @type: The MonoType to check
10228 * Returns: TRUE if the type can be used as the basetype of an enum
10230 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10231 switch (type->type) {
10234 case MONO_TYPE_BOOLEAN:
10237 case MONO_TYPE_CHAR:
10250 * mono_class_is_valid_enum:
10251 * @klass: An enum class to be validated
10253 * This method verify the required properties an enum should have.
10255 * Returns: TRUE if the informed enum class is valid
10257 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10258 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10259 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10261 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10262 MonoClassField * field;
10263 gpointer iter = NULL;
10264 gboolean found_base_field = FALSE;
10266 g_assert (klass->enumtype);
10267 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10268 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10272 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10275 while ((field = mono_class_get_fields (klass, &iter))) {
10276 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10277 if (found_base_field)
10279 found_base_field = TRUE;
10280 if (!mono_type_is_valid_enum_basetype (field->type))
10285 if (!found_base_field)
10288 if (klass->method.count > 0)
10295 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10297 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10301 * mono_class_setup_interface_id:
10303 * Initializes MonoClass::interface_id if required.
10305 * LOCKING: Acquires the loader lock.
10308 mono_class_setup_interface_id (MonoClass *class)
10310 mono_loader_lock ();
10311 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10312 class->interface_id = mono_get_unique_iid (class);
10313 mono_loader_unlock ();
10317 * mono_class_alloc_ext:
10319 * Allocate klass->ext if not already done.
10322 mono_class_alloc_ext (MonoClass *klass)
10329 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10330 mono_image_lock (klass->image);
10331 mono_memory_barrier ();
10334 class_ext_size += sizeof (MonoClassExt);
10335 mono_image_unlock (klass->image);
10339 * mono_class_setup_interfaces:
10341 * Initialize class->interfaces/interfaces_count.
10342 * LOCKING: Acquires the loader lock.
10343 * This function can fail the type.
10346 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10348 int i, interface_count;
10349 MonoClass **interfaces;
10351 mono_error_init (error);
10353 if (klass->interfaces_inited)
10356 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10357 MonoType *args [1];
10359 /* generic IList, ICollection, IEnumerable */
10360 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10361 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10363 args [0] = &klass->element_class->byval_arg;
10364 interfaces [0] = mono_class_bind_generic_parameters (
10365 mono_defaults.generic_ilist_class, 1, args, FALSE);
10366 if (interface_count > 1)
10367 interfaces [1] = mono_class_bind_generic_parameters (
10368 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10369 } else if (klass->generic_class) {
10370 MonoClass *gklass = klass->generic_class->container_class;
10372 mono_class_setup_interfaces (gklass, error);
10373 if (!mono_error_ok (error)) {
10374 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10378 interface_count = gklass->interface_count;
10379 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10380 for (i = 0; i < interface_count; i++) {
10381 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10382 if (!mono_error_ok (error)) {
10383 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10388 interface_count = 0;
10392 mono_image_lock (klass->image);
10394 if (!klass->interfaces_inited) {
10395 klass->interface_count = interface_count;
10396 klass->interfaces = interfaces;
10398 mono_memory_barrier ();
10400 klass->interfaces_inited = TRUE;
10403 mono_image_unlock (klass->image);
10407 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10409 MonoClass *class = field->parent;
10410 MonoImage *image = class->image;
10411 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10412 int field_idx = field - class->fields;
10414 mono_error_init (error);
10417 MonoClassField *gfield = >d->fields [field_idx];
10418 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10419 if (!mono_error_ok (error)) {
10420 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10421 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10425 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10426 if (!mono_error_ok (error)) {
10427 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10428 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10433 guint32 cols [MONO_FIELD_SIZE];
10434 MonoGenericContainer *container = NULL;
10435 int idx = class->field.first + field_idx;
10437 /*FIXME, in theory we do not lazy load SRE fields*/
10438 g_assert (!image_is_dynamic (image));
10440 if (class->generic_container) {
10441 container = class->generic_container;
10443 container = gtd->generic_container;
10444 g_assert (container);
10447 /* class->field.first and idx points into the fieldptr table */
10448 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10450 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10451 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10452 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10456 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10458 mono_metadata_decode_value (sig, &sig);
10459 /* FIELD signature == 0x06 */
10460 g_assert (*sig == 0x06);
10461 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10463 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10468 mono_field_resolve_flags (MonoClassField *field)
10470 MonoClass *class = field->parent;
10471 MonoImage *image = class->image;
10472 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10473 int field_idx = field - class->fields;
10477 MonoClassField *gfield = >d->fields [field_idx];
10478 return mono_field_get_flags (gfield);
10480 int idx = class->field.first + field_idx;
10482 /*FIXME, in theory we do not lazy load SRE fields*/
10483 g_assert (!image_is_dynamic (image));
10485 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10490 * mono_class_setup_basic_field_info:
10491 * @class: The class to initialize
10493 * Initializes the class->fields array of fields.
10494 * Aquires the loader lock.
10497 mono_class_setup_basic_field_info_locking (MonoClass *class)
10499 mono_loader_lock ();
10500 mono_class_setup_basic_field_info (class);
10501 mono_loader_unlock ();
10505 * mono_class_get_fields_lazy:
10506 * @klass: the MonoClass to act on
10508 * This routine is an iterator routine for retrieving the fields in a class.
10509 * Only minimal information about fields are loaded. Accessors must be used
10510 * for all MonoClassField returned.
10512 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10513 * iterate over all of the elements. When no more values are
10514 * available, the return value is NULL.
10516 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10519 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10521 MonoClassField* field;
10525 mono_class_setup_basic_field_info_locking (klass);
10526 if (!klass->fields)
10528 /* start from the first */
10529 if (klass->field.count) {
10530 return *iter = &klass->fields [0];
10538 if (field < &klass->fields [klass->field.count]) {
10539 return *iter = field;
10545 mono_class_full_name (MonoClass *klass)
10547 return mono_type_full_name (&klass->byval_arg);