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:
626 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
628 mono_error_init (error);
630 switch (type->type) {
631 case MONO_TYPE_MVAR: {
633 int num = mono_type_get_generic_param_num (type);
634 MonoGenericInst *inst = context->method_inst;
635 if (!inst || !inst->type_argv)
637 if (num >= inst->type_argc) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
640 num, info ? info->name : "", inst->type_argc);
644 if (!is_valid_generic_argument (inst->type_argv [num])) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
647 num, info ? info->name : "", inst->type_argv [num]->type);
651 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
652 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
653 * ->byref and ->attrs from @type are propagated to the returned type.
655 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
656 nt->byref = type->byref;
657 nt->attrs = type->attrs;
660 case MONO_TYPE_VAR: {
662 int num = mono_type_get_generic_param_num (type);
663 MonoGenericInst *inst = context->class_inst;
666 if (num >= inst->type_argc) {
667 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
668 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
669 num, info ? info->name : "", inst->type_argc);
672 if (!is_valid_generic_argument (inst->type_argv [num])) {
673 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
674 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
675 num, info ? info->name : "", inst->type_argv [num]->type);
678 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
679 nt->byref = type->byref;
680 nt->attrs = type->attrs;
683 case MONO_TYPE_SZARRAY: {
684 MonoClass *eclass = type->data.klass;
685 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
686 if (!inflated || !mono_error_ok (error))
688 nt = mono_metadata_type_dup (image, type);
689 nt->data.klass = mono_class_from_mono_type (inflated);
690 mono_metadata_free_type (inflated);
693 case MONO_TYPE_ARRAY: {
694 MonoClass *eclass = type->data.array->eklass;
695 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
696 if (!inflated || !mono_error_ok (error))
698 nt = mono_metadata_type_dup (image, type);
699 nt->data.array->eklass = mono_class_from_mono_type (inflated);
700 mono_metadata_free_type (inflated);
703 case MONO_TYPE_GENERICINST: {
704 MonoGenericClass *gclass = type->data.generic_class;
705 MonoGenericInst *inst;
707 if (!gclass->context.class_inst->is_open)
710 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
711 if (!mono_error_ok (error))
713 if (inst != gclass->context.class_inst)
714 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
716 if (gclass == type->data.generic_class)
719 nt = mono_metadata_type_dup (image, type);
720 nt->data.generic_class = gclass;
723 case MONO_TYPE_CLASS:
724 case MONO_TYPE_VALUETYPE: {
725 MonoClass *klass = type->data.klass;
726 MonoGenericContainer *container = klass->generic_container;
727 MonoGenericInst *inst;
728 MonoGenericClass *gclass = NULL;
734 /* We can't use context->class_inst directly, since it can have more elements */
735 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
736 if (!mono_error_ok (error))
738 if (inst == container->context.class_inst)
741 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
743 nt = mono_metadata_type_dup (image, type);
744 nt->type = MONO_TYPE_GENERICINST;
745 nt->data.generic_class = gclass;
755 mono_generic_class_get_context (MonoGenericClass *gclass)
757 return &gclass->context;
761 mono_class_get_context (MonoClass *class)
763 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
767 * mono_class_get_generic_container:
769 * Return the generic container of KLASS which should be a generic type definition.
771 MonoGenericContainer*
772 mono_class_get_generic_container (MonoClass *klass)
774 g_assert (klass->is_generic);
776 return klass->generic_container;
780 * mono_class_get_generic_class:
782 * Return the MonoGenericClass of KLASS, which should be a generic instance.
785 mono_class_get_generic_class (MonoClass *klass)
787 g_assert (klass->is_inflated);
789 return klass->generic_class;
793 * mono_class_inflate_generic_type_with_mempool:
794 * @mempool: a mempool
796 * @context: a generics context
797 * @error: error context
799 * The same as mono_class_inflate_generic_type, but allocates the MonoType
800 * from mempool if it is non-NULL. If it is NULL, the MonoType is
801 * allocated on the heap and is owned by the caller.
802 * The returned type can potentially be the same as TYPE, so it should not be
803 * modified by the caller, and it should be freed using mono_metadata_free_type ().
806 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
808 MonoType *inflated = NULL;
809 mono_error_init (error);
812 inflated = inflate_generic_type (image, type, context, error);
813 if (!mono_error_ok (error))
817 MonoType *shared = mono_metadata_get_shared_type (type);
822 return mono_metadata_type_dup (image, type);
826 mono_stats.inflated_type_count++;
831 * mono_class_inflate_generic_type:
833 * @context: a generics context
835 * If @type is a generic type and @context is not NULL, instantiate it using the
836 * generics context @context.
838 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
839 * on the heap and is owned by the caller. Returns NULL on error.
841 * @deprecated Please use mono_class_inflate_generic_type_checked instead
844 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
848 result = mono_class_inflate_generic_type_checked (type, context, &error);
850 if (!mono_error_ok (&error)) {
851 mono_error_cleanup (&error);
858 * mono_class_inflate_generic_type:
860 * @context: a generics context
861 * @error: error context to use
863 * If @type is a generic type and @context is not NULL, instantiate it using the
864 * generics context @context.
866 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
867 * on the heap and is owned by the caller.
870 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
872 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
876 * mono_class_inflate_generic_type_no_copy:
878 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
882 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
884 MonoType *inflated = NULL;
886 mono_error_init (error);
888 inflated = inflate_generic_type (image, type, context, error);
889 if (!mono_error_ok (error))
896 mono_stats.inflated_type_count++;
901 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
906 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
907 if (!mono_error_ok (error))
910 res = mono_class_from_mono_type (inflated);
911 mono_metadata_free_type (inflated);
916 * mono_class_inflate_generic_class:
918 * Inflate the class GKLASS with CONTEXT.
921 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
926 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
927 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
934 static MonoGenericContext
935 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
937 MonoGenericInst *class_inst = NULL;
938 MonoGenericInst *method_inst = NULL;
939 MonoGenericContext res = { NULL, NULL };
941 mono_error_init (error);
943 if (context->class_inst) {
944 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
945 if (!mono_error_ok (error))
949 if (context->method_inst) {
950 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
951 if (!mono_error_ok (error))
955 res.class_inst = class_inst;
956 res.method_inst = method_inst;
962 * mono_class_inflate_generic_method:
963 * @method: a generic method
964 * @context: a generics context
966 * Instantiate the generic method @method using the generics context @context.
968 * Returns: the new instantiated method
971 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
973 return mono_class_inflate_generic_method_full (method, NULL, context);
977 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
979 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
983 * mono_class_inflate_generic_method_full:
985 * Instantiate method @method with the generic context @context.
986 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
987 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
990 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
993 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
994 if (!mono_error_ok (&error))
995 /*FIXME do proper error handling - on this case, kill this function. */
996 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1002 * mono_class_inflate_generic_method_full_checked:
1003 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1006 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1009 MonoMethodInflated *iresult, *cached;
1010 MonoMethodSignature *sig;
1011 MonoGenericContext tmp_context;
1012 gboolean is_mb_open = FALSE;
1014 mono_error_init (error);
1016 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1017 while (method->is_inflated) {
1018 MonoGenericContext *method_context = mono_method_get_context (method);
1019 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1021 tmp_context = inflate_generic_context (method_context, context, error);
1022 if (!mono_error_ok (error))
1024 context = &tmp_context;
1026 if (mono_metadata_generic_context_equal (method_context, context))
1029 method = imethod->declaring;
1033 * A method only needs to be inflated if the context has argument for which it is
1036 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1037 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1040 if (!((method->is_generic && context->method_inst) ||
1041 (method->klass->generic_container && context->class_inst)))
1045 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1046 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1047 * This is opposite to the way non-SRE MethodInfos behave.
1049 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1051 * void Example<T> () {
1055 * In Example, the method token must be encoded as: "void Example<!!0>()"
1057 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1058 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1060 * On the other hand, inflating a non-SRE generic method with its own arguments should
1061 * return itself. For example:
1063 * MethodInfo m = ... //m is a generic method definition
1064 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1067 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1068 * what happens with regular methods.
1070 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1071 * everything should behave like a regular type or method.
1074 is_mb_open = method->is_generic &&
1075 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1076 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1078 iresult = g_new0 (MonoMethodInflated, 1);
1079 iresult->context = *context;
1080 iresult->declaring = method;
1081 iresult->method.method.is_mb_open = is_mb_open;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1094 cached = mono_method_inflated_lookup (iresult, FALSE);
1097 return (MonoMethod*)cached;
1100 mono_stats.inflated_method_count++;
1102 inflated_methods_size += sizeof (MonoMethodInflated);
1104 sig = mono_method_signature (method);
1106 char *name = mono_type_get_full_name (method->klass);
1107 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1113 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1115 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1118 result = (MonoMethod *) iresult;
1119 result->is_inflated = TRUE;
1120 result->is_generic = FALSE;
1121 result->sre_method = FALSE;
1122 result->signature = NULL;
1123 result->is_mb_open = is_mb_open;
1125 if (!context->method_inst) {
1126 /* Set the generic_container of the result to the generic_container of method */
1127 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1129 if (generic_container) {
1130 result->is_generic = 1;
1131 mono_method_set_generic_container (result, generic_container);
1135 if (!klass_hint || !klass_hint->generic_class ||
1136 klass_hint->generic_class->container_class != method->klass ||
1137 klass_hint->generic_class->context.class_inst != context->class_inst)
1140 if (method->klass->generic_container)
1141 result->klass = klass_hint;
1143 if (!result->klass) {
1144 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1145 if (!mono_error_ok (error))
1148 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1150 mono_metadata_free_type (inflated);
1154 * FIXME: This should hold, but it doesn't:
1156 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1157 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1158 * g_assert (result->is_generic);
1161 * Fixing this here causes other things to break, hence a very
1162 * ugly hack in mini-trampolines.c - see
1163 * is_generic_method_definition().
1166 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1174 * mono_get_inflated_method:
1176 * Obsolete. We keep it around since it's mentioned in the public API.
1179 mono_get_inflated_method (MonoMethod *method)
1185 * mono_method_get_context_general:
1187 * @uninflated: handle uninflated methods?
1189 * Returns the generic context of a method or NULL if it doesn't have
1190 * one. For an inflated method that's the context stored in the
1191 * method. Otherwise it's in the method's generic container or in the
1192 * generic container of the method's class.
1195 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1197 if (method->is_inflated) {
1198 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1199 return &imethod->context;
1203 if (method->is_generic)
1204 return &(mono_method_get_generic_container (method)->context);
1205 if (method->klass->generic_container)
1206 return &method->klass->generic_container->context;
1211 * mono_method_get_context:
1214 * Returns the generic context for method if it's inflated, otherwise
1218 mono_method_get_context (MonoMethod *method)
1220 return mono_method_get_context_general (method, FALSE);
1224 * mono_method_get_generic_container:
1226 * Returns the generic container of METHOD, which should be a generic method definition.
1227 * Returns NULL if METHOD is not a generic method definition.
1228 * LOCKING: Acquires the loader lock.
1230 MonoGenericContainer*
1231 mono_method_get_generic_container (MonoMethod *method)
1233 MonoGenericContainer *container;
1235 if (!method->is_generic)
1238 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1239 g_assert (container);
1245 * mono_method_set_generic_container:
1247 * Sets the generic container of METHOD to CONTAINER.
1248 * LOCKING: Acquires the image lock.
1251 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1253 g_assert (method->is_generic);
1255 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1259 * mono_class_find_enum_basetype:
1260 * @class: The enum class
1262 * Determine the basetype of an enum by iterating through its fields. We do this
1263 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1266 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1268 MonoGenericContainer *container = NULL;
1269 MonoImage *m = class->image;
1270 const int top = class->field.count;
1273 g_assert (class->enumtype);
1275 mono_error_init (error);
1277 if (class->generic_container)
1278 container = class->generic_container;
1279 else if (class->generic_class) {
1280 MonoClass *gklass = class->generic_class->container_class;
1282 container = gklass->generic_container;
1283 g_assert (container);
1287 * Fetch all the field information.
1289 for (i = 0; i < top; i++){
1291 guint32 cols [MONO_FIELD_SIZE];
1292 int idx = class->field.first + i;
1295 /* class->field.first and idx points into the fieldptr table */
1296 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1298 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1301 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1302 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1306 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1307 mono_metadata_decode_value (sig, &sig);
1308 /* FIELD signature == 0x06 */
1310 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1314 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1316 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1317 mono_error_set_from_loader_error (error);
1319 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1322 if (class->generic_class) {
1323 //FIXME do we leak here?
1324 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1325 if (!mono_error_ok (error))
1327 ftype->attrs = cols [MONO_FIELD_FLAGS];
1332 mono_error_set_type_load_class (error, class, "Could not find base type");
1335 g_assert (!mono_loader_get_last_error ());
1340 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1343 mono_type_has_exceptions (MonoType *type)
1345 switch (type->type) {
1346 case MONO_TYPE_CLASS:
1347 case MONO_TYPE_VALUETYPE:
1348 case MONO_TYPE_SZARRAY:
1349 return type->data.klass->exception_type;
1350 case MONO_TYPE_ARRAY:
1351 return type->data.array->eklass->exception_type;
1352 case MONO_TYPE_GENERICINST:
1353 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1362 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1366 mono_class_alloc (MonoClass *class, int size)
1368 if (class->generic_class)
1369 return mono_image_set_alloc (class->generic_class->owner, size);
1371 return mono_image_alloc (class->image, size);
1375 mono_class_alloc0 (MonoClass *class, int size)
1379 res = mono_class_alloc (class, size);
1380 memset (res, 0, size);
1384 #define mono_class_new0(class,struct_type, n_structs) \
1385 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1388 * mono_class_setup_basic_field_info:
1389 * @class: The class to initialize
1391 * Initializes the class->fields.
1392 * LOCKING: Assumes the loader lock is held.
1395 mono_class_setup_basic_field_info (MonoClass *class)
1397 MonoClassField *field;
1405 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1406 image = class->image;
1407 top = class->field.count;
1409 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1411 * This happens when a generic instance of an unfinished generic typebuilder
1412 * is used as an element type for creating an array type. We can't initialize
1413 * the fields of this class using the fields of gklass, since gklass is not
1414 * finished yet, fields could be added to it later.
1420 mono_class_setup_basic_field_info (gtd);
1422 top = gtd->field.count;
1423 class->field.first = gtd->field.first;
1424 class->field.count = gtd->field.count;
1427 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1430 * Fetch all the field information.
1432 for (i = 0; i < top; i++){
1433 field = &class->fields [i];
1434 field->parent = class;
1437 field->name = mono_field_get_name (>d->fields [i]);
1439 int idx = class->field.first + i;
1440 /* class->field.first and idx points into the fieldptr table */
1441 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1442 /* The name is needed for fieldrefs */
1443 field->name = mono_metadata_string_heap (image, name_idx);
1449 * mono_class_setup_fields:
1450 * @class: The class to initialize
1452 * Initializes the class->fields.
1453 * LOCKING: Assumes the loader lock is held.
1456 mono_class_setup_fields (MonoClass *class)
1459 MonoImage *m = class->image;
1461 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1462 int i, blittable = TRUE;
1463 guint32 real_size = 0;
1464 guint32 packing_size = 0;
1465 gboolean explicit_size;
1466 MonoClassField *field;
1467 MonoGenericContainer *container = NULL;
1468 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1471 * FIXME: We have a race condition here. It's possible that this function returns
1472 * to its caller with `instance_size` set to `0` instead of the actual size. This
1473 * is not a problem when the function is called recursively on the same class,
1474 * because the size will be initialized by the outer invocation. What follows is a
1475 * description of how it can occur in other cases, too. There it is a problem,
1476 * because it can lead to the GC being asked to allocate an object of size `0`,
1477 * which SGen chokes on. The race condition is triggered infrequently by
1478 * `tests/sgen-suspend.cs`.
1480 * This function is called for a class whenever one of its subclasses is inited.
1481 * For example, it's called for every subclass of Object. What it does is this:
1483 * if (class->setup_fields_called)
1486 * class->instance_size = 0;
1488 * class->setup_fields_called = 1;
1489 * ... critical point
1490 * class->instance_size = actual_instance_size;
1492 * The last two steps are sometimes reversed, but that only changes the way in which
1493 * the race condition works.
1495 * Assume thread A goes through this function and makes it to the critical point.
1496 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1497 * immediately, but `instance_size` is incorrect.
1499 * The other case looks like this:
1501 * if (class->setup_fields_called)
1503 * ... critical point X
1504 * class->instance_size = 0;
1505 * ... critical point Y
1506 * class->instance_size = actual_instance_size;
1508 * class->setup_fields_called = 1;
1510 * Assume thread A goes through the function and makes it to critical point X. Now
1511 * thread B runs through the whole of the function, returning, assuming
1512 * `instance_size` is set. At that point thread A gets to run and makes it to
1513 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1516 if (class->setup_fields_called)
1519 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1521 * This happens when a generic instance of an unfinished generic typebuilder
1522 * is used as an element type for creating an array type. We can't initialize
1523 * the fields of this class using the fields of gklass, since gklass is not
1524 * finished yet, fields could be added to it later.
1529 mono_class_setup_basic_field_info (class);
1530 top = class->field.count;
1533 mono_class_setup_fields (gtd);
1534 if (gtd->exception_type) {
1535 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1540 class->instance_size = 0;
1542 class->sizes.class_size = 0;
1544 if (class->parent) {
1545 /* For generic instances, class->parent might not have been initialized */
1546 mono_class_init (class->parent);
1547 if (!class->parent->size_inited) {
1548 mono_class_setup_fields (class->parent);
1549 if (class->parent->exception_type) {
1550 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1554 class->instance_size += class->parent->instance_size;
1555 class->min_align = class->parent->min_align;
1556 /* we use |= since it may have been set already */
1557 class->has_references |= class->parent->has_references;
1558 blittable = class->parent->blittable;
1560 class->instance_size = sizeof (MonoObject);
1561 class->min_align = 1;
1564 /* We can't really enable 16 bytes alignment until the GC supports it.
1565 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1566 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1567 Bug #506144 is an example of this issue.
1569 if (class->simd_type)
1570 class->min_align = 16;
1572 /* Get the real size */
1573 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1575 if (explicit_size) {
1576 if ((packing_size & 0xffffff00) != 0) {
1577 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1578 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1581 class->packing_size = packing_size;
1582 real_size += class->instance_size;
1586 if (explicit_size && real_size) {
1587 class->instance_size = MAX (real_size, class->instance_size);
1589 class->blittable = blittable;
1590 mono_memory_barrier ();
1591 class->size_inited = 1;
1592 class->fields_inited = 1;
1593 class->setup_fields_called = 1;
1597 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1600 /* Prevent infinite loops if the class references itself */
1601 class->setup_fields_called = 1;
1603 if (class->generic_container) {
1604 container = class->generic_container;
1606 container = gtd->generic_container;
1607 g_assert (container);
1611 * Fetch all the field information.
1613 for (i = 0; i < top; i++){
1614 int idx = class->field.first + i;
1615 field = &class->fields [i];
1617 field->parent = class;
1620 mono_field_resolve_type (field, &error);
1621 if (!mono_error_ok (&error)) {
1622 /*mono_field_resolve_type already failed class*/
1623 mono_error_cleanup (&error);
1627 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1628 g_assert (field->type);
1631 if (mono_field_is_deleted (field))
1634 MonoClassField *gfield = >d->fields [i];
1635 field->offset = gfield->offset;
1637 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1639 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1640 field->offset = offset;
1642 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1646 if (field->offset < -1) { /*-1 is used to encode special static fields */
1647 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1650 if (class->generic_container) {
1651 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1657 /* Only do these checks if we still think this type is blittable */
1658 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1659 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1662 MonoClass *field_class = mono_class_from_mono_type (field->type);
1664 mono_class_setup_fields (field_class);
1665 if (field_class->exception_type) {
1666 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1670 if (!field_class || !field_class->blittable)
1675 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1676 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1677 blittable = class->element_class->blittable;
1680 if (mono_type_has_exceptions (field->type)) {
1681 char *class_name = mono_type_get_full_name (class);
1682 char *type_name = mono_type_full_name (field->type);
1684 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1685 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1686 g_free (class_name);
1690 /* The def_value of fields is compute lazily during vtable creation */
1693 if (class == mono_defaults.string_class)
1696 class->blittable = blittable;
1698 if (class->enumtype && !mono_class_enum_basetype (class)) {
1699 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1702 if (explicit_size && real_size) {
1703 class->instance_size = MAX (real_size, class->instance_size);
1706 if (class->exception_type)
1708 mono_class_layout_fields (class);
1710 /*valuetypes can't be neither bigger than 1Mb or empty. */
1711 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1712 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1714 mono_memory_barrier ();
1715 class->fields_inited = 1;
1719 * mono_class_setup_fields_locking:
1720 * @class: The class to initialize
1722 * Initializes the class->fields array of fields.
1723 * Aquires the loader lock.
1726 mono_class_setup_fields_locking (MonoClass *class)
1728 /* This can be checked without locks */
1729 if (class->fields_inited)
1731 mono_loader_lock ();
1732 mono_class_setup_fields (class);
1733 mono_loader_unlock ();
1737 * mono_class_has_references:
1739 * Returns whenever @klass->has_references is set, initializing it if needed.
1740 * Aquires the loader lock.
1743 mono_class_has_references (MonoClass *klass)
1745 if (klass->init_pending) {
1746 /* Be conservative */
1749 mono_class_init (klass);
1751 return klass->has_references;
1756 * mono_type_get_basic_type_from_generic:
1759 * Returns a closed type corresponding to the possibly open type
1763 mono_type_get_basic_type_from_generic (MonoType *type)
1765 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1766 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) && !type->data.generic_param->gshared_constraint)
1767 return &mono_defaults.object_class->byval_arg;
1772 * mono_class_layout_fields:
1775 * Compute the placement of fields inside an object or struct, according to
1776 * the layout rules and set the following fields in @class:
1777 * - has_references (if the class contains instance references firled or structs that contain references)
1778 * - has_static_refs (same, but for static fields)
1779 * - instance_size (size of the object in memory)
1780 * - class_size (size needed for the static fields)
1781 * - size_inited (flag set when the instance_size is set)
1783 * LOCKING: this is supposed to be called with the loader lock held.
1786 mono_class_layout_fields (MonoClass *class)
1789 const int top = class->field.count;
1790 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1791 guint32 pass, passes, real_size;
1792 gboolean gc_aware_layout = FALSE;
1793 gboolean has_static_fields = FALSE;
1794 MonoClassField *field;
1797 * When we do generic sharing we need to have layout
1798 * information for open generic classes (either with a generic
1799 * context containing type variables or with a generic
1800 * container), so we don't return in that case anymore.
1804 * Enable GC aware auto layout: in this mode, reference
1805 * fields are grouped together inside objects, increasing collector
1807 * Requires that all classes whose layout is known to native code be annotated
1808 * with [StructLayout (LayoutKind.Sequential)]
1809 * Value types have gc_aware_layout disabled by default, as per
1810 * what the default is for other runtimes.
1812 /* corlib is missing [StructLayout] directives in many places */
1813 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1814 if (!class->valuetype)
1815 gc_aware_layout = TRUE;
1818 /* Compute klass->has_references */
1820 * Process non-static fields first, since static fields might recursively
1821 * refer to the class itself.
1823 for (i = 0; i < top; i++) {
1826 field = &class->fields [i];
1828 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1829 ftype = mono_type_get_underlying_type (field->type);
1830 ftype = mono_type_get_basic_type_from_generic (ftype);
1831 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1832 class->has_references = TRUE;
1836 for (i = 0; i < top; i++) {
1839 field = &class->fields [i];
1841 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1842 ftype = mono_type_get_underlying_type (field->type);
1843 ftype = mono_type_get_basic_type_from_generic (ftype);
1844 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1845 class->has_static_refs = TRUE;
1849 for (i = 0; i < top; i++) {
1852 field = &class->fields [i];
1854 ftype = mono_type_get_underlying_type (field->type);
1855 ftype = mono_type_get_basic_type_from_generic (ftype);
1856 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1857 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1858 class->has_static_refs = TRUE;
1860 class->has_references = TRUE;
1865 * Compute field layout and total size (not considering static fields)
1869 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1870 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1872 if (gc_aware_layout)
1877 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1880 if (class->parent) {
1881 mono_class_setup_fields (class->parent);
1882 if (class->parent->exception_type) {
1883 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1886 real_size = class->parent->instance_size;
1888 real_size = sizeof (MonoObject);
1891 for (pass = 0; pass < passes; ++pass) {
1892 for (i = 0; i < top; i++){
1897 field = &class->fields [i];
1899 if (mono_field_is_deleted (field))
1901 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1904 ftype = mono_type_get_underlying_type (field->type);
1905 ftype = mono_type_get_basic_type_from_generic (ftype);
1906 if (gc_aware_layout) {
1907 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1916 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1917 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1918 /* This field is a hack inserted by MCS to empty structures */
1922 size = mono_type_size (field->type, &align);
1924 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1925 align = class->packing_size ? MIN (class->packing_size, align): align;
1926 /* if the field has managed references, we need to force-align it
1929 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1930 align = MAX (align, sizeof (gpointer));
1932 class->min_align = MAX (align, class->min_align);
1933 field->offset = real_size;
1935 field->offset += align - 1;
1936 field->offset &= ~(align - 1);
1938 /*TypeBuilders produce all sort of weird things*/
1939 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1940 real_size = field->offset + size;
1943 class->instance_size = MAX (real_size, class->instance_size);
1945 if (class->instance_size & (class->min_align - 1)) {
1946 class->instance_size += class->min_align - 1;
1947 class->instance_size &= ~(class->min_align - 1);
1951 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1955 for (i = 0; i < top; i++) {
1960 field = &class->fields [i];
1963 * There must be info about all the fields in a type if it
1964 * uses explicit layout.
1966 if (mono_field_is_deleted (field))
1968 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1971 size = mono_type_size (field->type, &align);
1972 align = class->packing_size ? MIN (class->packing_size, align): align;
1973 class->min_align = MAX (align, class->min_align);
1976 * When we get here, field->offset is already set by the
1977 * loader (for either runtime fields or fields loaded from metadata).
1978 * The offset is from the start of the object: this works for both
1979 * classes and valuetypes.
1981 field->offset += sizeof (MonoObject);
1982 ftype = mono_type_get_underlying_type (field->type);
1983 ftype = mono_type_get_basic_type_from_generic (ftype);
1984 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1985 if (field->offset % sizeof (gpointer)) {
1986 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1993 real_size = MAX (real_size, size + field->offset);
1996 if (class->has_references) {
1997 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1999 /* Check for overlapping reference and non-reference fields */
2000 for (i = 0; i < top; i++) {
2003 field = &class->fields [i];
2005 if (mono_field_is_deleted (field))
2007 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2009 ftype = mono_type_get_underlying_type (field->type);
2010 if (MONO_TYPE_IS_REFERENCE (ftype))
2011 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2013 for (i = 0; i < top; i++) {
2014 field = &class->fields [i];
2016 if (mono_field_is_deleted (field))
2018 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2021 // FIXME: Too much code does this
2023 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2024 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);
2025 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2029 g_free (ref_bitmap);
2032 class->instance_size = MAX (real_size, class->instance_size);
2033 if (class->instance_size & (class->min_align - 1)) {
2034 class->instance_size += class->min_align - 1;
2035 class->instance_size &= ~(class->min_align - 1);
2041 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2043 * For small structs, set min_align to at least the struct size to improve
2044 * performance, and since the JIT memset/memcpy code assumes this and generates
2045 * unaligned accesses otherwise. See #78990 for a testcase.
2047 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2048 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2051 mono_memory_barrier ();
2052 class->size_inited = 1;
2055 * Compute static field layout and size
2057 for (i = 0; i < top; i++){
2061 field = &class->fields [i];
2063 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2065 if (mono_field_is_deleted (field))
2068 if (mono_type_has_exceptions (field->type)) {
2069 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2073 has_static_fields = TRUE;
2075 size = mono_type_size (field->type, &align);
2076 field->offset = class->sizes.class_size;
2077 /*align is always non-zero here*/
2078 field->offset += align - 1;
2079 field->offset &= ~(align - 1);
2080 class->sizes.class_size = field->offset + size;
2083 if (has_static_fields && class->sizes.class_size == 0)
2084 /* Simplify code which depends on class_size != 0 if the class has static fields */
2085 class->sizes.class_size = 8;
2089 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2093 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2094 method->klass = class;
2095 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2096 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2097 method->signature = sig;
2098 method->name = name;
2101 if (name [0] == '.') {
2102 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2104 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2110 * mono_class_setup_methods:
2113 * Initializes the 'methods' array in CLASS.
2114 * Calling this method should be avoided if possible since it allocates a lot
2115 * of long-living MonoMethod structures.
2116 * Methods belonging to an interface are assigned a sequential slot starting
2119 * On failure this function sets class->exception_type
2122 mono_class_setup_methods (MonoClass *class)
2125 MonoMethod **methods;
2130 if (class->generic_class) {
2132 MonoClass *gklass = class->generic_class->container_class;
2134 mono_class_init (gklass);
2135 if (!gklass->exception_type)
2136 mono_class_setup_methods (gklass);
2137 if (gklass->exception_type) {
2138 /* FIXME make exception_data less opaque so it's possible to dup it here */
2139 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2143 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2144 count = gklass->method.count;
2145 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2147 for (i = 0; i < count; i++) {
2148 methods [i] = mono_class_inflate_generic_method_full_checked (
2149 gklass->methods [i], class, mono_class_get_context (class), &error);
2150 if (!mono_error_ok (&error)) {
2151 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2152 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)));
2155 mono_error_cleanup (&error);
2159 } else if (class->rank) {
2161 MonoMethod *amethod;
2162 MonoMethodSignature *sig;
2163 int count_generic = 0, first_generic = 0;
2165 gboolean jagged_ctor = FALSE;
2167 count = 3 + (class->rank > 1? 2: 1);
2169 mono_class_setup_interfaces (class, &error);
2170 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2172 if (class->rank == 1 && class->element_class->rank) {
2174 class->method.count ++;
2177 if (class->interface_count) {
2178 count_generic = generic_array_methods (class);
2179 first_generic = count;
2180 count += class->interface_count * count_generic;
2183 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2185 sig = mono_metadata_signature_alloc (class->image, class->rank);
2186 sig->ret = &mono_defaults.void_class->byval_arg;
2187 sig->pinvoke = TRUE;
2188 sig->hasthis = TRUE;
2189 for (i = 0; i < class->rank; ++i)
2190 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2192 amethod = create_array_method (class, ".ctor", sig);
2193 methods [method_num++] = amethod;
2194 if (class->rank > 1) {
2195 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2196 sig->ret = &mono_defaults.void_class->byval_arg;
2197 sig->pinvoke = TRUE;
2198 sig->hasthis = TRUE;
2199 for (i = 0; i < class->rank * 2; ++i)
2200 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2202 amethod = create_array_method (class, ".ctor", sig);
2203 methods [method_num++] = amethod;
2207 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2208 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2209 sig->ret = &mono_defaults.void_class->byval_arg;
2210 sig->pinvoke = TRUE;
2211 sig->hasthis = TRUE;
2212 for (i = 0; i < class->rank + 1; ++i)
2213 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2214 amethod = create_array_method (class, ".ctor", sig);
2215 methods [method_num++] = amethod;
2218 /* element Get (idx11, [idx2, ...]) */
2219 sig = mono_metadata_signature_alloc (class->image, class->rank);
2220 sig->ret = &class->element_class->byval_arg;
2221 sig->pinvoke = TRUE;
2222 sig->hasthis = TRUE;
2223 for (i = 0; i < class->rank; ++i)
2224 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2225 amethod = create_array_method (class, "Get", sig);
2226 methods [method_num++] = amethod;
2227 /* element& Address (idx11, [idx2, ...]) */
2228 sig = mono_metadata_signature_alloc (class->image, class->rank);
2229 sig->ret = &class->element_class->this_arg;
2230 sig->pinvoke = TRUE;
2231 sig->hasthis = TRUE;
2232 for (i = 0; i < class->rank; ++i)
2233 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2234 amethod = create_array_method (class, "Address", sig);
2235 methods [method_num++] = amethod;
2236 /* void Set (idx11, [idx2, ...], element) */
2237 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2238 sig->ret = &mono_defaults.void_class->byval_arg;
2239 sig->pinvoke = TRUE;
2240 sig->hasthis = TRUE;
2241 for (i = 0; i < class->rank; ++i)
2242 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2243 sig->params [i] = &class->element_class->byval_arg;
2244 amethod = create_array_method (class, "Set", sig);
2245 methods [method_num++] = amethod;
2247 for (i = 0; i < class->interface_count; i++)
2248 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2252 count = class->method.count;
2253 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2254 for (i = 0; i < count; ++i) {
2255 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2256 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2258 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)));
2259 mono_error_cleanup (&error);
2264 if (MONO_CLASS_IS_INTERFACE (class)) {
2266 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2267 for (i = 0; i < count; ++i) {
2268 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2269 methods [i]->slot = slot++;
2273 mono_image_lock (class->image);
2275 if (!class->methods) {
2276 class->method.count = count;
2278 /* Needed because of the double-checking locking pattern */
2279 mono_memory_barrier ();
2281 class->methods = methods;
2284 mono_image_unlock (class->image);
2288 * mono_class_get_method_by_index:
2290 * Returns class->methods [index], initializing class->methods if neccesary.
2292 * LOCKING: Acquires the loader lock.
2295 mono_class_get_method_by_index (MonoClass *class, int index)
2298 /* Avoid calling setup_methods () if possible */
2299 if (class->generic_class && !class->methods) {
2300 MonoClass *gklass = class->generic_class->container_class;
2303 m = mono_class_inflate_generic_method_full_checked (
2304 gklass->methods [index], class, mono_class_get_context (class), &error);
2305 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2307 * If setup_methods () is called later for this class, no duplicates are created,
2308 * since inflate_generic_method guarantees that only one instance of a method
2309 * is created for each context.
2312 mono_class_setup_methods (class);
2313 g_assert (m == class->methods [index]);
2317 mono_class_setup_methods (class);
2318 if (class->exception_type) /*FIXME do proper error handling*/
2320 g_assert (index >= 0 && index < class->method.count);
2321 return class->methods [index];
2326 * mono_class_get_inflated_method:
2328 * Given an inflated class CLASS and a method METHOD which should be a method of
2329 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2332 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2334 MonoClass *gklass = class->generic_class->container_class;
2337 g_assert (method->klass == gklass);
2339 mono_class_setup_methods (gklass);
2340 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2342 for (i = 0; i < gklass->method.count; ++i) {
2343 if (gklass->methods [i] == method) {
2344 if (class->methods) {
2345 return class->methods [i];
2348 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2349 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2359 * mono_class_get_vtable_entry:
2361 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2362 * LOCKING: Acquires the loader lock.
2365 mono_class_get_vtable_entry (MonoClass *class, int offset)
2369 if (class->rank == 1) {
2371 * szarrays do not overwrite any methods of Array, so we can avoid
2372 * initializing their vtables in some cases.
2374 mono_class_setup_vtable (class->parent);
2375 if (offset < class->parent->vtable_size)
2376 return class->parent->vtable [offset];
2379 if (class->generic_class) {
2381 MonoClass *gklass = class->generic_class->container_class;
2382 mono_class_setup_vtable (gklass);
2383 m = gklass->vtable [offset];
2385 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2386 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2388 mono_class_setup_vtable (class);
2389 if (class->exception_type)
2391 m = class->vtable [offset];
2398 * mono_class_get_vtable_size:
2400 * Return the vtable size for KLASS.
2403 mono_class_get_vtable_size (MonoClass *klass)
2405 mono_class_setup_vtable (klass);
2407 return klass->vtable_size;
2411 * mono_class_setup_properties:
2413 * Initialize class->ext.property and class->ext.properties.
2415 * This method can fail the class.
2418 mono_class_setup_properties (MonoClass *class)
2420 guint startm, endm, i, j;
2421 guint32 cols [MONO_PROPERTY_SIZE];
2422 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2423 MonoProperty *properties;
2427 if (class->ext && class->ext->properties)
2430 if (class->generic_class) {
2431 MonoClass *gklass = class->generic_class->container_class;
2433 mono_class_init (gklass);
2434 mono_class_setup_properties (gklass);
2435 if (gklass->exception_type) {
2436 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2440 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2442 for (i = 0; i < gklass->ext->property.count; i++) {
2444 MonoProperty *prop = &properties [i];
2446 *prop = gklass->ext->properties [i];
2449 prop->get = mono_class_inflate_generic_method_full_checked (
2450 prop->get, class, mono_class_get_context (class), &error);
2452 prop->set = mono_class_inflate_generic_method_full_checked (
2453 prop->set, class, mono_class_get_context (class), &error);
2455 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2456 prop->parent = class;
2459 first = gklass->ext->property.first;
2460 count = gklass->ext->property.count;
2462 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2463 count = last - first;
2466 mono_class_setup_methods (class);
2467 if (class->exception_type)
2471 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2472 for (i = first; i < last; ++i) {
2473 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2474 properties [i - first].parent = class;
2475 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2476 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2478 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2479 for (j = startm; j < endm; ++j) {
2482 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2484 if (class->image->uncompressed_metadata) {
2486 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2487 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2488 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2490 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2493 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2494 case METHOD_SEMANTIC_SETTER:
2495 properties [i - first].set = method;
2497 case METHOD_SEMANTIC_GETTER:
2498 properties [i - first].get = method;
2507 mono_class_alloc_ext (class);
2509 mono_image_lock (class->image);
2511 if (class->ext->properties) {
2512 /* We leak 'properties' which was allocated from the image mempool */
2513 mono_image_unlock (class->image);
2517 class->ext->property.first = first;
2518 class->ext->property.count = count;
2520 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2521 mono_memory_barrier ();
2523 /* Leave this assignment as the last op in the function */
2524 class->ext->properties = properties;
2526 mono_image_unlock (class->image);
2530 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2532 MonoMethod **om, **retval;
2535 for (om = methods, count = 0; *om; ++om, ++count)
2538 retval = g_new0 (MonoMethod*, count + 1);
2540 for (om = methods, count = 0; *om; ++om, ++count) {
2542 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2543 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2549 /*This method can fail the class.*/
2551 mono_class_setup_events (MonoClass *class)
2554 guint startm, endm, i, j;
2555 guint32 cols [MONO_EVENT_SIZE];
2556 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2560 if (class->ext && class->ext->events)
2563 if (class->generic_class) {
2564 MonoClass *gklass = class->generic_class->container_class;
2565 MonoGenericContext *context = NULL;
2567 mono_class_setup_events (gklass);
2568 if (gklass->exception_type) {
2569 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2573 first = gklass->ext->event.first;
2574 count = gklass->ext->event.count;
2576 events = mono_class_new0 (class, MonoEvent, count);
2579 context = mono_class_get_context (class);
2581 for (i = 0; i < count; i++) {
2583 MonoEvent *event = &events [i];
2584 MonoEvent *gevent = &gklass->ext->events [i];
2586 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2588 event->parent = class;
2589 event->name = gevent->name;
2590 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2591 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2592 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2593 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2594 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2595 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2597 #ifndef MONO_SMALL_CONFIG
2598 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2600 event->attrs = gevent->attrs;
2603 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2604 count = last - first;
2607 mono_class_setup_methods (class);
2608 if (class->exception_type) {
2609 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2614 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2615 for (i = first; i < last; ++i) {
2616 MonoEvent *event = &events [i - first];
2618 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2619 event->parent = class;
2620 event->attrs = cols [MONO_EVENT_FLAGS];
2621 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2623 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2624 for (j = startm; j < endm; ++j) {
2627 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2629 if (class->image->uncompressed_metadata) {
2631 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2632 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2633 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2635 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2638 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2639 case METHOD_SEMANTIC_ADD_ON:
2640 event->add = method;
2642 case METHOD_SEMANTIC_REMOVE_ON:
2643 event->remove = method;
2645 case METHOD_SEMANTIC_FIRE:
2646 event->raise = method;
2648 case METHOD_SEMANTIC_OTHER: {
2649 #ifndef MONO_SMALL_CONFIG
2652 if (event->other == NULL) {
2653 event->other = g_new0 (MonoMethod*, 2);
2655 while (event->other [n])
2657 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2659 event->other [n] = method;
2660 /* NULL terminated */
2661 event->other [n + 1] = NULL;
2672 mono_class_alloc_ext (class);
2674 mono_image_lock (class->image);
2676 if (class->ext->events) {
2677 mono_image_unlock (class->image);
2681 class->ext->event.first = first;
2682 class->ext->event.count = count;
2684 /* Flush any pending writes as we do double checked locking on class->ext.events */
2685 mono_memory_barrier ();
2687 /* Leave this assignment as the last op in the function */
2688 class->ext->events = events;
2690 mono_image_unlock (class->image);
2694 * Global pool of interface IDs, represented as a bitset.
2695 * LOCKING: Protected by the classes lock.
2697 static MonoBitSet *global_interface_bitset = NULL;
2700 * mono_unload_interface_ids:
2701 * @bitset: bit set of interface IDs
2703 * When an image is unloaded, the interface IDs associated with
2704 * the image are put back in the global pool of IDs so the numbers
2708 mono_unload_interface_ids (MonoBitSet *bitset)
2711 mono_bitset_sub (global_interface_bitset, bitset);
2716 mono_unload_interface_id (MonoClass *class)
2718 if (global_interface_bitset && class->interface_id) {
2720 mono_bitset_clear (global_interface_bitset, class->interface_id);
2726 * mono_get_unique_iid:
2729 * Assign a unique integer ID to the interface represented by @class.
2730 * The ID will positive and as small as possible.
2731 * LOCKING: Acquires the classes lock.
2732 * Returns: the new ID.
2735 mono_get_unique_iid (MonoClass *class)
2739 g_assert (MONO_CLASS_IS_INTERFACE (class));
2743 if (!global_interface_bitset) {
2744 global_interface_bitset = mono_bitset_new (128, 0);
2747 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2749 int old_size = mono_bitset_size (global_interface_bitset);
2750 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2751 mono_bitset_free (global_interface_bitset);
2752 global_interface_bitset = new_set;
2755 mono_bitset_set (global_interface_bitset, iid);
2756 /* set the bit also in the per-image set */
2757 if (!class->generic_class) {
2758 if (class->image->interface_bitset) {
2759 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2760 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2761 mono_bitset_free (class->image->interface_bitset);
2762 class->image->interface_bitset = new_set;
2765 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2767 mono_bitset_set (class->image->interface_bitset, iid);
2772 #ifndef MONO_SMALL_CONFIG
2773 if (mono_print_vtable) {
2775 char *type_name = mono_type_full_name (&class->byval_arg);
2776 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2777 generic_id = class->generic_class->context.class_inst->id;
2778 g_assert (generic_id != 0);
2782 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2787 g_assert (iid <= 65535);
2792 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2797 mono_class_setup_interfaces (klass, error);
2798 if (!mono_error_ok (error))
2801 for (i = 0; i < klass->interface_count; i++) {
2802 ic = klass->interfaces [i];
2805 *res = g_ptr_array_new ();
2806 g_ptr_array_add (*res, ic);
2807 mono_class_init (ic);
2808 if (ic->exception_type) {
2809 mono_error_set_type_load_class (error, ic, "Error Loading class");
2813 collect_implemented_interfaces_aux (ic, res, error);
2814 if (!mono_error_ok (error))
2820 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2822 GPtrArray *res = NULL;
2824 collect_implemented_interfaces_aux (klass, &res, error);
2825 if (!mono_error_ok (error)) {
2827 g_ptr_array_free (res, TRUE);
2834 compare_interface_ids (const void *p_key, const void *p_element) {
2835 const MonoClass *key = p_key;
2836 const MonoClass *element = *(MonoClass**) p_element;
2838 return (key->interface_id - element->interface_id);
2841 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2843 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2844 MonoClass **result = mono_binary_search (
2846 klass->interfaces_packed,
2847 klass->interface_offsets_count,
2848 sizeof (MonoClass *),
2849 compare_interface_ids);
2851 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2858 * mono_class_interface_offset_with_variance:
2860 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2861 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2863 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2865 * FIXME figure out MS disambiguation rules and fix this function.
2868 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2869 int i = mono_class_interface_offset (klass, itf);
2870 *non_exact_match = FALSE;
2874 if (!mono_class_has_variant_generic_params (itf))
2877 for (i = 0; i < klass->interface_offsets_count; i++) {
2878 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2879 *non_exact_match = TRUE;
2880 return klass->interface_offsets_packed [i];
2888 print_implemented_interfaces (MonoClass *klass) {
2891 GPtrArray *ifaces = NULL;
2893 int ancestor_level = 0;
2895 name = mono_type_get_full_name (klass);
2896 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2899 for (i = 0; i < klass->interface_offsets_count; i++)
2900 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2901 klass->interfaces_packed [i]->interface_id,
2902 klass->interface_offsets_packed [i],
2903 klass->interfaces_packed [i]->method.count,
2904 klass->interfaces_packed [i]->name_space,
2905 klass->interfaces_packed [i]->name );
2906 printf ("Interface flags: ");
2907 for (i = 0; i <= klass->max_interface_id; i++)
2908 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2909 printf ("(%d,T)", i);
2911 printf ("(%d,F)", i);
2913 printf ("Dump interface flags:");
2914 #ifdef COMPRESSED_INTERFACE_BITMAP
2916 const uint8_t* p = klass->interface_bitmap;
2917 i = klass->max_interface_id;
2919 printf (" %d x 00 %02X", p [0], p [1]);
2925 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2926 printf (" %02X", klass->interface_bitmap [i]);
2929 while (klass != NULL) {
2930 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2931 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2932 if (!mono_error_ok (&error)) {
2933 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2934 mono_error_cleanup (&error);
2935 } else if (ifaces) {
2936 for (i = 0; i < ifaces->len; i++) {
2937 MonoClass *ic = g_ptr_array_index (ifaces, i);
2938 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2939 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2941 mono_class_interface_offset (klass, ic),
2946 g_ptr_array_free (ifaces, TRUE);
2949 klass = klass->parent;
2954 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2957 args [0] = &arg0->byval_arg;
2959 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2963 array_class_get_if_rank (MonoClass *class, guint rank)
2965 return rank ? mono_array_class_get (class, rank) : class;
2969 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2971 valuetype_types [0] = eclass;
2972 if (eclass == mono_defaults.int16_class)
2973 valuetype_types [1] = mono_defaults.uint16_class;
2974 else if (eclass == mono_defaults.uint16_class)
2975 valuetype_types [1] = mono_defaults.int16_class;
2976 else if (eclass == mono_defaults.int32_class)
2977 valuetype_types [1] = mono_defaults.uint32_class;
2978 else if (eclass == mono_defaults.uint32_class)
2979 valuetype_types [1] = mono_defaults.int32_class;
2980 else if (eclass == mono_defaults.int64_class)
2981 valuetype_types [1] = mono_defaults.uint64_class;
2982 else if (eclass == mono_defaults.uint64_class)
2983 valuetype_types [1] = mono_defaults.int64_class;
2984 else if (eclass == mono_defaults.byte_class)
2985 valuetype_types [1] = mono_defaults.sbyte_class;
2986 else if (eclass == mono_defaults.sbyte_class)
2987 valuetype_types [1] = mono_defaults.byte_class;
2988 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2989 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2992 /* this won't be needed once bug #325495 is completely fixed
2993 * though we'll need something similar to know which interfaces to allow
2994 * in arrays when they'll be lazyly created
2996 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2997 * MS returns diferrent types based on which instance is called. For example:
2998 * object obj = new byte[10][];
2999 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3000 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3003 * Fixing this should kill quite some code, save some bits and improve compatibility.
3006 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3008 MonoClass *eclass = class->element_class;
3009 static MonoClass* generic_icollection_class = NULL;
3010 static MonoClass* generic_ienumerable_class = NULL;
3011 static MonoClass* generic_ienumerator_class = NULL;
3012 static MonoClass* generic_ireadonlylist_class = NULL;
3013 static MonoClass* generic_ireadonlycollection_class = NULL;
3014 MonoClass *valuetype_types[2] = { NULL, NULL };
3015 MonoClass **interfaces = NULL;
3016 int i, nifaces, interface_count, real_count, original_rank;
3018 gboolean internal_enumerator;
3019 gboolean eclass_is_valuetype;
3021 if (!mono_defaults.generic_ilist_class) {
3025 internal_enumerator = FALSE;
3026 eclass_is_valuetype = FALSE;
3027 original_rank = eclass->rank;
3028 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3029 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3031 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3033 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3034 original_rank = eclass->rank;
3036 eclass = eclass->element_class;
3037 internal_enumerator = TRUE;
3038 *is_enumerator = TRUE;
3046 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3047 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3049 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3051 if (!generic_icollection_class) {
3052 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3053 "System.Collections.Generic", "ICollection`1");
3054 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3055 "System.Collections.Generic", "IEnumerable`1");
3056 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3057 "System.Collections.Generic", "IEnumerator`1");
3058 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3059 "System.Collections.Generic", "IReadOnlyList`1");
3060 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3061 "System.Collections.Generic", "IReadOnlyCollection`1");
3064 mono_class_init (eclass);
3067 * Arrays in 2.0 need to implement a number of generic interfaces
3068 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3069 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3070 * We collect the types needed to build the
3071 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3072 * the generic interfaces needed to implement.
3074 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3075 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3077 if (eclass->valuetype) {
3078 nifaces = generic_ireadonlylist_class ? 5 : 3;
3079 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3081 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3082 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3083 if (internal_enumerator) {
3085 if (valuetype_types [1])
3089 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3090 interfaces [0] = valuetype_types [0];
3091 if (valuetype_types [1])
3092 interfaces [nifaces] = valuetype_types [1];
3094 eclass_is_valuetype = TRUE;
3097 int idepth = eclass->idepth;
3098 if (!internal_enumerator)
3100 nifaces = generic_ireadonlylist_class ? 2 : 3;
3102 // FIXME: This doesn't seem to work/required for generic params
3103 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3104 mono_class_setup_interface_offsets (eclass);
3106 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3107 /* we add object for interfaces and the supertypes for the other
3108 * types. The last of the supertypes is the element class itself which we
3109 * already created the explicit interfaces for (so we include it for IEnumerator
3110 * and exclude it for arrays).
3112 if (MONO_CLASS_IS_INTERFACE (eclass))
3115 interface_count += idepth;
3116 if (eclass->rank && eclass->element_class->valuetype) {
3117 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3118 if (valuetype_types [1])
3121 /* IList, ICollection, IEnumerable, IReadOnlyList */
3122 interface_count *= nifaces;
3123 real_count = interface_count;
3124 if (internal_enumerator) {
3125 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3126 if (valuetype_types [1])
3129 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3130 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3131 interfaces [0] = mono_defaults.object_class;
3135 for (i = 0; i < idepth; i++) {
3136 mono_class_init (eclass->supertypes [i]);
3137 interfaces [j] = eclass->supertypes [i];
3141 if (all_interfaces) {
3142 for (i = 0; i < eclass->interface_offsets_count; i++) {
3143 interfaces [j] = eclass->interfaces_packed [i];
3147 for (i = 0; i < eclass->interface_count; i++) {
3148 interfaces [j] = eclass->interfaces [i];
3152 if (valuetype_types [1]) {
3153 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3158 /* instantiate the generic interfaces */
3159 for (i = 0; i < interface_count; i += nifaces) {
3160 MonoClass *iface = interfaces [i];
3162 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3163 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3165 if (eclass->valuetype) {
3166 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3167 if (generic_ireadonlylist_class) {
3168 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3169 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3172 if (!generic_ireadonlylist_class)
3173 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3176 if (internal_enumerator) {
3178 /* instantiate IEnumerator<iface> */
3179 for (i = 0; i < interface_count; i++) {
3180 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3182 j = interface_count;
3183 if (!eclass_is_valuetype) {
3184 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3185 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3188 for (i = 0; i < eclass->idepth; i++) {
3189 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3193 for (i = 0; i < eclass->interface_offsets_count; i++) {
3194 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3198 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3200 if (valuetype_types [1])
3201 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3205 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3206 for (i = 0; i < real_count; ++i) {
3207 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3208 g_print ("%s implements %s\n", type_name, name);
3219 find_array_interface (MonoClass *klass, const char *name)
3222 for (i = 0; i < klass->interface_count; ++i) {
3223 if (strcmp (klass->interfaces [i]->name, name) == 0)
3230 * Return the number of virtual methods.
3231 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3232 * Return -1 on failure.
3233 * FIXME It would be nice if this information could be cached somewhere.
3236 count_virtual_methods (MonoClass *class)
3240 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3242 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3243 mono_class_setup_methods (class);
3244 if (class->exception_type)
3247 for (i = 0; i < class->method.count; ++i) {
3248 flags = class->methods [i]->flags;
3249 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3253 for (i = 0; i < class->method.count; ++i) {
3254 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3256 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3264 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3272 m = (l + num_ifaces) / 2;
3273 if (interfaces_full [m] == ic)
3275 if (l == num_ifaces)
3277 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3286 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3288 int i = find_interface (num_ifaces, interfaces_full, ic);
3290 return interface_offsets_full [i];
3295 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3297 int i = find_interface (num_ifaces, interfaces_full, ic);
3301 interface_offsets_full [i] = offset;
3304 for (i = 0; i < num_ifaces; ++i) {
3305 if (interfaces_full [i]) {
3307 if (interfaces_full [i]->interface_id < ic->interface_id)
3310 while (end < num_ifaces && interfaces_full [end]) end++;
3311 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3312 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3314 interfaces_full [i] = ic;
3315 interface_offsets_full [i] = offset;
3321 #ifdef COMPRESSED_INTERFACE_BITMAP
3324 * Compressed interface bitmap design.
3326 * Interface bitmaps take a large amount of memory, because their size is
3327 * linear with the maximum interface id assigned in the process (each interface
3328 * is assigned a unique id as it is loaded). The number of interface classes
3329 * is high because of the many implicit interfaces implemented by arrays (we'll
3330 * need to lazy-load them in the future).
3331 * Most classes implement a very small number of interfaces, so the bitmap is
3332 * sparse. This bitmap needs to be checked by interface casts, so access to the
3333 * needed bit must be fast and doable with few jit instructions.
3335 * The current compression format is as follows:
3336 * *) it is a sequence of one or more two-byte elements
3337 * *) the first byte in the element is the count of empty bitmap bytes
3338 * at the current bitmap position
3339 * *) the second byte in the element is an actual bitmap byte at the current
3342 * As an example, the following compressed bitmap bytes:
3343 * 0x07 0x01 0x00 0x7
3344 * correspond to the following bitmap:
3345 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3347 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3348 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3349 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3353 * mono_compress_bitmap:
3354 * @dest: destination buffer
3355 * @bitmap: bitmap buffer
3356 * @size: size of @bitmap in bytes
3358 * This is a mono internal function.
3359 * The @bitmap data is compressed into a format that is small but
3360 * still searchable in few instructions by the JIT and runtime.
3361 * The compressed data is stored in the buffer pointed to by the
3362 * @dest array. Passing a #NULL value for @dest allows to just compute
3363 * the size of the buffer.
3364 * This compression algorithm assumes the bits set in the bitmap are
3365 * few and far between, like in interface bitmaps.
3366 * Returns: the size of the compressed bitmap in bytes.
3369 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3373 const uint8_t *end = bitmap + size;
3374 while (bitmap < end) {
3375 if (*bitmap || numz == 255) {
3399 * mono_class_interface_match:
3400 * @bitmap: a compressed bitmap buffer
3401 * @id: the index to check in the bitmap
3403 * This is a mono internal function.
3404 * Checks if a bit is set in a compressed interface bitmap. @id must
3405 * be already checked for being smaller than the maximum id encoded in the
3408 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3412 mono_class_interface_match (const uint8_t *bitmap, int id)
3415 id -= bitmap [0] * 8;
3419 return bitmap [1] & (1 << id);
3428 * LOCKING: this is supposed to be called with the loader lock held.
3429 * Return -1 on failure and set exception_type
3432 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3436 int i, j, max_iid, num_ifaces;
3437 MonoClass **interfaces_full = NULL;
3438 int *interface_offsets_full = NULL;
3440 GPtrArray **ifaces_array = NULL;
3441 int interface_offsets_count;
3442 MonoClass **array_interfaces = NULL;
3443 int num_array_interfaces;
3444 int is_enumerator = FALSE;
3446 mono_class_setup_supertypes (class);
3448 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3449 * implicit interfaces have the property that they are assigned the same slot in the
3450 * vtables for compatible interfaces
3452 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3454 /* compute maximum number of slots and maximum interface id */
3456 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3457 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3458 for (j = 0; j < class->idepth; j++) {
3459 k = class->supertypes [j];
3460 num_ifaces += k->interface_count;
3461 for (i = 0; i < k->interface_count; i++) {
3462 ic = k->interfaces [i];
3465 mono_class_init (ic);
3467 if (max_iid < ic->interface_id)
3468 max_iid = ic->interface_id;
3470 ifaces = mono_class_get_implemented_interfaces (k, &error);
3471 if (!mono_error_ok (&error)) {
3472 char *name = mono_type_get_full_name (k);
3473 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)));
3475 mono_error_cleanup (&error);
3480 num_ifaces += ifaces->len;
3481 for (i = 0; i < ifaces->len; ++i) {
3482 ic = g_ptr_array_index (ifaces, i);
3483 if (max_iid < ic->interface_id)
3484 max_iid = ic->interface_id;
3486 ifaces_array [j] = ifaces;
3490 for (i = 0; i < num_array_interfaces; ++i) {
3491 ic = array_interfaces [i];
3492 mono_class_init (ic);
3493 if (max_iid < ic->interface_id)
3494 max_iid = ic->interface_id;
3497 if (MONO_CLASS_IS_INTERFACE (class)) {
3499 if (max_iid < class->interface_id)
3500 max_iid = class->interface_id;
3502 class->max_interface_id = max_iid;
3503 /* compute vtable offset for interfaces */
3504 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3505 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3507 for (i = 0; i < num_ifaces; i++) {
3508 interface_offsets_full [i] = -1;
3511 /* skip the current class */
3512 for (j = 0; j < class->idepth - 1; j++) {
3513 k = class->supertypes [j];
3514 ifaces = ifaces_array [j];
3517 for (i = 0; i < ifaces->len; ++i) {
3519 ic = g_ptr_array_index (ifaces, i);
3521 /*Force the sharing of interface offsets between parent and subtypes.*/
3522 io = mono_class_interface_offset (k, ic);
3524 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3529 g_assert (class == class->supertypes [class->idepth - 1]);
3530 ifaces = ifaces_array [class->idepth - 1];
3532 for (i = 0; i < ifaces->len; ++i) {
3534 ic = g_ptr_array_index (ifaces, i);
3535 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3537 count = count_virtual_methods (ic);
3539 char *name = mono_type_get_full_name (ic);
3540 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3549 if (MONO_CLASS_IS_INTERFACE (class))
3550 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3552 if (num_array_interfaces) {
3553 if (is_enumerator) {
3554 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3555 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3556 g_assert (ienumerator_offset >= 0);
3557 for (i = 0; i < num_array_interfaces; ++i) {
3558 ic = array_interfaces [i];
3559 if (strcmp (ic->name, "IEnumerator`1") == 0)
3560 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3562 g_assert_not_reached ();
3563 /*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);*/
3566 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3567 int ilist_iface_idx = find_array_interface (class, "IList`1");
3568 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3569 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3570 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3571 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3572 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3573 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3574 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3575 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3576 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3577 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3578 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3579 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3580 for (i = 0; i < num_array_interfaces; ++i) {
3582 ic = array_interfaces [i];
3583 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3584 offset = ilist_offset;
3585 else if (strcmp (ic->name, "ICollection`1") == 0)
3586 offset = icollection_offset;
3587 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3588 offset = ienumerable_offset;
3589 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3590 offset = ireadonlylist_offset;
3591 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3592 offset = ireadonlycollection_offset;
3594 g_assert_not_reached ();
3595 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3596 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3601 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3602 if (interface_offsets_full [i] != -1) {
3603 interface_offsets_count ++;
3608 * We might get called multiple times:
3609 * - mono_class_init ()
3610 * - mono_class_setup_vtable ().
3611 * - mono_class_setup_interface_offsets ().
3612 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3613 * means we have to overwrite those when called from other places (#4440).
3615 if (class->interfaces_packed && !overwrite) {
3616 g_assert (class->interface_offsets_count == interface_offsets_count);
3620 class->interface_offsets_count = interface_offsets_count;
3621 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3622 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3623 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3624 #ifdef COMPRESSED_INTERFACE_BITMAP
3625 bitmap = g_malloc0 (bsize);
3627 bitmap = mono_class_alloc0 (class, bsize);
3629 for (i = 0; i < interface_offsets_count; i++) {
3630 int id = interfaces_full [i]->interface_id;
3631 bitmap [id >> 3] |= (1 << (id & 7));
3632 class->interfaces_packed [i] = interfaces_full [i];
3633 class->interface_offsets_packed [i] = interface_offsets_full [i];
3634 /*if (num_array_interfaces)
3635 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]);*/
3637 #ifdef COMPRESSED_INTERFACE_BITMAP
3638 i = mono_compress_bitmap (NULL, bitmap, bsize);
3639 class->interface_bitmap = mono_class_alloc0 (class, i);
3640 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3643 class->interface_bitmap = bitmap;
3648 g_free (interfaces_full);
3649 g_free (interface_offsets_full);
3650 g_free (array_interfaces);
3651 for (i = 0; i < class->idepth; i++) {
3652 ifaces = ifaces_array [i];
3654 g_ptr_array_free (ifaces, TRUE);
3656 g_free (ifaces_array);
3658 //printf ("JUST DONE: ");
3659 //print_implemented_interfaces (class);
3665 * Setup interface offsets for interfaces.
3667 * - class->max_interface_id
3668 * - class->interface_offsets_count
3669 * - class->interfaces_packed
3670 * - class->interface_offsets_packed
3671 * - class->interface_bitmap
3673 * This function can fail @class.
3676 mono_class_setup_interface_offsets (MonoClass *class)
3678 mono_loader_lock ();
3680 setup_interface_offsets (class, 0, FALSE);
3682 mono_loader_unlock ();
3685 /*Checks if @klass has @parent as one of it's parents type gtd
3689 * Bar<T> : Foo<Bar<Bar<T>>>
3693 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3695 klass = mono_class_get_generic_type_definition (klass);
3696 parent = mono_class_get_generic_type_definition (parent);
3697 mono_class_setup_supertypes (klass);
3698 mono_class_setup_supertypes (parent);
3700 return klass->idepth >= parent->idepth &&
3701 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3705 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3707 MonoGenericInst *ginst;
3709 if (!class->generic_class) {
3710 mono_class_setup_vtable_full (class, in_setup);
3711 return class->exception_type == 0;
3714 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3715 if (class->generic_class->container_class->exception_type) {
3716 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3720 ginst = class->generic_class->context.class_inst;
3721 for (i = 0; i < ginst->type_argc; ++i) {
3723 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3725 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3726 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3727 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3729 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3730 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3738 * mono_class_setup_vtable:
3740 * Creates the generic vtable of CLASS.
3741 * Initializes the following fields in MonoClass:
3744 * Plus all the fields initialized by setup_interface_offsets ().
3745 * If there is an error during vtable construction, class->exception_type is set.
3747 * LOCKING: Acquires the loader lock.
3750 mono_class_setup_vtable (MonoClass *class)
3752 mono_class_setup_vtable_full (class, NULL);
3756 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3758 MonoMethod **overrides;
3759 MonoGenericContext *context;
3767 if (MONO_CLASS_IS_INTERFACE (class)) {
3768 /* This sets method->slot for all methods if this is an interface */
3769 mono_class_setup_methods (class);
3773 if (class->exception_type)
3776 if (g_list_find (in_setup, class))
3779 mono_loader_lock ();
3781 if (class->vtable) {
3782 mono_loader_unlock ();
3786 mono_stats.generic_vtable_count ++;
3787 in_setup = g_list_prepend (in_setup, class);
3789 if (class->generic_class) {
3790 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3791 mono_loader_unlock ();
3792 g_list_remove (in_setup, class);
3796 context = mono_class_get_context (class);
3797 type_token = class->generic_class->container_class->type_token;
3799 context = (MonoGenericContext *) class->generic_container;
3800 type_token = class->type_token;
3803 if (image_is_dynamic (class->image)) {
3804 /* Generic instances can have zero method overrides without causing any harm.
3805 * This is true since we don't do layout all over again for them, we simply inflate
3806 * the layout of the parent.
3808 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3810 /* The following call fails if there are missing methods in the type */
3811 /* FIXME it's probably a good idea to avoid this for generic instances. */
3812 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3816 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3818 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3822 mono_loader_unlock ();
3823 g_list_remove (in_setup, class);
3828 #define DEBUG_INTERFACE_VTABLE_CODE 0
3829 #define TRACE_INTERFACE_VTABLE_CODE 0
3830 #define VERIFY_INTERFACE_VTABLE_CODE 0
3831 #define VTABLE_SELECTOR (1)
3833 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3834 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3835 if (!(VTABLE_SELECTOR)) break; \
3839 #define DEBUG_INTERFACE_VTABLE(stmt)
3842 #if TRACE_INTERFACE_VTABLE_CODE
3843 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3844 if (!(VTABLE_SELECTOR)) break; \
3848 #define TRACE_INTERFACE_VTABLE(stmt)
3851 #if VERIFY_INTERFACE_VTABLE_CODE
3852 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3853 if (!(VTABLE_SELECTOR)) break; \
3857 #define VERIFY_INTERFACE_VTABLE(stmt)
3861 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3863 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3867 GString *res = g_string_new ("");
3869 g_string_append_c (res, '(');
3870 for (i = 0; i < sig->param_count; ++i) {
3872 g_string_append_c (res, ',');
3873 mono_type_get_desc (res, sig->params [i], include_namespace);
3875 g_string_append (res, ")=>");
3876 if (sig->ret != NULL) {
3877 mono_type_get_desc (res, sig->ret, include_namespace);
3879 g_string_append (res, "NULL");
3882 g_string_free (res, FALSE);
3886 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3887 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3888 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3889 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3897 is_wcf_hack_disabled (void)
3899 static gboolean disabled;
3900 static gboolean inited = FALSE;
3902 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3909 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) {
3910 MonoMethodSignature *cmsig, *imsig;
3911 if (strcmp (im->name, cm->name) == 0) {
3912 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3913 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3916 if (! slot_is_empty) {
3917 if (require_newslot) {
3918 if (! interface_is_explicitly_implemented_by_class) {
3919 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3922 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3923 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3927 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3930 cmsig = mono_method_signature (cm);
3931 imsig = mono_method_signature (im);
3932 if (!cmsig || !imsig) {
3933 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3937 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3938 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3939 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3940 TRACE_INTERFACE_VTABLE (printf ("]"));
3943 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3944 /* CAS - SecurityAction.InheritanceDemand on interface */
3945 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3946 mono_secman_inheritancedemand_method (cm, im);
3949 if (mono_security_core_clr_enabled ())
3950 mono_security_core_clr_check_override (class, cm, im);
3952 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3953 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3954 char *body_name = mono_method_full_name (cm, TRUE);
3955 char *decl_name = mono_method_full_name (im, TRUE);
3956 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));
3964 MonoClass *ic = im->klass;
3965 const char *ic_name_space = ic->name_space;
3966 const char *ic_name = ic->name;
3969 if (! require_newslot) {
3970 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3973 if (cm->klass->rank == 0) {
3974 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3977 cmsig = mono_method_signature (cm);
3978 imsig = mono_method_signature (im);
3979 if (!cmsig || !imsig) {
3980 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3984 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3985 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3986 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3987 TRACE_INTERFACE_VTABLE (printf ("]"));
3990 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3991 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3994 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3995 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3998 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))) {
3999 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4003 subname = strstr (cm->name, ic_name_space);
4004 if (subname != cm->name) {
4005 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4008 subname += strlen (ic_name_space);
4009 if (subname [0] != '.') {
4010 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4014 if (strstr (subname, ic_name) != subname) {
4015 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4018 subname += strlen (ic_name);
4019 if (subname [0] != '.') {
4020 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4024 if (strcmp (subname, im->name) != 0) {
4025 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4029 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4030 /* CAS - SecurityAction.InheritanceDemand on interface */
4031 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4032 mono_secman_inheritancedemand_method (cm, im);
4035 if (mono_security_core_clr_enabled ())
4036 mono_security_core_clr_check_override (class, cm, im);
4038 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4039 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4040 char *body_name = mono_method_full_name (cm, TRUE);
4041 char *decl_name = mono_method_full_name (im, TRUE);
4042 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));
4052 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4054 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4055 MonoMethod *method = key;
4056 MonoMethod *override = value;
4057 MonoClass *method_class = mono_method_get_class (method);
4058 MonoClass *override_class = mono_method_get_class (override);
4060 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4061 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4062 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4065 print_overrides (GHashTable *override_map, const char *message) {
4067 printf ("Override map \"%s\" START:\n", message);
4068 g_hash_table_foreach (override_map, foreach_override, NULL);
4069 printf ("Override map \"%s\" END.\n", message);
4071 printf ("Override map \"%s\" EMPTY.\n", message);
4075 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4076 char *full_name = mono_type_full_name (&class->byval_arg);
4080 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4082 if (print_interfaces) {
4083 print_implemented_interfaces (class);
4084 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4087 if (class->parent) {
4088 parent_size = class->parent->vtable_size;
4092 for (i = 0; i < size; ++i) {
4093 MonoMethod *cm = vtable [i];
4094 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4095 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4097 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4105 #if VERIFY_INTERFACE_VTABLE_CODE
4107 mono_method_try_get_vtable_index (MonoMethod *method)
4109 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4110 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4111 if (imethod->declaring->is_generic)
4112 return imethod->declaring->slot;
4114 return method->slot;
4118 mono_class_verify_vtable (MonoClass *class)
4121 char *full_name = mono_type_full_name (&class->byval_arg);
4123 printf ("*** Verifying VTable of class '%s' \n", full_name);
4127 if (!class->methods)
4130 for (i = 0; i < class->method.count; ++i) {
4131 MonoMethod *cm = class->methods [i];
4134 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4138 full_name = mono_method_full_name (cm, TRUE);
4140 slot = mono_method_try_get_vtable_index (cm);
4142 if (slot >= class->vtable_size) {
4143 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4147 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4148 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4149 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4150 g_free (other_name);
4153 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4160 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4162 char *method_signature;
4165 for (index = 0; index < onum; ++index) {
4166 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4167 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4169 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4170 type_name = mono_type_full_name (&class->byval_arg);
4171 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4172 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4173 g_free (method_signature);
4175 mono_class_setup_methods (class);
4176 if (class->exception_type) {
4177 char *name = mono_type_get_full_name (class);
4178 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4182 for (index = 0; index < class->method.count; ++index) {
4183 MonoMethod *cm = class->methods [index];
4184 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4186 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4187 g_free (method_signature);
4192 mono_method_get_method_definition (MonoMethod *method)
4194 while (method->is_inflated)
4195 method = ((MonoMethodInflated*)method)->declaring;
4200 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4204 for (i = 0; i < onum; ++i) {
4205 MonoMethod *decl = overrides [i * 2];
4206 MonoMethod *body = overrides [i * 2 + 1];
4208 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4209 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4213 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4214 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4215 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4217 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4221 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4222 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4223 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4225 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4229 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4230 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4234 body = mono_method_get_method_definition (body);
4235 decl = mono_method_get_method_definition (decl);
4237 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4238 char *body_name = mono_method_full_name (body, TRUE);
4239 char *decl_name = mono_method_full_name (decl, TRUE);
4240 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));
4250 mono_class_need_stelemref_method (MonoClass *class)
4252 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4256 * LOCKING: this is supposed to be called with the loader lock held.
4259 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4263 MonoMethod **vtable;
4264 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4265 GPtrArray *ifaces = NULL;
4266 GHashTable *override_map = NULL;
4267 gboolean security_enabled = mono_security_enabled ();
4269 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4270 int first_non_interface_slot;
4272 GSList *virt_methods = NULL, *l;
4273 int stelemref_slot = 0;
4278 if (overrides && !verify_class_overrides (class, overrides, onum))
4281 ifaces = mono_class_get_implemented_interfaces (class, &error);
4282 if (!mono_error_ok (&error)) {
4283 char *name = mono_type_get_full_name (class);
4284 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)));
4286 mono_error_cleanup (&error);
4288 } else if (ifaces) {
4289 for (i = 0; i < ifaces->len; i++) {
4290 MonoClass *ic = g_ptr_array_index (ifaces, i);
4291 max_vtsize += ic->method.count;
4293 g_ptr_array_free (ifaces, TRUE);
4297 if (class->parent) {
4298 mono_class_init (class->parent);
4299 mono_class_setup_vtable_full (class->parent, in_setup);
4301 if (class->parent->exception_type) {
4302 char *name = mono_type_get_full_name (class->parent);
4303 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4308 max_vtsize += class->parent->vtable_size;
4309 cur_slot = class->parent->vtable_size;
4312 max_vtsize += class->method.count;
4314 /*Array have a slot for stelemref*/
4315 if (mono_class_need_stelemref_method (class)) {
4316 stelemref_slot = cur_slot;
4321 vtable = alloca (sizeof (gpointer) * max_vtsize);
4322 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4324 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4326 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4327 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4330 max_iid = class->max_interface_id;
4331 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4333 /* Optimized version for generic instances */
4334 if (class->generic_class) {
4336 MonoClass *gklass = class->generic_class->container_class;
4339 mono_class_setup_vtable_full (gklass, in_setup);
4340 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4341 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4345 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4346 class->vtable_size = gklass->vtable_size;
4347 for (i = 0; i < gklass->vtable_size; ++i)
4348 if (gklass->vtable [i]) {
4349 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4350 if (!mono_error_ok (&error)) {
4351 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4352 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4354 mono_error_cleanup (&error);
4358 tmp [i]->slot = gklass->vtable [i]->slot;
4360 mono_memory_barrier ();
4361 class->vtable = tmp;
4363 /* Have to set method->slot for abstract virtual methods */
4364 if (class->methods && gklass->methods) {
4365 for (i = 0; i < class->method.count; ++i)
4366 if (class->methods [i]->slot == -1)
4367 class->methods [i]->slot = gklass->methods [i]->slot;
4373 if (class->parent && class->parent->vtable_size) {
4374 MonoClass *parent = class->parent;
4377 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4379 // Also inherit parent interface vtables, just as a starting point.
4380 // This is needed otherwise bug-77127.exe fails when the property methods
4381 // have different names in the iterface and the class, because for child
4382 // classes the ".override" information is not used anymore.
4383 for (i = 0; i < parent->interface_offsets_count; i++) {
4384 MonoClass *parent_interface = parent->interfaces_packed [i];
4385 int interface_offset = mono_class_interface_offset (class, parent_interface);
4386 /*FIXME this is now dead code as this condition will never hold true.
4387 Since interface offsets are inherited then the offset of an interface implemented
4388 by a parent will never be the out of it's vtable boundary.
4390 if (interface_offset >= parent->vtable_size) {
4391 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4394 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4395 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4396 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4397 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4398 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4399 parent_interface_offset + j, parent_interface_offset, j,
4400 interface_offset + j, interface_offset, j));
4407 /*Array have a slot for stelemref*/
4408 if (mono_class_need_stelemref_method (class)) {
4409 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4411 method->slot = stelemref_slot;
4413 g_assert (method->slot == stelemref_slot);
4415 vtable [stelemref_slot] = method;
4418 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4419 /* override interface methods */
4420 for (i = 0; i < onum; i++) {
4421 MonoMethod *decl = overrides [i*2];
4422 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4424 dslot = mono_method_get_vtable_slot (decl);
4426 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4430 dslot += mono_class_interface_offset (class, decl->klass);
4431 vtable [dslot] = overrides [i*2 + 1];
4432 vtable [dslot]->slot = dslot;
4434 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4436 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4438 if (mono_security_core_clr_enabled ())
4439 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4442 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4443 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4446 * Create a list of virtual methods to avoid calling
4447 * mono_class_get_virtual_methods () which is slow because of the metadata
4451 gpointer iter = NULL;
4454 virt_methods = NULL;
4455 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4456 virt_methods = g_slist_prepend (virt_methods, cm);
4458 if (class->exception_type)
4462 // Loop on all implemented interfaces...
4463 for (i = 0; i < class->interface_offsets_count; i++) {
4464 MonoClass *parent = class->parent;
4466 gboolean interface_is_explicitly_implemented_by_class;
4469 ic = class->interfaces_packed [i];
4470 ic_offset = mono_class_interface_offset (class, ic);
4472 mono_class_setup_methods (ic);
4473 if (ic->exception_type)
4476 // Check if this interface is explicitly implemented (instead of just inherited)
4477 if (parent != NULL) {
4478 int implemented_interfaces_index;
4479 interface_is_explicitly_implemented_by_class = FALSE;
4480 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4481 if (ic == class->interfaces [implemented_interfaces_index]) {
4482 interface_is_explicitly_implemented_by_class = TRUE;
4487 interface_is_explicitly_implemented_by_class = TRUE;
4490 // Loop on all interface methods...
4491 for (im_index = 0; im_index < ic->method.count; im_index++) {
4492 MonoMethod *im = ic->methods [im_index];
4493 int im_slot = ic_offset + im->slot;
4494 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4496 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4499 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4501 // If there is an explicit implementation, just use it right away,
4502 // otherwise look for a matching method
4503 if (override_im == NULL) {
4507 // First look for a suitable method among the class methods
4508 for (l = virt_methods; l; l = l->next) {
4510 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)));
4511 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4512 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4513 vtable [im_slot] = cm;
4514 /* Why do we need this? */
4519 TRACE_INTERFACE_VTABLE (printf ("\n"));
4520 if (class->exception_type) /*Might be set by check_interface_method_override*/
4524 // If the slot is still empty, look in all the inherited virtual methods...
4525 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4526 MonoClass *parent = class->parent;
4527 // Reverse order, so that last added methods are preferred
4528 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4529 MonoMethod *cm = parent->vtable [cm_index];
4531 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));
4532 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4533 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4534 vtable [im_slot] = cm;
4535 /* Why do we need this? */
4541 if (class->exception_type) /*Might be set by check_interface_method_override*/
4543 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4547 g_assert (vtable [im_slot] == override_im);
4552 // If the class is not abstract, check that all its interface slots are full.
4553 // The check is done here and not directly at the end of the loop above because
4554 // it can happen (for injected generic array interfaces) that the same slot is
4555 // processed multiple times (those interfaces have overlapping slots), and it
4556 // will not always be the first pass the one that fills the slot.
4557 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4558 for (i = 0; i < class->interface_offsets_count; i++) {
4562 ic = class->interfaces_packed [i];
4563 ic_offset = mono_class_interface_offset (class, ic);
4565 for (im_index = 0; im_index < ic->method.count; im_index++) {
4566 MonoMethod *im = ic->methods [im_index];
4567 int im_slot = ic_offset + im->slot;
4569 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4572 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4573 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4574 if (vtable [im_slot] == NULL) {
4575 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4582 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4583 for (l = virt_methods; l; l = l->next) {
4586 * If the method is REUSE_SLOT, we must check in the
4587 * base class for a method to override.
4589 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4591 for (k = class->parent; k ; k = k->parent) {
4596 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4597 MonoMethodSignature *cmsig, *m1sig;
4599 cmsig = mono_method_signature (cm);
4600 m1sig = mono_method_signature (m1);
4602 if (!cmsig || !m1sig) {
4603 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4607 if (!strcmp(cm->name, m1->name) &&
4608 mono_metadata_signature_equal (cmsig, m1sig)) {
4610 /* CAS - SecurityAction.InheritanceDemand */
4611 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4612 mono_secman_inheritancedemand_method (cm, m1);
4615 if (mono_security_core_clr_enabled ())
4616 mono_security_core_clr_check_override (class, cm, m1);
4618 slot = mono_method_get_vtable_slot (m1);
4622 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4623 char *body_name = mono_method_full_name (cm, TRUE);
4624 char *decl_name = mono_method_full_name (m1, TRUE);
4625 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));
4631 g_assert (cm->slot < max_vtsize);
4633 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4634 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4635 mono_method_full_name (m1, 1), m1,
4636 mono_method_full_name (cm, 1), cm));
4637 g_hash_table_insert (override_map, m1, cm);
4641 if (k->exception_type)
4651 /*Non final newslot methods must be given a non-interface vtable slot*/
4652 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4656 cm->slot = cur_slot++;
4658 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4659 vtable [cm->slot] = cm;
4662 /* override non interface methods */
4663 for (i = 0; i < onum; i++) {
4664 MonoMethod *decl = overrides [i*2];
4665 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4666 g_assert (decl->slot != -1);
4667 vtable [decl->slot] = overrides [i*2 + 1];
4668 overrides [i * 2 + 1]->slot = decl->slot;
4670 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4671 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4672 mono_method_full_name (decl, 1), decl,
4673 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4674 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4676 if (mono_security_core_clr_enabled ())
4677 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4682 * If a method occupies more than one place in the vtable, and it is
4683 * overriden, then change the other occurances too.
4688 for (i = 0; i < max_vtsize; ++i)
4690 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4692 cm = g_hash_table_lookup (override_map, vtable [i]);
4697 g_hash_table_destroy (override_map);
4698 override_map = NULL;
4701 g_slist_free (virt_methods);
4702 virt_methods = NULL;
4704 /* Ensure that all vtable slots are filled with concrete instance methods */
4705 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4706 for (i = 0; i < cur_slot; ++i) {
4707 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4708 char *type_name = mono_type_get_full_name (class);
4709 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4710 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));
4712 g_free (method_name);
4718 if (class->generic_class) {
4719 MonoClass *gklass = class->generic_class->container_class;
4721 mono_class_init (gklass);
4723 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4725 /* Check that the vtable_size value computed in mono_class_init () is correct */
4726 if (class->vtable_size)
4727 g_assert (cur_slot == class->vtable_size);
4728 class->vtable_size = cur_slot;
4731 /* Try to share the vtable with our parent. */
4732 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4733 mono_memory_barrier ();
4734 class->vtable = class->parent->vtable;
4736 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4737 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4738 mono_memory_barrier ();
4739 class->vtable = tmp;
4742 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4743 if (mono_print_vtable) {
4746 print_implemented_interfaces (class);
4748 for (i = 0; i <= max_iid; i++)
4749 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4752 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4753 class->vtable_size, icount);
4755 for (i = 0; i < cur_slot; ++i) {
4760 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4761 mono_method_full_name (cm, TRUE));
4767 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4768 class->name, max_iid);
4770 for (i = 0; i < class->interface_count; i++) {
4771 ic = class->interfaces [i];
4772 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4773 mono_class_interface_offset (class, ic),
4774 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4777 for (k = class->parent; k ; k = k->parent) {
4778 for (i = 0; i < k->interface_count; i++) {
4779 ic = k->interfaces [i];
4780 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4781 mono_class_interface_offset (class, ic),
4782 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4788 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4793 char *name = mono_type_get_full_name (class);
4794 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4797 g_hash_table_destroy (override_map);
4799 g_slist_free (virt_methods);
4804 * mono_method_get_vtable_slot:
4806 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4807 * LOCKING: Acquires the loader lock.
4809 * FIXME Use proper MonoError machinery here.
4812 mono_method_get_vtable_slot (MonoMethod *method)
4814 if (method->slot == -1) {
4815 mono_class_setup_vtable (method->klass);
4816 if (method->klass->exception_type)
4818 if (method->slot == -1) {
4822 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4823 g_assert (method->klass->generic_class);
4824 gklass = method->klass->generic_class->container_class;
4825 mono_class_setup_methods (method->klass);
4826 g_assert (method->klass->methods);
4827 for (i = 0; i < method->klass->method.count; ++i) {
4828 if (method->klass->methods [i] == method)
4831 g_assert (i < method->klass->method.count);
4832 g_assert (gklass->methods);
4833 method->slot = gklass->methods [i]->slot;
4835 g_assert (method->slot != -1);
4837 return method->slot;
4841 * mono_method_get_vtable_index:
4844 * Returns the index into the runtime vtable to access the method or,
4845 * in the case of a virtual generic method, the virtual generic method
4846 * thunk. Returns -1 on failure.
4848 * FIXME Use proper MonoError machinery here.
4851 mono_method_get_vtable_index (MonoMethod *method)
4853 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4854 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4855 if (imethod->declaring->is_generic)
4856 return mono_method_get_vtable_slot (imethod->declaring);
4858 return mono_method_get_vtable_slot (method);
4861 static MonoMethod *default_ghc = NULL;
4862 static MonoMethod *default_finalize = NULL;
4863 static int finalize_slot = -1;
4864 static int ghc_slot = -1;
4867 initialize_object_slots (MonoClass *class)
4872 if (class == mono_defaults.object_class) {
4873 mono_class_setup_vtable (class);
4874 for (i = 0; i < class->vtable_size; ++i) {
4875 MonoMethod *cm = class->vtable [i];
4877 if (!strcmp (cm->name, "GetHashCode"))
4879 else if (!strcmp (cm->name, "Finalize"))
4883 g_assert (ghc_slot > 0);
4884 default_ghc = class->vtable [ghc_slot];
4886 g_assert (finalize_slot > 0);
4887 default_finalize = class->vtable [finalize_slot];
4892 MonoMethod *array_method;
4894 } GenericArrayMethodInfo;
4896 static int generic_array_method_num = 0;
4897 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4900 generic_array_methods (MonoClass *class)
4902 int i, count_generic = 0;
4903 GList *list = NULL, *tmp;
4904 if (generic_array_method_num)
4905 return generic_array_method_num;
4906 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4907 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4908 for (i = 0; i < class->parent->method.count; i++) {
4909 MonoMethod *m = class->parent->methods [i];
4910 if (!strncmp (m->name, "InternalArray__", 15)) {
4912 list = g_list_prepend (list, m);
4915 list = g_list_reverse (list);
4916 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4918 for (tmp = list; tmp; tmp = tmp->next) {
4919 const char *mname, *iname;
4921 MonoMethod *m = tmp->data;
4922 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4923 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4925 generic_array_method_info [i].array_method = m;
4926 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4927 iname = "System.Collections.Generic.ICollection`1.";
4928 mname = m->name + 27;
4929 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4930 iname = "System.Collections.Generic.IEnumerable`1.";
4931 mname = m->name + 27;
4932 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4933 iname = "System.Collections.Generic.IReadOnlyList`1.";
4934 mname = m->name + strlen (ireadonlylist_prefix);
4935 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4936 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4937 mname = m->name + strlen (ireadonlycollection_prefix);
4938 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4939 iname = "System.Collections.Generic.IList`1.";
4940 mname = m->name + 15;
4942 g_assert_not_reached ();
4945 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4946 strcpy (name, iname);
4947 strcpy (name + strlen (iname), mname);
4948 generic_array_method_info [i].name = name;
4951 /*g_print ("array generic methods: %d\n", count_generic);*/
4953 generic_array_method_num = count_generic;
4955 return generic_array_method_num;
4959 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4961 MonoGenericContext tmp_context;
4964 tmp_context.class_inst = NULL;
4965 tmp_context.method_inst = iface->generic_class->context.class_inst;
4966 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4968 for (i = 0; i < generic_array_method_num; i++) {
4970 MonoMethod *m = generic_array_method_info [i].array_method;
4971 MonoMethod *inflated;
4973 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4974 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4975 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4980 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4982 int null_length = strlen ("(null)");
4983 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4984 char *s = mono_image_alloc (image, len);
4987 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4988 g_assert (result == len - 1);
4994 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4996 gpointer exception_data = NULL;
4998 switch (error->exception_type) {
4999 case MONO_EXCEPTION_TYPE_LOAD:
5000 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5003 case MONO_EXCEPTION_MISSING_METHOD:
5004 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5007 case MONO_EXCEPTION_MISSING_FIELD: {
5008 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5009 const char *class_name;
5012 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5014 class_name = error->klass->name;
5016 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5019 g_free ((void*)class_name);
5023 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5026 if (error->ref_only)
5027 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.";
5029 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5031 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5035 case MONO_EXCEPTION_BAD_IMAGE:
5036 exception_data = error->msg;
5040 g_assert_not_reached ();
5043 mono_class_set_failure (class, error->exception_type, exception_data);
5048 * @class: the class to initialize
5050 * Compute the instance_size, class_size and other infos that cannot be
5051 * computed at mono_class_get() time. Also compute vtable_size if possible.
5052 * Returns TRUE on success or FALSE if there was a problem in loading
5053 * the type (incorrect assemblies, missing assemblies, methods, etc).
5055 * LOCKING: Acquires the loader lock.
5058 mono_class_init (MonoClass *class)
5061 MonoCachedClassInfo cached_info;
5062 gboolean has_cached_info;
5066 /* Double-checking locking pattern */
5067 if (class->inited || class->exception_type)
5068 return class->exception_type == MONO_EXCEPTION_NONE;
5070 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5072 /* We do everything inside the lock to prevent races */
5073 mono_loader_lock ();
5075 if (class->inited || class->exception_type) {
5076 mono_loader_unlock ();
5077 /* Somebody might have gotten in before us */
5078 return class->exception_type == MONO_EXCEPTION_NONE;
5081 if (class->init_pending) {
5082 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5086 class->init_pending = 1;
5088 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5089 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5094 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5095 MonoClass *element_class = class->element_class;
5096 if (!element_class->inited)
5097 mono_class_init (element_class);
5098 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5099 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5104 /* CAS - SecurityAction.InheritanceDemand */
5105 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5106 mono_secman_inheritancedemand_class (class, class->parent);
5109 mono_stats.initialized_class_count++;
5111 if (class->generic_class && !class->generic_class->is_dynamic) {
5112 MonoClass *gklass = class->generic_class->container_class;
5114 mono_stats.generic_class_count++;
5116 class->method = gklass->method;
5117 class->field = gklass->field;
5119 mono_class_init (gklass);
5120 // FIXME: Why is this needed ?
5121 if (!gklass->exception_type)
5122 mono_class_setup_methods (gklass);
5123 if (gklass->exception_type) {
5124 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5128 if (MONO_CLASS_IS_INTERFACE (class))
5129 class->interface_id = mono_get_unique_iid (class);
5132 if (class->parent && !class->parent->inited)
5133 mono_class_init (class->parent);
5135 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5137 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5138 class->nested_classes_inited = TRUE;
5141 * Computes the size used by the fields, and their locations
5143 if (has_cached_info) {
5144 class->instance_size = cached_info.instance_size;
5145 class->sizes.class_size = cached_info.class_size;
5146 class->packing_size = cached_info.packing_size;
5147 class->min_align = cached_info.min_align;
5148 class->blittable = cached_info.blittable;
5149 class->has_references = cached_info.has_references;
5150 class->has_static_refs = cached_info.has_static_refs;
5151 class->no_special_static_fields = cached_info.no_special_static_fields;
5154 if (!class->size_inited){
5155 mono_class_setup_fields (class);
5156 if (class->exception_type || mono_loader_get_last_error ())
5160 /* Initialize arrays */
5162 class->method.count = 3 + (class->rank > 1? 2: 1);
5164 if (class->interface_count) {
5165 int count_generic = generic_array_methods (class);
5166 class->method.count += class->interface_count * count_generic;
5170 mono_class_setup_supertypes (class);
5173 initialize_object_slots (class);
5176 * Initialize the rest of the data without creating a generic vtable if possible.
5177 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5178 * also avoid computing a generic vtable.
5180 if (has_cached_info) {
5182 class->vtable_size = cached_info.vtable_size;
5183 class->has_finalize = cached_info.has_finalize;
5184 class->has_finalize_inited = TRUE;
5185 class->ghcimpl = cached_info.ghcimpl;
5186 class->has_cctor = cached_info.has_cctor;
5187 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5188 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5189 * The first slot if for array with.
5191 static int szarray_vtable_size[2] = { 0 };
5193 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5196 if (!szarray_vtable_size [slot]) {
5197 mono_class_setup_vtable (class);
5198 szarray_vtable_size [slot] = class->vtable_size;
5200 class->vtable_size = szarray_vtable_size[slot];
5202 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5203 MonoClass *gklass = class->generic_class->container_class;
5205 /* Generic instance case */
5206 class->ghcimpl = gklass->ghcimpl;
5207 class->has_cctor = gklass->has_cctor;
5209 mono_class_setup_vtable (gklass);
5210 if (gklass->exception_type) {
5211 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5215 class->vtable_size = gklass->vtable_size;
5219 /* ghcimpl is not currently used
5221 if (class->parent) {
5222 MonoMethod *cmethod = class->vtable [ghc_slot];
5223 if (cmethod->is_inflated)
5224 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5225 if (cmethod == default_ghc) {
5231 /* C# doesn't allow interfaces to have cctors */
5232 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5233 MonoMethod *cmethod = NULL;
5235 if (class->type_token) {
5236 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5237 /* The find_method function ignores the 'flags' argument */
5238 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5239 class->has_cctor = 1;
5241 mono_class_setup_methods (class);
5242 if (class->exception_type)
5245 for (i = 0; i < class->method.count; ++i) {
5246 MonoMethod *method = class->methods [i];
5247 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5248 (strcmp (".cctor", method->name) == 0)) {
5249 class->has_cctor = 1;
5257 if (class->parent) {
5258 int first_iface_slot;
5259 /* This will compute class->parent->vtable_size for some classes */
5260 mono_class_init (class->parent);
5261 if (class->parent->exception_type) {
5262 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5265 if (mono_loader_get_last_error ())
5267 if (!class->parent->vtable_size) {
5268 /* FIXME: Get rid of this somehow */
5269 mono_class_setup_vtable (class->parent);
5270 if (class->parent->exception_type) {
5271 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5274 if (mono_loader_get_last_error ())
5277 first_iface_slot = class->parent->vtable_size;
5278 if (mono_class_need_stelemref_method (class))
5280 setup_interface_offsets (class, first_iface_slot, TRUE);
5282 setup_interface_offsets (class, 0, TRUE);
5285 if (mono_security_core_clr_enabled ())
5286 mono_security_core_clr_check_inheritance (class);
5288 if (mono_loader_get_last_error ()) {
5289 if (class->exception_type == MONO_EXCEPTION_NONE) {
5290 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5292 mono_loader_clear_error ();
5295 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5296 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5301 /* Because of the double-checking locking pattern */
5302 mono_memory_barrier ();
5304 class->init_pending = 0;
5306 mono_loader_unlock ();
5308 return class->exception_type == MONO_EXCEPTION_NONE;
5312 * mono_class_has_finalizer:
5314 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5318 mono_class_has_finalizer (MonoClass *klass)
5320 MonoClass *class = klass;
5321 gboolean has_finalize = FALSE;
5323 if (klass->has_finalize_inited)
5324 return klass->has_finalize;
5326 /* Interfaces and valuetypes are not supposed to have finalizers */
5327 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5328 MonoMethod *cmethod = NULL;
5330 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5331 } else if (class->generic_class) {
5332 MonoClass *gklass = class->generic_class->container_class;
5334 has_finalize = mono_class_has_finalizer (gklass);
5335 } else if (class->parent && class->parent->has_finalize) {
5336 has_finalize = TRUE;
5338 if (class->parent) {
5340 * Can't search in metadata for a method named Finalize, because that
5341 * ignores overrides.
5343 mono_class_setup_vtable (class);
5344 if (class->exception_type || mono_loader_get_last_error ())
5347 cmethod = class->vtable [finalize_slot];
5351 g_assert (class->vtable_size > finalize_slot);
5353 if (class->parent) {
5354 if (cmethod->is_inflated)
5355 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5356 if (cmethod != default_finalize)
5357 has_finalize = TRUE;
5363 mono_image_lock (klass->image);
5365 if (!klass->has_finalize_inited) {
5366 klass->has_finalize = has_finalize ? 1 : 0;
5368 mono_memory_barrier ();
5369 klass->has_finalize_inited = TRUE;
5372 mono_image_unlock (klass->image);
5374 return klass->has_finalize;
5378 mono_is_corlib_image (MonoImage *image)
5380 /* FIXME: allow the dynamic case for our compilers and with full trust */
5381 if (image_is_dynamic (image))
5382 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5384 return image == mono_defaults.corlib;
5388 * LOCKING: this assumes the loader lock is held
5391 mono_class_setup_mono_type (MonoClass *class)
5393 const char *name = class->name;
5394 const char *nspace = class->name_space;
5395 gboolean is_corlib = mono_is_corlib_image (class->image);
5397 class->this_arg.byref = 1;
5398 class->this_arg.data.klass = class;
5399 class->this_arg.type = MONO_TYPE_CLASS;
5400 class->byval_arg.data.klass = class;
5401 class->byval_arg.type = MONO_TYPE_CLASS;
5403 if (is_corlib && !strcmp (nspace, "System")) {
5404 if (!strcmp (name, "ValueType")) {
5406 * do not set the valuetype bit for System.ValueType.
5407 * class->valuetype = 1;
5409 class->blittable = TRUE;
5410 } else if (!strcmp (name, "Enum")) {
5412 * do not set the valuetype bit for System.Enum.
5413 * class->valuetype = 1;
5415 class->valuetype = 0;
5416 class->enumtype = 0;
5417 } else if (!strcmp (name, "Object")) {
5418 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5419 } else if (!strcmp (name, "String")) {
5420 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5421 } else if (!strcmp (name, "TypedReference")) {
5422 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5426 if (class->valuetype) {
5427 int t = MONO_TYPE_VALUETYPE;
5429 if (is_corlib && !strcmp (nspace, "System")) {
5432 if (!strcmp (name, "Boolean")) {
5433 t = MONO_TYPE_BOOLEAN;
5434 } else if (!strcmp(name, "Byte")) {
5436 class->blittable = TRUE;
5440 if (!strcmp (name, "Char")) {
5445 if (!strcmp (name, "Double")) {
5447 class->blittable = TRUE;
5451 if (!strcmp (name, "Int32")) {
5453 class->blittable = TRUE;
5454 } else if (!strcmp(name, "Int16")) {
5456 class->blittable = TRUE;
5457 } else if (!strcmp(name, "Int64")) {
5459 class->blittable = TRUE;
5460 } else if (!strcmp(name, "IntPtr")) {
5462 class->blittable = TRUE;
5466 if (!strcmp (name, "Single")) {
5468 class->blittable = TRUE;
5469 } else if (!strcmp(name, "SByte")) {
5471 class->blittable = TRUE;
5475 if (!strcmp (name, "UInt32")) {
5477 class->blittable = TRUE;
5478 } else if (!strcmp(name, "UInt16")) {
5480 class->blittable = TRUE;
5481 } else if (!strcmp(name, "UInt64")) {
5483 class->blittable = TRUE;
5484 } else if (!strcmp(name, "UIntPtr")) {
5486 class->blittable = TRUE;
5490 if (!strcmp (name, "TypedReference")) {
5491 t = MONO_TYPE_TYPEDBYREF;
5492 class->blittable = TRUE;
5496 if (!strcmp (name, "Void")) {
5504 class->this_arg.type = class->byval_arg.type = t;
5507 if (MONO_CLASS_IS_INTERFACE (class))
5508 class->interface_id = mono_get_unique_iid (class);
5514 * COM initialization is delayed until needed.
5515 * However when a [ComImport] attribute is present on a type it will trigger
5516 * the initialization. This is not a problem unless the BCL being executed
5517 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5520 init_com_from_comimport (MonoClass *class)
5522 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5523 if (mono_security_core_clr_enabled ()) {
5524 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5525 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5526 /* but it can not be made available for application (i.e. user code) since all COM calls
5527 * are considered native calls. In this case we fail with a TypeLoadException (just like
5528 * Silverlight 2 does */
5529 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5534 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5536 #endif /*DISABLE_COM*/
5539 * LOCKING: this assumes the loader lock is held
5542 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5544 gboolean system_namespace;
5545 gboolean is_corlib = mono_is_corlib_image (class->image);
5547 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5549 /* if root of the hierarchy */
5550 if (system_namespace && !strcmp (class->name, "Object")) {
5551 class->parent = NULL;
5552 class->instance_size = sizeof (MonoObject);
5555 if (!strcmp (class->name, "<Module>")) {
5556 class->parent = NULL;
5557 class->instance_size = 0;
5561 if (!MONO_CLASS_IS_INTERFACE (class)) {
5562 /* Imported COM Objects always derive from __ComObject. */
5564 if (MONO_CLASS_IS_IMPORT (class)) {
5565 init_com_from_comimport (class);
5566 if (parent == mono_defaults.object_class)
5567 parent = mono_class_get_com_object_class ();
5571 /* set the parent to something useful and safe, but mark the type as broken */
5572 parent = mono_defaults.object_class;
5573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5576 class->parent = parent;
5578 if (parent->generic_class && !parent->name) {
5580 * If the parent is a generic instance, we may get
5581 * called before it is fully initialized, especially
5582 * before it has its name.
5587 #ifndef DISABLE_REMOTING
5588 class->marshalbyref = parent->marshalbyref;
5589 class->contextbound = parent->contextbound;
5592 class->delegate = parent->delegate;
5594 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5595 mono_class_set_is_com_object (class);
5597 if (system_namespace) {
5598 #ifndef DISABLE_REMOTING
5599 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5600 class->marshalbyref = 1;
5602 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5603 class->contextbound = 1;
5605 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5606 class->delegate = 1;
5609 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5610 (strcmp (class->parent->name_space, "System") == 0)))
5611 class->valuetype = 1;
5612 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5613 class->valuetype = class->enumtype = 1;
5615 /*class->enumtype = class->parent->enumtype; */
5617 /* initialize com types if COM interfaces are present */
5619 if (MONO_CLASS_IS_IMPORT (class))
5620 init_com_from_comimport (class);
5622 class->parent = NULL;
5628 * mono_class_setup_supertypes:
5631 * Build the data structure needed to make fast type checks work.
5632 * This currently sets two fields in @class:
5633 * - idepth: distance between @class and System.Object in the type
5635 * - supertypes: array of classes: each element has a class in the hierarchy
5636 * starting from @class up to System.Object
5638 * LOCKING: This function is atomic, in case of contention we waste memory.
5641 mono_class_setup_supertypes (MonoClass *class)
5644 MonoClass **supertypes;
5646 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5650 if (class->parent && !class->parent->supertypes)
5651 mono_class_setup_supertypes (class->parent);
5653 class->idepth = class->parent->idepth + 1;
5657 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5658 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5660 if (class->parent) {
5661 supertypes [class->idepth - 1] = class;
5662 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5664 supertypes [0] = class;
5667 mono_atomic_store_release (&class->supertypes, supertypes);
5671 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5673 MonoClass *gtd = (MonoClass*)user_data;
5674 /* Only try to fix generic instances of @gtd */
5675 if (gclass->generic_class->container_class != gtd)
5678 /* Check if the generic instance has no parent. */
5679 if (gtd->parent && !gclass->parent)
5680 mono_generic_class_setup_parent (gclass, gtd);
5686 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5688 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5689 mono_error_set_type_load_class (error, class, msg);
5693 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5695 MonoLoaderError *lerror = mono_loader_get_last_error ();
5698 set_failure_from_loader_error (class, lerror);
5699 mono_error_set_from_loader_error (error);
5703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5704 mono_error_set_type_load_class (error, class, msg);
5709 * mono_class_create_from_typedef:
5710 * @image: image where the token is valid
5711 * @type_token: typedef token
5712 * @error: used to return any error found while creating the type
5714 * Create the MonoClass* representing the specified type token.
5715 * @type_token must be a TypeDef token.
5717 * FIXME: don't return NULL on failure, just the the caller figure it out.
5720 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5722 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5723 MonoClass *class, *parent = NULL;
5724 guint32 cols [MONO_TYPEDEF_SIZE];
5725 guint32 cols_next [MONO_TYPEDEF_SIZE];
5726 guint tidx = mono_metadata_token_index (type_token);
5727 MonoGenericContext *context = NULL;
5728 const char *name, *nspace;
5730 MonoClass **interfaces;
5731 guint32 field_last, method_last;
5732 guint32 nesting_tokeen;
5734 mono_error_init (error);
5736 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5737 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5738 g_assert (!mono_loader_get_last_error ());
5742 mono_loader_lock ();
5744 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5745 mono_loader_unlock ();
5746 g_assert (!mono_loader_get_last_error ());
5750 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5752 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5753 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5755 class = mono_image_alloc0 (image, sizeof (MonoClass));
5758 class->name_space = nspace;
5760 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5762 class->image = image;
5763 class->type_token = type_token;
5764 class->flags = cols [MONO_TYPEDEF_FLAGS];
5766 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5768 classes_size += sizeof (MonoClass);
5771 * Check whether we're a generic type definition.
5773 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5774 if (class->generic_container) {
5775 class->is_generic = 1;
5776 class->generic_container->owner.klass = class;
5777 context = &class->generic_container->context;
5780 if (class->generic_container)
5781 enable_gclass_recording ();
5783 if (cols [MONO_TYPEDEF_EXTENDS]) {
5785 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5787 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5788 /*WARNING: this must satisfy mono_metadata_type_hash*/
5789 class->this_arg.byref = 1;
5790 class->this_arg.data.klass = class;
5791 class->this_arg.type = MONO_TYPE_CLASS;
5792 class->byval_arg.data.klass = class;
5793 class->byval_arg.type = MONO_TYPE_CLASS;
5795 parent = mono_class_get_checked (image, parent_token, error);
5796 if (parent && context) /* Always inflate */
5797 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5799 if (parent == NULL) {
5800 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5801 goto parent_failure;
5804 for (tmp = parent; tmp; tmp = tmp->parent) {
5806 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5807 goto parent_failure;
5809 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5810 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5811 goto parent_failure;
5816 mono_class_setup_parent (class, parent);
5818 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5819 mono_class_setup_mono_type (class);
5821 if (class->generic_container)
5822 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5825 * This might access class->byval_arg for recursion generated by generic constraints,
5826 * so it has to come after setup_mono_type ().
5828 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5829 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5830 if (!mono_error_ok (error)) {
5831 /*FIXME implement a mono_class_set_failure_from_mono_error */
5832 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5833 mono_loader_unlock ();
5834 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5835 g_assert (!mono_loader_get_last_error ());
5840 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5844 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5848 class->cast_class = class->element_class = class;
5850 if (!class->enumtype) {
5851 if (!mono_metadata_interfaces_from_typedef_full (
5852 image, type_token, &interfaces, &icount, FALSE, context, error)){
5854 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5855 mono_loader_unlock ();
5856 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5860 class->interfaces = interfaces;
5861 class->interface_count = icount;
5862 class->interfaces_inited = 1;
5865 /*g_print ("Load class %s\n", name);*/
5868 * Compute the field and method lists
5870 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5871 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5873 if (tt->rows > tidx){
5874 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5875 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5876 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5878 field_last = image->tables [MONO_TABLE_FIELD].rows;
5879 method_last = image->tables [MONO_TABLE_METHOD].rows;
5882 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5883 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5884 class->field.count = field_last - class->field.first;
5886 class->field.count = 0;
5888 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5889 class->method.count = method_last - class->method.first;
5891 class->method.count = 0;
5893 /* reserve space to store vector pointer in arrays */
5894 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5895 class->instance_size += 2 * sizeof (gpointer);
5896 g_assert (class->field.count == 0);
5899 if (class->enumtype) {
5900 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5901 if (!enum_basetype) {
5902 /*set it to a default value as the whole runtime can't handle this to be null*/
5903 class->cast_class = class->element_class = mono_defaults.int32_class;
5904 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5905 mono_loader_unlock ();
5906 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5907 g_assert (!mono_loader_get_last_error ());
5910 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5914 * If we're a generic type definition, load the constraints.
5915 * We must do this after the class has been constructed to make certain recursive scenarios
5918 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5919 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)));
5920 mono_loader_unlock ();
5921 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5922 g_assert (!mono_loader_get_last_error ());
5926 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5927 if (!strncmp (name, "Vector", 6))
5928 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");
5931 mono_loader_unlock ();
5933 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5934 g_assert (!mono_loader_get_last_error ());
5939 mono_class_setup_mono_type (class);
5940 mono_loader_unlock ();
5941 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5942 g_assert (!mono_loader_get_last_error ());
5946 /** is klass Nullable<T>? */
5948 mono_class_is_nullable (MonoClass *klass)
5950 return klass->generic_class != NULL &&
5951 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5955 /** if klass is T? return T */
5957 mono_class_get_nullable_param (MonoClass *klass)
5959 g_assert (mono_class_is_nullable (klass));
5960 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5964 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5968 MonoGenericClass *gclass = klass->generic_class;
5970 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5971 if (!mono_error_ok (&error)) {
5972 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5973 klass->parent = mono_defaults.object_class;
5974 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5975 mono_error_cleanup (&error);
5979 mono_class_setup_parent (klass, klass->parent);
5981 if (klass->enumtype) {
5982 klass->cast_class = gtd->cast_class;
5983 klass->element_class = gtd->element_class;
5989 * Create the `MonoClass' for an instantiation of a generic type.
5990 * We only do this if we actually need it.
5993 mono_generic_class_get_class (MonoGenericClass *gclass)
5995 MonoClass *klass, *gklass;
5997 if (gclass->cached_class)
5998 return gclass->cached_class;
6000 mono_loader_lock ();
6001 if (gclass->cached_class) {
6002 mono_loader_unlock ();
6003 return gclass->cached_class;
6006 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6008 gklass = gclass->container_class;
6010 if (record_gclass_instantiation > 0)
6011 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6013 if (gklass->nested_in) {
6014 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6015 klass->nested_in = gklass->nested_in;
6018 klass->name = gklass->name;
6019 klass->name_space = gklass->name_space;
6021 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6023 klass->image = gklass->image;
6024 klass->flags = gklass->flags;
6025 klass->type_token = gklass->type_token;
6026 klass->field.count = gklass->field.count;
6028 klass->is_inflated = 1;
6029 klass->generic_class = gclass;
6031 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6032 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6033 klass->this_arg.byref = TRUE;
6034 klass->enumtype = gklass->enumtype;
6035 klass->valuetype = gklass->valuetype;
6037 klass->cast_class = klass->element_class = klass;
6039 if (mono_class_is_nullable (klass))
6040 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6043 * We're not interested in the nested classes of a generic instance.
6044 * We use the generic type definition to look for nested classes.
6047 mono_generic_class_setup_parent (klass, gklass);
6049 if (gclass->is_dynamic) {
6052 mono_class_setup_supertypes (klass);
6054 if (klass->enumtype) {
6056 * For enums, gklass->fields might not been set, but instance_size etc. is
6057 * already set in mono_reflection_create_internal_class (). For non-enums,
6058 * these will be computed normally in mono_class_layout_fields ().
6060 klass->instance_size = gklass->instance_size;
6061 klass->sizes.class_size = gklass->sizes.class_size;
6062 mono_memory_barrier ();
6063 klass->size_inited = 1;
6067 mono_memory_barrier ();
6068 gclass->cached_class = klass;
6070 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6072 inflated_classes ++;
6073 inflated_classes_size += sizeof (MonoClass);
6075 mono_loader_unlock ();
6081 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6083 MonoClass *klass, **ptr;
6085 MonoGenericContainer *container = mono_generic_param_owner (param);
6089 image = mono_defaults.corlib;
6091 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6092 classes_size += sizeof (MonoClass);
6095 klass->name = pinfo->name;
6097 int n = mono_generic_param_num (param);
6098 klass->name = mono_image_alloc0 (image, 16);
6099 sprintf ((char*)klass->name, "%d", n);
6104 MonoMethod *omethod = container->owner.method;
6105 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6107 MonoClass *oklass = container->owner.klass;
6108 klass->name_space = oklass ? oklass->name_space : "";
6111 klass->name_space = "";
6114 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6118 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6122 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6123 klass->parent = pinfo->constraints [0];
6125 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6126 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6128 klass->parent = mono_defaults.object_class;
6131 if (count - pos > 0) {
6132 klass->interface_count = count - pos;
6133 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6134 klass->interfaces_inited = TRUE;
6135 for (i = pos; i < count; i++)
6136 klass->interfaces [i - pos] = pinfo->constraints [i];
6139 klass->image = image;
6141 klass->inited = TRUE;
6142 klass->cast_class = klass->element_class = klass;
6143 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6145 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6146 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6147 klass->this_arg.byref = TRUE;
6149 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6150 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6152 /*Init these fields to sane values*/
6153 klass->min_align = 1;
6155 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6156 * constrained to, the JIT depends on this.
6158 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6159 mono_memory_barrier ();
6160 klass->size_inited = 1;
6161 klass->setup_fields_called = 1;
6163 mono_class_setup_supertypes (klass);
6165 if (count - pos > 0) {
6166 mono_class_setup_vtable (klass->parent);
6167 if (klass->parent->exception_type)
6168 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6170 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6176 #define FAST_CACHE_SIZE 16
6179 * LOCKING: Takes the image lock depending on @take_lock.
6182 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6184 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6185 MonoImage *image = param->image;
6190 if (n < FAST_CACHE_SIZE) {
6192 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6194 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6196 MonoClass *klass = NULL;
6197 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6200 mono_image_lock (image);
6201 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6203 mono_image_unlock (image);
6210 * LOCKING: Image lock (param->image) must be held
6213 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6215 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6216 MonoImage *image = param->image;
6220 if (n < FAST_CACHE_SIZE) {
6222 /* Requires locking to avoid droping an already published class */
6223 if (!image->mvar_cache_fast)
6224 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6225 image->mvar_cache_fast [n] = klass;
6227 if (!image->var_cache_fast)
6228 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6229 image->var_cache_fast [n] = klass;
6232 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6234 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6236 ht = g_hash_table_new (NULL, NULL);
6237 mono_memory_barrier ();
6239 image->mvar_cache_slow = ht;
6241 image->var_cache_slow = ht;
6244 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6249 * LOCKING: Acquires the image lock (@image).
6252 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6254 MonoGenericContainer *container = mono_generic_param_owner (param);
6255 MonoGenericParamInfo *pinfo = NULL;
6256 MonoClass *klass, *klass2;
6259 pinfo = mono_generic_param_info (param);
6260 klass = pinfo->pklass;
6263 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6268 if (!image && container) {
6270 MonoMethod *method = container->owner.method;
6271 image = (method && method->klass) ? method->klass->image : NULL;
6273 MonoClass *klass = container->owner.klass;
6274 // FIXME: 'klass' should not be null
6275 // But, monodis creates GenericContainers without associating a owner to it
6276 image = klass ? klass->image : NULL;
6280 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6282 mono_memory_barrier ();
6284 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6285 image = mono_defaults.corlib;
6287 mono_image_lock (image);
6289 klass2 = pinfo->pklass;
6291 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6297 pinfo->pklass = klass;
6299 set_anon_gparam_class (param, is_mvar, klass);
6301 mono_image_unlock (image);
6303 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6305 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6307 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6313 mono_ptr_class_get (MonoType *type)
6316 MonoClass *el_class;
6320 el_class = mono_class_from_mono_type (type);
6321 image = el_class->image;
6323 mono_image_lock (image);
6324 if (image->ptr_cache) {
6325 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6326 mono_image_unlock (image);
6330 mono_image_unlock (image);
6332 result = mono_image_alloc0 (image, sizeof (MonoClass));
6334 classes_size += sizeof (MonoClass);
6336 result->parent = NULL; /* no parent for PTR types */
6337 result->name_space = el_class->name_space;
6338 name = g_strdup_printf ("%s*", el_class->name);
6339 result->name = mono_image_strdup (image, name);
6342 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6344 result->image = el_class->image;
6345 result->inited = TRUE;
6346 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6347 /* Can pointers get boxed? */
6348 result->instance_size = sizeof (gpointer);
6349 result->cast_class = result->element_class = el_class;
6350 result->blittable = TRUE;
6352 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6353 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6354 result->this_arg.byref = TRUE;
6356 mono_class_setup_supertypes (result);
6358 mono_image_lock (image);
6359 if (image->ptr_cache) {
6361 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6362 mono_image_unlock (image);
6363 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6367 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6369 g_hash_table_insert (image->ptr_cache, el_class, result);
6370 mono_image_unlock (image);
6372 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6378 mono_fnptr_class_get (MonoMethodSignature *sig)
6381 static GHashTable *ptr_hash = NULL;
6383 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6385 mono_loader_lock ();
6388 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6390 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6391 mono_loader_unlock ();
6394 result = g_new0 (MonoClass, 1);
6396 result->parent = NULL; /* no parent for PTR types */
6397 result->name_space = "System";
6398 result->name = "MonoFNPtrFakeClass";
6400 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6402 result->image = mono_defaults.corlib; /* need to fix... */
6403 result->inited = TRUE;
6404 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6405 /* Can pointers get boxed? */
6406 result->instance_size = sizeof (gpointer);
6407 result->cast_class = result->element_class = result;
6408 result->blittable = TRUE;
6410 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6411 result->this_arg.data.method = result->byval_arg.data.method = sig;
6412 result->this_arg.byref = TRUE;
6413 result->blittable = TRUE;
6415 mono_class_setup_supertypes (result);
6417 g_hash_table_insert (ptr_hash, sig, result);
6419 mono_loader_unlock ();
6421 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6427 mono_class_from_mono_type (MonoType *type)
6429 switch (type->type) {
6430 case MONO_TYPE_OBJECT:
6431 return type->data.klass? type->data.klass: mono_defaults.object_class;
6432 case MONO_TYPE_VOID:
6433 return type->data.klass? type->data.klass: mono_defaults.void_class;
6434 case MONO_TYPE_BOOLEAN:
6435 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6436 case MONO_TYPE_CHAR:
6437 return type->data.klass? type->data.klass: mono_defaults.char_class;
6439 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6441 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6443 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6445 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6447 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6449 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6451 return type->data.klass? type->data.klass: mono_defaults.int_class;
6453 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6455 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6457 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6459 return type->data.klass? type->data.klass: mono_defaults.single_class;
6461 return type->data.klass? type->data.klass: mono_defaults.double_class;
6462 case MONO_TYPE_STRING:
6463 return type->data.klass? type->data.klass: mono_defaults.string_class;
6464 case MONO_TYPE_TYPEDBYREF:
6465 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6466 case MONO_TYPE_ARRAY:
6467 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6469 return mono_ptr_class_get (type->data.type);
6470 case MONO_TYPE_FNPTR:
6471 return mono_fnptr_class_get (type->data.method);
6472 case MONO_TYPE_SZARRAY:
6473 return mono_array_class_get (type->data.klass, 1);
6474 case MONO_TYPE_CLASS:
6475 case MONO_TYPE_VALUETYPE:
6476 return type->data.klass;
6477 case MONO_TYPE_GENERICINST:
6478 return mono_generic_class_get_class (type->data.generic_class);
6480 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6481 case MONO_TYPE_MVAR:
6482 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6484 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6485 g_assert_not_reached ();
6492 * mono_type_retrieve_from_typespec
6493 * @image: context where the image is created
6494 * @type_spec: typespec token
6495 * @context: the generic context used to evaluate generic instantiations in
6498 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6500 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6502 *did_inflate = FALSE;
6507 if (context && (context->class_inst || context->method_inst)) {
6508 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6510 if (!mono_error_ok (error)) {
6511 g_assert (!mono_loader_get_last_error ());
6517 *did_inflate = TRUE;
6524 * mono_class_create_from_typespec
6525 * @image: context where the image is created
6526 * @type_spec: typespec token
6527 * @context: the generic context used to evaluate generic instantiations in
6530 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6533 gboolean inflated = FALSE;
6534 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6535 if (!mono_error_ok (error))
6537 ret = mono_class_from_mono_type (t);
6539 mono_metadata_free_type (t);
6544 * mono_bounded_array_class_get:
6545 * @element_class: element class
6546 * @rank: the dimension of the array class
6547 * @bounded: whenever the array has non-zero bounds
6549 * Returns: a class object describing the array with element type @element_type and
6553 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6557 MonoClass *parent = NULL;
6558 GSList *list, *rootlist = NULL;
6561 gboolean corlib_type = FALSE;
6563 g_assert (rank <= 255);
6566 /* bounded only matters for one-dimensional arrays */
6569 image = eclass->image;
6571 if (rank == 1 && !bounded) {
6573 * This case is very frequent not just during compilation because of calls
6574 * from mono_class_from_mono_type (), mono_array_new (),
6575 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6577 mono_mutex_lock (&image->szarray_cache_lock);
6578 if (!image->szarray_cache)
6579 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6580 class = g_hash_table_lookup (image->szarray_cache, eclass);
6581 mono_mutex_unlock (&image->szarray_cache_lock);
6585 mono_loader_lock ();
6587 mono_loader_lock ();
6589 if (!image->array_cache)
6590 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6592 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6593 for (; list; list = list->next) {
6595 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6596 mono_loader_unlock ();
6603 /* for the building corlib use System.Array from it */
6604 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6605 parent = mono_class_from_name (image, "System", "Array");
6608 parent = mono_defaults.array_class;
6609 if (!parent->inited)
6610 mono_class_init (parent);
6613 class = mono_image_alloc0 (image, sizeof (MonoClass));
6615 class->image = image;
6616 class->name_space = eclass->name_space;
6617 nsize = strlen (eclass->name);
6618 name = g_malloc (nsize + 2 + rank + 1);
6619 memcpy (name, eclass->name, nsize);
6622 memset (name + nsize + 1, ',', rank - 1);
6624 name [nsize + rank] = '*';
6625 name [nsize + rank + bounded] = ']';
6626 name [nsize + rank + bounded + 1] = 0;
6627 class->name = mono_image_strdup (image, name);
6630 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6632 classes_size += sizeof (MonoClass);
6634 class->type_token = 0;
6635 /* all arrays are marked serializable and sealed, bug #42779 */
6636 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6637 class->parent = parent;
6638 class->instance_size = mono_class_instance_size (class->parent);
6640 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6641 /*Arrays of those two types are invalid.*/
6642 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6643 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6644 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6645 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6646 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6648 /* element_size -1 is ok as this is not an instantitable type*/
6649 class->sizes.element_size = -1;
6651 class->sizes.element_size = mono_class_array_element_size (eclass);
6653 mono_class_setup_supertypes (class);
6655 if (eclass->generic_class)
6656 mono_class_init (eclass);
6657 if (!eclass->size_inited)
6658 mono_class_setup_fields (eclass);
6659 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6660 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6662 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6666 if (eclass->enumtype)
6667 class->cast_class = eclass->element_class;
6669 class->cast_class = eclass;
6671 switch (class->cast_class->byval_arg.type) {
6673 class->cast_class = mono_defaults.byte_class;
6676 class->cast_class = mono_defaults.int16_class;
6679 #if SIZEOF_VOID_P == 4
6683 class->cast_class = mono_defaults.int32_class;
6686 #if SIZEOF_VOID_P == 8
6690 class->cast_class = mono_defaults.int64_class;
6696 class->element_class = eclass;
6698 if ((rank > 1) || bounded) {
6699 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6700 class->byval_arg.type = MONO_TYPE_ARRAY;
6701 class->byval_arg.data.array = at;
6702 at->eklass = eclass;
6704 /* FIXME: complete.... */
6706 class->byval_arg.type = MONO_TYPE_SZARRAY;
6707 class->byval_arg.data.klass = eclass;
6709 class->this_arg = class->byval_arg;
6710 class->this_arg.byref = 1;
6715 class->generic_container = eclass->generic_container;
6717 if (rank == 1 && !bounded) {
6718 MonoClass *prev_class;
6720 mono_mutex_lock (&image->szarray_cache_lock);
6721 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6723 /* Someone got in before us */
6726 g_hash_table_insert (image->szarray_cache, eclass, class);
6727 mono_mutex_unlock (&image->szarray_cache_lock);
6729 list = g_slist_append (rootlist, class);
6730 g_hash_table_insert (image->array_cache, eclass, list);
6733 mono_loader_unlock ();
6735 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6741 * mono_array_class_get:
6742 * @element_class: element class
6743 * @rank: the dimension of the array class
6745 * Returns: a class object describing the array with element type @element_type and
6749 mono_array_class_get (MonoClass *eclass, guint32 rank)
6751 return mono_bounded_array_class_get (eclass, rank, FALSE);
6755 * mono_class_instance_size:
6758 * Returns: the size of an object instance
6761 mono_class_instance_size (MonoClass *klass)
6763 if (!klass->size_inited)
6764 mono_class_init (klass);
6766 return klass->instance_size;
6770 * mono_class_min_align:
6773 * Returns: minimm alignment requirements
6776 mono_class_min_align (MonoClass *klass)
6778 if (!klass->size_inited)
6779 mono_class_init (klass);
6781 return klass->min_align;
6785 * mono_class_value_size:
6788 * This function is used for value types, and return the
6789 * space and the alignment to store that kind of value object.
6791 * Returns: the size of a value of kind @klass
6794 mono_class_value_size (MonoClass *klass, guint32 *align)
6798 /* fixme: check disable, because we still have external revereces to
6799 * mscorlib and Dummy Objects
6801 /*g_assert (klass->valuetype);*/
6803 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6806 *align = klass->min_align;
6812 * mono_class_data_size:
6815 * Returns: the size of the static class data
6818 mono_class_data_size (MonoClass *klass)
6821 mono_class_init (klass);
6822 /* This can happen with dynamically created types */
6823 if (!klass->fields_inited)
6824 mono_class_setup_fields_locking (klass);
6826 /* in arrays, sizes.class_size is unioned with element_size
6827 * and arrays have no static fields
6831 return klass->sizes.class_size;
6835 * Auxiliary routine to mono_class_get_field
6837 * Takes a field index instead of a field token.
6839 static MonoClassField *
6840 mono_class_get_field_idx (MonoClass *class, int idx)
6842 mono_class_setup_fields_locking (class);
6843 if (class->exception_type)
6847 if (class->image->uncompressed_metadata) {
6849 * class->field.first points to the FieldPtr table, while idx points into the
6850 * Field table, so we have to do a search.
6852 /*FIXME this is broken for types with multiple fields with the same name.*/
6853 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6856 for (i = 0; i < class->field.count; ++i)
6857 if (mono_field_get_name (&class->fields [i]) == name)
6858 return &class->fields [i];
6859 g_assert_not_reached ();
6861 if (class->field.count) {
6862 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6863 return &class->fields [idx - class->field.first];
6867 class = class->parent;
6873 * mono_class_get_field:
6874 * @class: the class to lookup the field.
6875 * @field_token: the field token
6877 * Returns: A MonoClassField representing the type and offset of
6878 * the field, or a NULL value if the field does not belong to this
6882 mono_class_get_field (MonoClass *class, guint32 field_token)
6884 int idx = mono_metadata_token_index (field_token);
6886 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6888 return mono_class_get_field_idx (class, idx - 1);
6892 * mono_class_get_field_from_name:
6893 * @klass: the class to lookup the field.
6894 * @name: the field name
6896 * Search the class @klass and it's parents for a field with the name @name.
6898 * Returns: the MonoClassField pointer of the named field or NULL
6901 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6903 return mono_class_get_field_from_name_full (klass, name, NULL);
6907 * mono_class_get_field_from_name_full:
6908 * @klass: the class to lookup the field.
6909 * @name: the field name
6910 * @type: the type of the fields. This optional.
6912 * Search the class @klass and it's parents for a field with the name @name and type @type.
6914 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6915 * of its generic type definition.
6917 * Returns: the MonoClassField pointer of the named field or NULL
6920 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6924 mono_class_setup_fields_locking (klass);
6925 if (klass->exception_type)
6929 for (i = 0; i < klass->field.count; ++i) {
6930 MonoClassField *field = &klass->fields [i];
6932 if (strcmp (name, mono_field_get_name (field)) != 0)
6936 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6937 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6942 klass = klass->parent;
6948 * mono_class_get_field_token:
6949 * @field: the field we need the token of
6951 * Get the token of a field. Note that the tokesn is only valid for the image
6952 * the field was loaded from. Don't use this function for fields in dynamic types.
6954 * Returns: the token representing the field in the image it was loaded from.
6957 mono_class_get_field_token (MonoClassField *field)
6959 MonoClass *klass = field->parent;
6962 mono_class_setup_fields_locking (klass);
6967 for (i = 0; i < klass->field.count; ++i) {
6968 if (&klass->fields [i] == field) {
6969 int idx = klass->field.first + i + 1;
6971 if (klass->image->uncompressed_metadata)
6972 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6973 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6976 klass = klass->parent;
6979 g_assert_not_reached ();
6984 mono_field_get_index (MonoClassField *field)
6986 int index = field - field->parent->fields;
6988 g_assert (index >= 0 && index < field->parent->field.count);
6994 * mono_class_get_field_default_value:
6996 * Return the default value of the field as a pointer into the metadata blob.
6999 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7002 guint32 constant_cols [MONO_CONSTANT_SIZE];
7004 MonoClass *klass = field->parent;
7006 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7008 if (!klass->ext || !klass->ext->field_def_values) {
7009 MonoFieldDefaultValue *def_values;
7011 mono_class_alloc_ext (klass);
7013 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7015 mono_image_lock (klass->image);
7016 mono_memory_barrier ();
7017 if (!klass->ext->field_def_values)
7018 klass->ext->field_def_values = def_values;
7019 mono_image_unlock (klass->image);
7022 field_index = mono_field_get_index (field);
7024 if (!klass->ext->field_def_values [field_index].data) {
7025 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7029 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7031 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7032 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7033 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7036 *def_type = klass->ext->field_def_values [field_index].def_type;
7037 return klass->ext->field_def_values [field_index].data;
7041 mono_property_get_index (MonoProperty *prop)
7043 int index = prop - prop->parent->ext->properties;
7045 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7051 * mono_class_get_property_default_value:
7053 * Return the default value of the field as a pointer into the metadata blob.
7056 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7059 guint32 constant_cols [MONO_CONSTANT_SIZE];
7060 MonoClass *klass = property->parent;
7062 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7064 * We don't cache here because it is not used by C# so it's quite rare, but
7065 * we still do the lookup in klass->ext because that is where the data
7066 * is stored for dynamic assemblies.
7069 if (image_is_dynamic (klass->image)) {
7070 int prop_index = mono_property_get_index (property);
7071 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7072 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7073 return klass->ext->prop_def_values [prop_index].data;
7077 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7081 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7082 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7083 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7087 mono_class_get_event_token (MonoEvent *event)
7089 MonoClass *klass = event->parent;
7094 for (i = 0; i < klass->ext->event.count; ++i) {
7095 if (&klass->ext->events [i] == event)
7096 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7099 klass = klass->parent;
7102 g_assert_not_reached ();
7107 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7111 gpointer iter = NULL;
7112 while ((p = mono_class_get_properties (klass, &iter))) {
7113 if (! strcmp (name, p->name))
7116 klass = klass->parent;
7122 mono_class_get_property_token (MonoProperty *prop)
7124 MonoClass *klass = prop->parent;
7128 gpointer iter = NULL;
7129 while ((p = mono_class_get_properties (klass, &iter))) {
7130 if (&klass->ext->properties [i] == prop)
7131 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7135 klass = klass->parent;
7138 g_assert_not_reached ();
7143 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7145 const char *name, *nspace;
7146 if (image_is_dynamic (image))
7147 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7149 switch (type_token & 0xff000000){
7150 case MONO_TOKEN_TYPE_DEF: {
7151 guint32 cols [MONO_TYPEDEF_SIZE];
7152 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7153 guint tidx = mono_metadata_token_index (type_token);
7155 if (tidx > tt->rows)
7156 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7158 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7159 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7160 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7161 if (strlen (nspace) == 0)
7162 return g_strdup_printf ("%s", name);
7164 return g_strdup_printf ("%s.%s", nspace, name);
7167 case MONO_TOKEN_TYPE_REF: {
7169 guint32 cols [MONO_TYPEREF_SIZE];
7170 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7171 guint tidx = mono_metadata_token_index (type_token);
7174 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7176 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7177 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7178 mono_error_cleanup (&error);
7182 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7183 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7184 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7185 if (strlen (nspace) == 0)
7186 return g_strdup_printf ("%s", name);
7188 return g_strdup_printf ("%s.%s", nspace, name);
7191 case MONO_TOKEN_TYPE_SPEC:
7192 return g_strdup_printf ("Typespec 0x%08x", type_token);
7194 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7199 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7201 if (image_is_dynamic (image))
7202 return g_strdup_printf ("DynamicAssembly %s", image->name);
7204 switch (type_token & 0xff000000){
7205 case MONO_TOKEN_TYPE_DEF:
7206 if (image->assembly)
7207 return mono_stringify_assembly_name (&image->assembly->aname);
7208 else if (image->assembly_name)
7209 return g_strdup (image->assembly_name);
7210 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7211 case MONO_TOKEN_TYPE_REF: {
7213 MonoAssemblyName aname;
7214 guint32 cols [MONO_TYPEREF_SIZE];
7215 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7216 guint32 idx = mono_metadata_token_index (type_token);
7219 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7221 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7222 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7223 mono_error_cleanup (&error);
7226 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7228 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7229 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7230 case MONO_RESOLUTION_SCOPE_MODULE:
7232 return g_strdup ("");
7233 case MONO_RESOLUTION_SCOPE_MODULEREF:
7235 return g_strdup ("");
7236 case MONO_RESOLUTION_SCOPE_TYPEREF:
7238 return g_strdup ("");
7239 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7240 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7241 return mono_stringify_assembly_name (&aname);
7243 g_assert_not_reached ();
7247 case MONO_TOKEN_TYPE_SPEC:
7249 return g_strdup ("");
7251 g_assert_not_reached ();
7258 * mono_class_get_full:
7259 * @image: the image where the class resides
7260 * @type_token: the token for the class
7261 * @context: the generic context used to evaluate generic instantiations in
7262 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7264 * Returns: the MonoClass that represents @type_token in @image
7267 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7271 class = mono_class_get_checked (image, type_token, &error);
7273 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7274 class = mono_class_inflate_generic_class_checked (class, context, &error);
7276 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7282 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7286 mono_error_init (error);
7287 class = mono_class_get_checked (image, type_token, error);
7289 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7290 class = mono_class_inflate_generic_class_checked (class, context, error);
7295 * mono_class_get_checked:
7296 * @image: the image where the class resides
7297 * @type_token: the token for the class
7298 * @error: error object to return any error
7300 * Returns: the MonoClass that represents @type_token in @image
7303 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7305 MonoClass *class = NULL;
7307 mono_error_init (error);
7309 if (image_is_dynamic (image)) {
7310 int table = mono_metadata_token_table (type_token);
7312 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7313 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7316 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7320 switch (type_token & 0xff000000){
7321 case MONO_TOKEN_TYPE_DEF:
7322 class = mono_class_create_from_typedef (image, type_token, error);
7324 case MONO_TOKEN_TYPE_REF:
7325 class = mono_class_from_typeref_checked (image, type_token, error);
7327 case MONO_TOKEN_TYPE_SPEC:
7328 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7331 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7335 /* Generic case, should be avoided for when a better error is possible. */
7336 if (!class && mono_error_ok (error)) {
7337 char *name = mono_class_name_from_token (image, type_token);
7338 char *assembly = mono_assembly_name_from_token (image, type_token);
7339 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7347 * mono_type_get_checked:
7348 * @image: the image where the type resides
7349 * @type_token: the token for the type
7350 * @context: the generic context used to evaluate generic instantiations in
7351 * @error: Error handling context
7353 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7355 * Returns: the MonoType that represents @type_token in @image
7358 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7360 MonoType *type = NULL;
7361 gboolean inflated = FALSE;
7363 mono_error_init (error);
7365 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7366 if (image_is_dynamic (image))
7367 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7369 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7370 MonoClass *class = mono_class_get_checked (image, type_token, error);
7373 g_assert (!mono_loader_get_last_error ());
7378 return mono_class_get_type (class);
7381 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7384 g_assert (!mono_loader_get_last_error ());
7389 MonoType *tmp = type;
7390 type = mono_class_get_type (mono_class_from_mono_type (type));
7391 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7392 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7393 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7395 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7397 if (type->type != tmp->type)
7400 mono_metadata_free_type (tmp);
7407 mono_class_get (MonoImage *image, guint32 type_token)
7409 return mono_class_get_full (image, type_token, NULL);
7413 * mono_image_init_name_cache:
7415 * Initializes the class name cache stored in image->name_cache.
7417 * LOCKING: Acquires the corresponding image lock.
7420 mono_image_init_name_cache (MonoImage *image)
7422 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7423 guint32 cols [MONO_TYPEDEF_SIZE];
7426 guint32 i, visib, nspace_index;
7427 GHashTable *name_cache2, *nspace_table;
7429 mono_image_lock (image);
7431 if (image->name_cache) {
7432 mono_image_unlock (image);
7436 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7438 if (image_is_dynamic (image)) {
7439 mono_image_unlock (image);
7443 /* Temporary hash table to avoid lookups in the nspace_table */
7444 name_cache2 = g_hash_table_new (NULL, NULL);
7446 for (i = 1; i <= t->rows; ++i) {
7447 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7448 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7450 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7451 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7453 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7455 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7456 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7458 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7459 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7460 if (!nspace_table) {
7461 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7462 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7463 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7466 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7469 /* Load type names from EXPORTEDTYPES table */
7471 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7472 guint32 cols [MONO_EXP_TYPE_SIZE];
7475 for (i = 0; i < t->rows; ++i) {
7476 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7477 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7478 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7480 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7481 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7482 if (!nspace_table) {
7483 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7484 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7485 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7488 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7492 g_hash_table_destroy (name_cache2);
7493 mono_image_unlock (image);
7496 /*FIXME Only dynamic assemblies should allow this operation.*/
7498 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7499 const char *name, guint32 index)
7501 GHashTable *nspace_table;
7502 GHashTable *name_cache;
7505 mono_image_lock (image);
7507 if (!image->name_cache)
7508 mono_image_init_name_cache (image);
7510 name_cache = image->name_cache;
7511 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7512 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7513 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7516 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7517 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7519 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7521 mono_image_unlock (image);
7530 find_nocase (gpointer key, gpointer value, gpointer user_data)
7532 char *name = (char*)key;
7533 FindUserData *data = (FindUserData*)user_data;
7535 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7536 data->value = value;
7540 * mono_class_from_name_case:
7541 * @image: The MonoImage where the type is looked up in
7542 * @name_space: the type namespace
7543 * @name: the type short name.
7544 * @deprecated: use the _checked variant
7546 * Obtains a MonoClass with a given namespace and a given name which
7547 * is located in the given MonoImage. The namespace and name
7548 * lookups are case insensitive.
7551 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7554 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7555 g_assert (!mono_error_ok (&error));
7560 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7562 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7563 guint32 cols [MONO_TYPEDEF_SIZE];
7568 mono_error_init (error);
7570 if (image_is_dynamic (image)) {
7572 FindUserData user_data;
7574 mono_image_lock (image);
7576 if (!image->name_cache)
7577 mono_image_init_name_cache (image);
7579 user_data.key = name_space;
7580 user_data.value = NULL;
7581 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7583 if (user_data.value) {
7584 GHashTable *nspace_table = (GHashTable*)user_data.value;
7586 user_data.key = name;
7587 user_data.value = NULL;
7589 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7591 if (user_data.value)
7592 token = GPOINTER_TO_UINT (user_data.value);
7595 mono_image_unlock (image);
7598 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7604 /* add a cache if needed */
7605 for (i = 1; i <= t->rows; ++i) {
7606 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7607 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7609 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7610 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7612 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7614 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7615 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7616 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7617 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7623 return_nested_in (MonoClass *class, char *nested)
7626 char *s = strchr (nested, '/');
7627 gpointer iter = NULL;
7634 while ((found = mono_class_get_nested_types (class, &iter))) {
7635 if (strcmp (found->name, nested) == 0) {
7637 return return_nested_in (found, s);
7645 search_modules (MonoImage *image, const char *name_space, const char *name)
7647 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7648 MonoImage *file_image;
7653 * The EXPORTEDTYPES table only contains public types, so have to search the
7655 * Note: image->modules contains the contents of the MODULEREF table, while
7656 * the real module list is in the FILE table.
7658 for (i = 0; i < file_table->rows; i++) {
7659 guint32 cols [MONO_FILE_SIZE];
7660 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7661 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7664 file_image = mono_image_load_file_for_image (image, i + 1);
7666 class = mono_class_from_name (file_image, name_space, name);
7676 * mono_class_from_name:
7677 * @image: The MonoImage where the type is looked up in
7678 * @name_space: the type namespace
7679 * @name: the type short name.
7681 * Obtains a MonoClass with a given namespace and a given name which
7682 * is located in the given MonoImage.
7684 * To reference nested classes, use the "/" character as a separator.
7685 * For example use "Foo/Bar" to reference the class Bar that is nested
7686 * inside Foo, like this: "class Foo { class Bar {} }".
7689 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7692 GHashTable *nspace_table;
7693 MonoImage *loaded_image;
7700 if ((nested = strchr (name, '/'))) {
7701 int pos = nested - name;
7702 int len = strlen (name);
7705 memcpy (buf, name, len + 1);
7707 nested = buf + pos + 1;
7711 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7712 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7713 gboolean res = get_class_from_name (image, name_space, name, &class);
7716 class = search_modules (image, name_space, name);
7718 return class ? return_nested_in (class, nested) : NULL;
7724 mono_image_lock (image);
7726 if (!image->name_cache)
7727 mono_image_init_name_cache (image);
7729 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7732 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7734 mono_image_unlock (image);
7736 if (!token && image_is_dynamic (image) && image->modules) {
7737 /* Search modules as well */
7738 for (i = 0; i < image->module_count; ++i) {
7739 MonoImage *module = image->modules [i];
7741 class = mono_class_from_name (module, name_space, name);
7748 class = search_modules (image, name_space, name);
7756 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7757 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7758 guint32 cols [MONO_EXP_TYPE_SIZE];
7761 idx = mono_metadata_token_index (token);
7763 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7765 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7766 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7767 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7770 class = mono_class_from_name (loaded_image, name_space, name);
7772 return return_nested_in (class, nested);
7774 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7775 guint32 assembly_idx;
7777 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7779 mono_assembly_load_reference (image, assembly_idx - 1);
7780 g_assert (image->references [assembly_idx - 1]);
7781 if (image->references [assembly_idx - 1] == (gpointer)-1)
7784 /* FIXME: Cycle detection */
7785 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7787 g_error ("not yet implemented");
7791 token = MONO_TOKEN_TYPE_DEF | token;
7793 class = mono_class_get_checked (image, token, &error);
7794 if (!mono_error_ok (&error)) {
7795 mono_loader_set_error_from_mono_error (&error);
7796 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7799 return return_nested_in (class, nested);
7804 * mono_class_is_subclass_of:
7805 * @klass: class to probe if it is a subclass of another one
7806 * @klassc: the class we suspect is the base class
7807 * @check_interfaces: whether we should perform interface checks
7809 * This method determines whether @klass is a subclass of @klassc.
7811 * If the @check_interfaces flag is set, then if @klassc is an interface
7812 * this method return true if the @klass implements the interface or
7813 * if @klass is an interface, if one of its base classes is @klass.
7815 * If @check_interfaces is false then, then if @klass is not an interface
7816 * then it returns true if the @klass is a subclass of @klassc.
7818 * if @klass is an interface and @klassc is System.Object, then this function
7823 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7824 gboolean check_interfaces)
7826 /*FIXME test for interfaces with variant generic arguments*/
7828 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7829 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7831 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7834 for (i = 0; i < klass->interface_count; i ++) {
7835 MonoClass *ic = klass->interfaces [i];
7840 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7845 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7848 if (klassc == mono_defaults.object_class)
7855 mono_type_is_generic_argument (MonoType *type)
7857 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7861 mono_class_has_variant_generic_params (MonoClass *klass)
7864 MonoGenericContainer *container;
7866 if (!klass->generic_class)
7869 container = klass->generic_class->container_class->generic_container;
7871 for (i = 0; i < container->type_argc; ++i)
7872 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7879 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7881 if (target == candidate)
7884 if (check_for_reference_conv &&
7885 mono_type_is_generic_argument (&target->byval_arg) &&
7886 mono_type_is_generic_argument (&candidate->byval_arg)) {
7887 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7888 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7890 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7893 if (!mono_class_is_assignable_from (target, candidate))
7899 * @container the generic container from the GTD
7900 * @klass: the class to be assigned to
7901 * @oklass: the source class
7903 * Both klass and oklass must be instances of the same generic interface.
7904 * Return true if @klass can be assigned to a @klass variable
7907 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7910 MonoType **klass_argv, **oklass_argv;
7911 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7912 MonoGenericContainer *container = klass_gtd->generic_container;
7914 if (klass == oklass)
7917 /*Viable candidates are instances of the same generic interface*/
7918 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7921 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7922 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7924 for (j = 0; j < container->type_argc; ++j) {
7925 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7926 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7928 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7932 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7933 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7935 if (param1_class != param2_class) {
7936 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7937 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7939 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7940 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7950 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7952 MonoGenericParam *gparam, *ogparam;
7953 MonoGenericParamInfo *tinfo, *cinfo;
7954 MonoClass **candidate_class;
7955 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7958 if (target == candidate)
7960 if (target->byval_arg.type != candidate->byval_arg.type)
7963 gparam = target->byval_arg.data.generic_param;
7964 ogparam = candidate->byval_arg.data.generic_param;
7965 tinfo = mono_generic_param_info (gparam);
7966 cinfo = mono_generic_param_info (ogparam);
7968 class_constraint_satisfied = FALSE;
7969 valuetype_constraint_satisfied = FALSE;
7971 /*candidate must have a super set of target's special constraints*/
7972 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7973 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7975 if (cinfo->constraints) {
7976 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7977 MonoClass *cc = *candidate_class;
7979 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7980 class_constraint_satisfied = TRUE;
7981 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7982 valuetype_constraint_satisfied = TRUE;
7985 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7986 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7988 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7990 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7992 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7993 valuetype_constraint_satisfied)) {
7998 /*candidate type constraints must be a superset of target's*/
7999 if (tinfo->constraints) {
8000 MonoClass **target_class;
8001 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8002 MonoClass *tc = *target_class;
8005 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8006 * check it's constraints since it satisfy the constraint by itself.
8008 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8011 if (!cinfo->constraints)
8014 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8015 MonoClass *cc = *candidate_class;
8017 if (mono_class_is_assignable_from (tc, cc))
8021 * This happens when we have the following:
8023 * Bar<K> where K : IFace
8024 * Foo<T, U> where T : U where U : IFace
8026 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8029 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8030 if (mono_gparam_is_assignable_from (target, cc))
8034 if (!*candidate_class)
8039 /*candidate itself must have a constraint that satisfy target*/
8040 if (cinfo->constraints) {
8041 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8042 MonoClass *cc = *candidate_class;
8043 if (mono_class_is_assignable_from (target, cc))
8051 * mono_class_is_assignable_from:
8052 * @klass: the class to be assigned to
8053 * @oklass: the source class
8055 * Return: true if an instance of object oklass can be assigned to an
8056 * instance of object @klass
8059 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8061 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8063 mono_class_init (klass);
8065 if (!oklass->inited)
8066 mono_class_init (oklass);
8068 if (klass->exception_type || oklass->exception_type)
8071 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8072 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8074 return mono_gparam_is_assignable_from (klass, oklass);
8077 if (MONO_CLASS_IS_INTERFACE (klass)) {
8078 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8079 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8080 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8084 for (i = 0; constraints [i]; ++i) {
8085 if (mono_class_is_assignable_from (klass, constraints [i]))
8093 /* interface_offsets might not be set for dynamic classes */
8094 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8096 * oklass might be a generic type parameter but they have
8097 * interface_offsets set.
8099 return mono_reflection_call_is_assignable_to (oklass, klass);
8100 if (!oklass->interface_bitmap)
8101 /* Happens with generic instances of not-yet created dynamic types */
8103 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8106 if (mono_class_has_variant_generic_params (klass)) {
8109 mono_class_setup_interfaces (oklass, &error);
8110 if (!mono_error_ok (&error)) {
8111 mono_error_cleanup (&error);
8115 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8116 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8117 MonoClass *iface = oklass->interfaces_packed [i];
8119 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8124 } else if (klass->delegate) {
8125 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8127 }else if (klass->rank) {
8128 MonoClass *eclass, *eoclass;
8130 if (oklass->rank != klass->rank)
8133 /* vectors vs. one dimensional arrays */
8134 if (oklass->byval_arg.type != klass->byval_arg.type)
8137 eclass = klass->cast_class;
8138 eoclass = oklass->cast_class;
8141 * a is b does not imply a[] is b[] when a is a valuetype, and
8142 * b is a reference type.
8145 if (eoclass->valuetype) {
8146 if ((eclass == mono_defaults.enum_class) ||
8147 (eclass == mono_defaults.enum_class->parent) ||
8148 (eclass == mono_defaults.object_class))
8152 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8153 } else if (mono_class_is_nullable (klass)) {
8154 if (mono_class_is_nullable (oklass))
8155 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8157 return mono_class_is_assignable_from (klass->cast_class, oklass);
8158 } else if (klass == mono_defaults.object_class)
8161 return mono_class_has_parent (oklass, klass);
8164 /*Check if @oklass is variant compatible with @klass.*/
8166 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8169 MonoType **klass_argv, **oklass_argv;
8170 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8171 MonoGenericContainer *container = klass_gtd->generic_container;
8173 /*Viable candidates are instances of the same generic interface*/
8174 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8177 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8178 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8180 for (j = 0; j < container->type_argc; ++j) {
8181 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8182 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8184 if (param1_class->valuetype != param2_class->valuetype)
8188 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8189 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8191 if (param1_class != param2_class) {
8192 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8193 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8195 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8196 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8204 /*Check if @candidate implements the interface @target*/
8206 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8210 gboolean is_variant = mono_class_has_variant_generic_params (target);
8212 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8213 if (mono_class_is_variant_compatible_slow (target, candidate))
8218 if (candidate == target)
8221 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8222 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8223 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8225 if (tb && tb->interfaces) {
8226 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8227 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8228 MonoClass *iface_class;
8230 /* we can't realize the type here since it can do pretty much anything. */
8233 iface_class = mono_class_from_mono_type (iface->type);
8234 if (iface_class == target)
8236 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8238 if (mono_class_implement_interface_slow (target, iface_class))
8243 /*setup_interfaces don't mono_class_init anything*/
8244 /*FIXME this doesn't handle primitive type arrays.
8245 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8246 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8248 mono_class_setup_interfaces (candidate, &error);
8249 if (!mono_error_ok (&error)) {
8250 mono_error_cleanup (&error);
8254 for (i = 0; i < candidate->interface_count; ++i) {
8255 if (candidate->interfaces [i] == target)
8258 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8261 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8265 candidate = candidate->parent;
8266 } while (candidate);
8272 * Check if @oklass can be assigned to @klass.
8273 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8276 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8278 if (candidate == target)
8280 if (target == mono_defaults.object_class)
8283 if (mono_class_has_parent (candidate, target))
8286 /*If target is not an interface there is no need to check them.*/
8287 if (MONO_CLASS_IS_INTERFACE (target))
8288 return mono_class_implement_interface_slow (target, candidate);
8290 if (target->delegate && mono_class_has_variant_generic_params (target))
8291 return mono_class_is_variant_compatible (target, candidate, FALSE);
8294 MonoClass *eclass, *eoclass;
8296 if (target->rank != candidate->rank)
8299 /* vectors vs. one dimensional arrays */
8300 if (target->byval_arg.type != candidate->byval_arg.type)
8303 eclass = target->cast_class;
8304 eoclass = candidate->cast_class;
8307 * a is b does not imply a[] is b[] when a is a valuetype, and
8308 * b is a reference type.
8311 if (eoclass->valuetype) {
8312 if ((eclass == mono_defaults.enum_class) ||
8313 (eclass == mono_defaults.enum_class->parent) ||
8314 (eclass == mono_defaults.object_class))
8318 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8320 /*FIXME properly handle nullables */
8321 /*FIXME properly handle (M)VAR */
8326 * mono_class_get_cctor:
8327 * @klass: A MonoClass pointer
8329 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8332 mono_class_get_cctor (MonoClass *klass)
8334 MonoCachedClassInfo cached_info;
8336 if (image_is_dynamic (klass->image)) {
8338 * has_cctor is not set for these classes because mono_class_init () is
8341 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8344 if (!klass->has_cctor)
8347 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8349 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8350 if (!mono_error_ok (&error))
8351 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8355 if (klass->generic_class && !klass->methods)
8356 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8358 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8362 * mono_class_get_finalizer:
8363 * @klass: The MonoClass pointer
8365 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8368 mono_class_get_finalizer (MonoClass *klass)
8370 MonoCachedClassInfo cached_info;
8373 mono_class_init (klass);
8374 if (!mono_class_has_finalizer (klass))
8377 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8379 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8380 if (!mono_error_ok (&error))
8381 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8384 mono_class_setup_vtable (klass);
8385 return klass->vtable [finalize_slot];
8390 * mono_class_needs_cctor_run:
8391 * @klass: the MonoClass pointer
8392 * @caller: a MonoMethod describing the caller
8394 * Determines whenever the class has a static constructor and whenever it
8395 * needs to be called when executing CALLER.
8398 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8402 method = mono_class_get_cctor (klass);
8404 return (method == caller) ? FALSE : TRUE;
8410 * mono_class_array_element_size:
8413 * Returns: the number of bytes an element of type @klass
8414 * uses when stored into an array.
8417 mono_class_array_element_size (MonoClass *klass)
8419 MonoType *type = &klass->byval_arg;
8422 switch (type->type) {
8425 case MONO_TYPE_BOOLEAN:
8429 case MONO_TYPE_CHAR:
8438 case MONO_TYPE_CLASS:
8439 case MONO_TYPE_STRING:
8440 case MONO_TYPE_OBJECT:
8441 case MONO_TYPE_SZARRAY:
8442 case MONO_TYPE_ARRAY:
8443 return sizeof (gpointer);
8448 case MONO_TYPE_VALUETYPE:
8449 if (type->data.klass->enumtype) {
8450 type = mono_class_enum_basetype (type->data.klass);
8451 klass = klass->element_class;
8454 return mono_class_instance_size (klass) - sizeof (MonoObject);
8455 case MONO_TYPE_GENERICINST:
8456 type = &type->data.generic_class->container_class->byval_arg;
8459 case MONO_TYPE_MVAR: {
8462 return mono_type_size (type, &align);
8464 case MONO_TYPE_VOID:
8468 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8474 * mono_array_element_size:
8475 * @ac: pointer to a #MonoArrayClass
8477 * Returns: the size of single array element.
8480 mono_array_element_size (MonoClass *ac)
8482 g_assert (ac->rank);
8483 return ac->sizes.element_size;
8487 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8488 MonoGenericContext *context)
8491 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8492 g_assert (mono_error_ok (&error));
8497 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8498 MonoGenericContext *context, MonoError *error)
8500 mono_error_init (error);
8502 if (image_is_dynamic (image)) {
8503 MonoClass *tmp_handle_class;
8504 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8506 g_assert (tmp_handle_class);
8508 *handle_class = tmp_handle_class;
8510 if (tmp_handle_class == mono_defaults.typehandle_class)
8511 return &((MonoClass*)obj)->byval_arg;
8516 switch (token & 0xff000000) {
8517 case MONO_TOKEN_TYPE_DEF:
8518 case MONO_TOKEN_TYPE_REF:
8519 case MONO_TOKEN_TYPE_SPEC: {
8522 *handle_class = mono_defaults.typehandle_class;
8523 type = mono_type_get_checked (image, token, context, error);
8527 mono_class_init (mono_class_from_mono_type (type));
8528 /* We return a MonoType* as handle */
8531 case MONO_TOKEN_FIELD_DEF: {
8533 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8535 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8539 *handle_class = mono_defaults.fieldhandle_class;
8540 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8544 mono_class_init (class);
8545 return mono_class_get_field (class, token);
8547 case MONO_TOKEN_METHOD_DEF:
8548 case MONO_TOKEN_METHOD_SPEC: {
8550 meth = mono_get_method_checked (image, token, NULL, context, error);
8552 *handle_class = mono_defaults.methodhandle_class;
8558 case MONO_TOKEN_MEMBER_REF: {
8559 guint32 cols [MONO_MEMBERREF_SIZE];
8561 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8562 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8563 mono_metadata_decode_blob_size (sig, &sig);
8564 if (*sig == 0x6) { /* it's a field */
8566 MonoClassField *field;
8567 field = mono_field_from_token_checked (image, token, &klass, context, error);
8569 *handle_class = mono_defaults.fieldhandle_class;
8573 meth = mono_get_method_checked (image, token, NULL, context, error);
8575 *handle_class = mono_defaults.methodhandle_class;
8580 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8586 * This function might need to call runtime functions so it can't be part
8587 * of the metadata library.
8589 static MonoLookupDynamicToken lookup_dynamic = NULL;
8592 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8594 lookup_dynamic = func;
8598 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8600 MonoClass *handle_class;
8602 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8606 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8608 return lookup_dynamic (image, token, valid_token, handle_class, context);
8611 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8614 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8616 get_cached_class_info = func;
8620 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8622 if (!get_cached_class_info)
8625 return get_cached_class_info (klass, res);
8629 mono_install_get_class_from_name (MonoGetClassFromName func)
8631 get_class_from_name = func;
8635 mono_class_get_image (MonoClass *klass)
8637 return klass->image;
8641 * mono_class_get_element_class:
8642 * @klass: the MonoClass to act on
8644 * Returns: the element class of an array or an enumeration.
8647 mono_class_get_element_class (MonoClass *klass)
8649 return klass->element_class;
8653 * mono_class_is_valuetype:
8654 * @klass: the MonoClass to act on
8656 * Returns: true if the MonoClass represents a ValueType.
8659 mono_class_is_valuetype (MonoClass *klass)
8661 return klass->valuetype;
8665 * mono_class_is_enum:
8666 * @klass: the MonoClass to act on
8668 * Returns: true if the MonoClass represents an enumeration.
8671 mono_class_is_enum (MonoClass *klass)
8673 return klass->enumtype;
8677 * mono_class_enum_basetype:
8678 * @klass: the MonoClass to act on
8680 * Returns: the underlying type representation for an enumeration.
8683 mono_class_enum_basetype (MonoClass *klass)
8685 if (klass->element_class == klass)
8686 /* SRE or broken types */
8689 return &klass->element_class->byval_arg;
8693 * mono_class_get_parent
8694 * @klass: the MonoClass to act on
8696 * Returns: the parent class for this class.
8699 mono_class_get_parent (MonoClass *klass)
8701 return klass->parent;
8705 * mono_class_get_nesting_type;
8706 * @klass: the MonoClass to act on
8708 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8711 mono_class_get_nesting_type (MonoClass *klass)
8713 return klass->nested_in;
8717 * mono_class_get_rank:
8718 * @klass: the MonoClass to act on
8720 * Returns: the rank for the array (the number of dimensions).
8723 mono_class_get_rank (MonoClass *klass)
8729 * mono_class_get_flags:
8730 * @klass: the MonoClass to act on
8732 * The type flags from the TypeDef table from the metadata.
8733 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8736 * Returns: the flags from the TypeDef table.
8739 mono_class_get_flags (MonoClass *klass)
8741 return klass->flags;
8745 * mono_class_get_name
8746 * @klass: the MonoClass to act on
8748 * Returns: the name of the class.
8751 mono_class_get_name (MonoClass *klass)
8757 * mono_class_get_namespace:
8758 * @klass: the MonoClass to act on
8760 * Returns: the namespace of the class.
8763 mono_class_get_namespace (MonoClass *klass)
8765 return klass->name_space;
8769 * mono_class_get_type:
8770 * @klass: the MonoClass to act on
8772 * This method returns the internal Type representation for the class.
8774 * Returns: the MonoType from the class.
8777 mono_class_get_type (MonoClass *klass)
8779 return &klass->byval_arg;
8783 * mono_class_get_type_token
8784 * @klass: the MonoClass to act on
8786 * This method returns type token for the class.
8788 * Returns: the type token for the class.
8791 mono_class_get_type_token (MonoClass *klass)
8793 return klass->type_token;
8797 * mono_class_get_byref_type:
8798 * @klass: the MonoClass to act on
8803 mono_class_get_byref_type (MonoClass *klass)
8805 return &klass->this_arg;
8809 * mono_class_num_fields:
8810 * @klass: the MonoClass to act on
8812 * Returns: the number of static and instance fields in the class.
8815 mono_class_num_fields (MonoClass *klass)
8817 return klass->field.count;
8821 * mono_class_num_methods:
8822 * @klass: the MonoClass to act on
8824 * Returns: the number of methods in the class.
8827 mono_class_num_methods (MonoClass *klass)
8829 return klass->method.count;
8833 * mono_class_num_properties
8834 * @klass: the MonoClass to act on
8836 * Returns: the number of properties in the class.
8839 mono_class_num_properties (MonoClass *klass)
8841 mono_class_setup_properties (klass);
8843 return klass->ext->property.count;
8847 * mono_class_num_events:
8848 * @klass: the MonoClass to act on
8850 * Returns: the number of events in the class.
8853 mono_class_num_events (MonoClass *klass)
8855 mono_class_setup_events (klass);
8857 return klass->ext->event.count;
8861 * mono_class_get_fields:
8862 * @klass: the MonoClass to act on
8864 * This routine is an iterator routine for retrieving the fields in a class.
8866 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8867 * iterate over all of the elements. When no more values are
8868 * available, the return value is NULL.
8870 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8873 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8875 MonoClassField* field;
8879 mono_class_setup_fields_locking (klass);
8880 if (klass->exception_type)
8882 /* start from the first */
8883 if (klass->field.count) {
8884 return *iter = &klass->fields [0];
8892 if (field < &klass->fields [klass->field.count]) {
8893 return *iter = field;
8899 * mono_class_get_methods
8900 * @klass: the MonoClass to act on
8902 * This routine is an iterator routine for retrieving the fields in a class.
8904 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8905 * iterate over all of the elements. When no more values are
8906 * available, the return value is NULL.
8908 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8911 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8913 MonoMethod** method;
8917 mono_class_setup_methods (klass);
8920 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8921 * FIXME we should better report this error to the caller
8923 if (!klass->methods)
8925 /* start from the first */
8926 if (klass->method.count) {
8927 *iter = &klass->methods [0];
8928 return klass->methods [0];
8936 if (method < &klass->methods [klass->method.count]) {
8944 * mono_class_get_virtual_methods:
8946 * Iterate over the virtual methods of KLASS.
8948 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8951 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8953 MonoMethod** method;
8956 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8958 mono_class_setup_methods (klass);
8960 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8961 * FIXME we should better report this error to the caller
8963 if (!klass->methods)
8965 /* start from the first */
8966 method = &klass->methods [0];
8971 while (method < &klass->methods [klass->method.count]) {
8972 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8976 if (method < &klass->methods [klass->method.count]) {
8983 /* Search directly in metadata to avoid calling setup_methods () */
8984 MonoMethod *res = NULL;
8990 start_index = GPOINTER_TO_UINT (*iter);
8993 for (i = start_index; i < klass->method.count; ++i) {
8996 /* class->method.first points into the methodptr table */
8997 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8999 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9003 if (i < klass->method.count) {
9005 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9006 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9008 /* Add 1 here so the if (*iter) check fails */
9009 *iter = GUINT_TO_POINTER (i + 1);
9018 * mono_class_get_properties:
9019 * @klass: the MonoClass to act on
9021 * This routine is an iterator routine for retrieving the properties in a class.
9023 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9024 * iterate over all of the elements. When no more values are
9025 * available, the return value is NULL.
9027 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9030 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9032 MonoProperty* property;
9036 mono_class_setup_properties (klass);
9037 /* start from the first */
9038 if (klass->ext->property.count) {
9039 return *iter = &klass->ext->properties [0];
9047 if (property < &klass->ext->properties [klass->ext->property.count]) {
9048 return *iter = property;
9054 * mono_class_get_events:
9055 * @klass: the MonoClass to act on
9057 * This routine is an iterator routine for retrieving the properties in a class.
9059 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9060 * iterate over all of the elements. When no more values are
9061 * available, the return value is NULL.
9063 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9066 mono_class_get_events (MonoClass* klass, gpointer *iter)
9072 mono_class_setup_events (klass);
9073 /* start from the first */
9074 if (klass->ext->event.count) {
9075 return *iter = &klass->ext->events [0];
9083 if (event < &klass->ext->events [klass->ext->event.count]) {
9084 return *iter = event;
9090 * mono_class_get_interfaces
9091 * @klass: the MonoClass to act on
9093 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9095 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9096 * iterate over all of the elements. When no more values are
9097 * available, the return value is NULL.
9099 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9102 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9110 mono_class_init (klass);
9111 if (!klass->interfaces_inited) {
9112 mono_class_setup_interfaces (klass, &error);
9113 if (!mono_error_ok (&error)) {
9114 mono_error_cleanup (&error);
9118 /* start from the first */
9119 if (klass->interface_count) {
9120 *iter = &klass->interfaces [0];
9121 return klass->interfaces [0];
9129 if (iface < &klass->interfaces [klass->interface_count]) {
9137 setup_nested_types (MonoClass *klass)
9140 GList *classes, *nested_classes, *l;
9143 if (klass->nested_classes_inited)
9146 if (!klass->type_token)
9147 klass->nested_classes_inited = TRUE;
9149 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9153 guint32 cols [MONO_NESTED_CLASS_SIZE];
9154 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9155 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9156 if (!mono_error_ok (&error)) {
9157 /*FIXME don't swallow the error message*/
9158 mono_error_cleanup (&error);
9160 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9164 classes = g_list_prepend (classes, nclass);
9166 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9169 mono_class_alloc_ext (klass);
9171 nested_classes = NULL;
9172 for (l = classes; l; l = l->next)
9173 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9174 g_list_free (classes);
9176 mono_image_lock (klass->image);
9178 mono_memory_barrier ();
9179 if (!klass->nested_classes_inited) {
9180 klass->ext->nested_classes = nested_classes;
9181 mono_memory_barrier ();
9182 klass->nested_classes_inited = TRUE;
9185 mono_image_unlock (klass->image);
9189 * mono_class_get_nested_types
9190 * @klass: the MonoClass to act on
9192 * This routine is an iterator routine for retrieving the nested types of a class.
9193 * This works only if @klass is non-generic, or a generic type definition.
9195 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9196 * iterate over all of the elements. When no more values are
9197 * available, the return value is NULL.
9199 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9202 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9208 if (!klass->nested_classes_inited)
9209 setup_nested_types (klass);
9212 /* start from the first */
9213 if (klass->ext && klass->ext->nested_classes) {
9214 *iter = klass->ext->nested_classes;
9215 return klass->ext->nested_classes->data;
9217 /* no nested types */
9232 * mono_class_is_delegate
9233 * @klass: the MonoClass to act on
9235 * Returns: true if the MonoClass represents a System.Delegate.
9238 mono_class_is_delegate (MonoClass *klass)
9240 return klass->delegate;
9244 * mono_class_implements_interface
9245 * @klass: The MonoClass to act on
9246 * @interface: The interface to check if @klass implements.
9248 * Returns: true if @klass implements @interface.
9251 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9253 return mono_class_is_assignable_from (iface, klass);
9257 * mono_field_get_name:
9258 * @field: the MonoClassField to act on
9260 * Returns: the name of the field.
9263 mono_field_get_name (MonoClassField *field)
9269 * mono_field_get_type:
9270 * @field: the MonoClassField to act on
9272 * Returns: MonoType of the field.
9275 mono_field_get_type (MonoClassField *field)
9278 MonoType *type = mono_field_get_type_checked (field, &error);
9279 if (!mono_error_ok (&error)) {
9280 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9281 mono_error_cleanup (&error);
9288 * mono_field_get_type_checked:
9289 * @field: the MonoClassField to act on
9290 * @error: used to return any erro found while retrieving @field type
9292 * Returns: MonoType of the field.
9295 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9297 mono_error_init (error);
9299 mono_field_resolve_type (field, error);
9304 * mono_field_get_parent:
9305 * @field: the MonoClassField to act on
9307 * Returns: MonoClass where the field was defined.
9310 mono_field_get_parent (MonoClassField *field)
9312 return field->parent;
9316 * mono_field_get_flags;
9317 * @field: the MonoClassField to act on
9319 * The metadata flags for a field are encoded using the
9320 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9322 * Returns: the flags for the field.
9325 mono_field_get_flags (MonoClassField *field)
9328 return mono_field_resolve_flags (field);
9329 return field->type->attrs;
9333 * mono_field_get_offset;
9334 * @field: the MonoClassField to act on
9336 * Returns: the field offset.
9339 mono_field_get_offset (MonoClassField *field)
9341 return field->offset;
9345 mono_field_get_rva (MonoClassField *field)
9349 MonoClass *klass = field->parent;
9350 MonoFieldDefaultValue *field_def_values;
9352 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9354 if (!klass->ext || !klass->ext->field_def_values) {
9355 mono_class_alloc_ext (klass);
9357 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9359 mono_image_lock (klass->image);
9360 if (!klass->ext->field_def_values)
9361 klass->ext->field_def_values = field_def_values;
9362 mono_image_unlock (klass->image);
9365 field_index = mono_field_get_index (field);
9367 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9368 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9370 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9371 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9374 return klass->ext->field_def_values [field_index].data;
9378 * mono_field_get_data;
9379 * @field: the MonoClassField to act on
9381 * Returns: pointer to the metadata constant value or to the field
9382 * data if it has an RVA flag.
9385 mono_field_get_data (MonoClassField *field)
9387 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9388 MonoTypeEnum def_type;
9390 return mono_class_get_field_default_value (field, &def_type);
9391 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9392 return mono_field_get_rva (field);
9399 * mono_property_get_name:
9400 * @prop: the MonoProperty to act on
9402 * Returns: the name of the property
9405 mono_property_get_name (MonoProperty *prop)
9411 * mono_property_get_set_method
9412 * @prop: the MonoProperty to act on.
9414 * Returns: the setter method of the property (A MonoMethod)
9417 mono_property_get_set_method (MonoProperty *prop)
9423 * mono_property_get_get_method
9424 * @prop: the MonoProperty to act on.
9426 * Returns: the setter method of the property (A MonoMethod)
9429 mono_property_get_get_method (MonoProperty *prop)
9435 * mono_property_get_parent:
9436 * @prop: the MonoProperty to act on.
9438 * Returns: the MonoClass where the property was defined.
9441 mono_property_get_parent (MonoProperty *prop)
9443 return prop->parent;
9447 * mono_property_get_flags:
9448 * @prop: the MonoProperty to act on.
9450 * The metadata flags for a property are encoded using the
9451 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9453 * Returns: the flags for the property.
9456 mono_property_get_flags (MonoProperty *prop)
9462 * mono_event_get_name:
9463 * @event: the MonoEvent to act on
9465 * Returns: the name of the event.
9468 mono_event_get_name (MonoEvent *event)
9474 * mono_event_get_add_method:
9475 * @event: The MonoEvent to act on.
9477 * Returns: the @add' method for the event (a MonoMethod).
9480 mono_event_get_add_method (MonoEvent *event)
9486 * mono_event_get_remove_method:
9487 * @event: The MonoEvent to act on.
9489 * Returns: the @remove method for the event (a MonoMethod).
9492 mono_event_get_remove_method (MonoEvent *event)
9494 return event->remove;
9498 * mono_event_get_raise_method:
9499 * @event: The MonoEvent to act on.
9501 * Returns: the @raise method for the event (a MonoMethod).
9504 mono_event_get_raise_method (MonoEvent *event)
9506 return event->raise;
9510 * mono_event_get_parent:
9511 * @event: the MonoEvent to act on.
9513 * Returns: the MonoClass where the event is defined.
9516 mono_event_get_parent (MonoEvent *event)
9518 return event->parent;
9522 * mono_event_get_flags
9523 * @event: the MonoEvent to act on.
9525 * The metadata flags for an event are encoded using the
9526 * EVENT_* constants. See the tabledefs.h file for details.
9528 * Returns: the flags for the event.
9531 mono_event_get_flags (MonoEvent *event)
9533 return event->attrs;
9537 * mono_class_get_method_from_name:
9538 * @klass: where to look for the method
9539 * @name: name of the method
9540 * @param_count: number of parameters. -1 for any number.
9542 * Obtains a MonoMethod with a given name and number of parameters.
9543 * It only works if there are no multiple signatures for any given method name.
9546 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9548 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9552 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9554 MonoMethod *res = NULL;
9557 /* Search directly in the metadata to avoid calling setup_methods () */
9558 for (i = 0; i < klass->method.count; ++i) {
9560 guint32 cols [MONO_METHOD_SIZE];
9562 MonoMethodSignature *sig;
9564 /* class->method.first points into the methodptr table */
9565 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9567 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9568 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9570 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9573 if (param_count == -1) {
9577 sig = mono_method_signature_checked (method, &error);
9579 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9582 if (sig->param_count == param_count) {
9593 * mono_class_get_method_from_name_flags:
9594 * @klass: where to look for the method
9595 * @name_space: name of the method
9596 * @param_count: number of parameters. -1 for any number.
9597 * @flags: flags which must be set in the method
9599 * Obtains a MonoMethod with a given name and number of parameters.
9600 * It only works if there are no multiple signatures for any given method name.
9603 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9605 MonoMethod *res = NULL;
9608 mono_class_init (klass);
9610 if (klass->generic_class && !klass->methods) {
9611 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9614 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9615 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9620 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9621 mono_class_setup_methods (klass);
9623 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9624 See mono/tests/array_load_exception.il
9625 FIXME we should better report this error to the caller
9627 if (!klass->methods)
9629 for (i = 0; i < klass->method.count; ++i) {
9630 MonoMethod *method = klass->methods [i];
9632 if (method->name[0] == name [0] &&
9633 !strcmp (name, method->name) &&
9634 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9635 ((method->flags & flags) == flags)) {
9642 res = find_method_in_metadata (klass, name, param_count, flags);
9649 * mono_class_set_failure:
9650 * @klass: class in which the failure was detected
9651 * @ex_type: the kind of exception/error to be thrown (later)
9652 * @ex_data: exception data (specific to each type of exception/error)
9654 * Keep a detected failure informations in the class for later processing.
9655 * Note that only the first failure is kept.
9657 * LOCKING: Acquires the loader lock.
9660 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9662 if (klass->exception_type)
9665 mono_loader_lock ();
9666 klass->exception_type = ex_type;
9668 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9669 mono_loader_unlock ();
9675 * mono_class_get_exception_data:
9677 * Return the exception_data property of KLASS.
9679 * LOCKING: Acquires the loader lock.
9682 mono_class_get_exception_data (MonoClass *klass)
9684 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9688 * mono_classes_init:
9690 * Initialize the resources used by this module.
9693 mono_classes_init (void)
9695 mono_mutex_init (&classes_mutex);
9697 mono_counters_register ("Inflated methods size",
9698 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9699 mono_counters_register ("Inflated classes",
9700 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9701 mono_counters_register ("Inflated classes size",
9702 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9703 mono_counters_register ("MonoClass size",
9704 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9705 mono_counters_register ("MonoClassExt size",
9706 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9710 * mono_classes_cleanup:
9712 * Free the resources used by this module.
9715 mono_classes_cleanup (void)
9717 if (global_interface_bitset)
9718 mono_bitset_free (global_interface_bitset);
9719 global_interface_bitset = NULL;
9720 mono_mutex_destroy (&classes_mutex);
9724 * mono_class_get_exception_for_failure:
9725 * @klass: class in which the failure was detected
9727 * Return a constructed MonoException than the caller can then throw
9728 * using mono_raise_exception - or NULL if no failure is present (or
9729 * doesn't result in an exception).
9732 mono_class_get_exception_for_failure (MonoClass *klass)
9734 gpointer exception_data = mono_class_get_exception_data (klass);
9736 switch (klass->exception_type) {
9737 #ifndef DISABLE_SECURITY
9738 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9739 MonoDomain *domain = mono_domain_get ();
9740 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9741 MonoMethod *method = exception_data;
9742 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9743 MonoObject *exc = NULL;
9747 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9748 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9749 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9751 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9752 return (MonoException*) exc;
9755 case MONO_EXCEPTION_TYPE_LOAD: {
9758 char *str = mono_type_get_full_name (klass);
9759 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9760 name = mono_string_new (mono_domain_get (), str);
9762 ex = mono_get_exception_type_load (name, astr);
9766 case MONO_EXCEPTION_MISSING_METHOD: {
9767 char *class_name = exception_data;
9768 char *assembly_name = class_name + strlen (class_name) + 1;
9770 return mono_get_exception_missing_method (class_name, assembly_name);
9772 case MONO_EXCEPTION_MISSING_FIELD: {
9773 char *class_name = exception_data;
9774 char *member_name = class_name + strlen (class_name) + 1;
9776 return mono_get_exception_missing_field (class_name, member_name);
9778 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9779 char *msg_format = exception_data;
9780 char *assembly_name = msg_format + strlen (msg_format) + 1;
9781 char *msg = g_strdup_printf (msg_format, assembly_name);
9784 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9790 case MONO_EXCEPTION_BAD_IMAGE: {
9791 return mono_get_exception_bad_image_format (exception_data);
9794 MonoLoaderError *error;
9797 error = mono_loader_get_last_error ();
9799 ex = mono_loader_error_prepare_exception (error);
9803 /* TODO - handle other class related failures */
9810 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9812 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9813 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9815 if (outer_klass == inner_klass)
9817 inner_klass = inner_klass->nested_in;
9818 } while (inner_klass);
9823 mono_class_get_generic_type_definition (MonoClass *klass)
9825 return klass->generic_class ? klass->generic_class->container_class : klass;
9829 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9831 * Generic instantiations are ignored for all super types of @klass.
9833 * Visibility checks ignoring generic instantiations.
9836 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9839 klass = mono_class_get_generic_type_definition (klass);
9840 parent = mono_class_get_generic_type_definition (parent);
9841 mono_class_setup_supertypes (klass);
9843 for (i = 0; i < klass->idepth; ++i) {
9844 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9850 * Subtype can only access parent members with family protection if the site object
9851 * is subclass of Subtype. For example:
9852 * class A { protected int x; }
9854 * void valid_access () {
9858 * void invalid_access () {
9865 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9867 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9870 if (context_klass == NULL)
9872 /*if access_klass is not member_klass context_klass must be type compat*/
9873 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9879 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9882 if (accessing == accessed)
9884 if (!accessed || !accessing)
9887 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9888 * anywhere so untrusted friends are not safe to access platform's code internals */
9889 if (mono_security_core_clr_enabled ()) {
9890 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9894 mono_assembly_load_friends (accessed);
9895 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9896 MonoAssemblyName *friend = tmp->data;
9897 /* Be conservative with checks */
9900 if (strcmp (accessing->aname.name, friend->name))
9902 if (friend->public_key_token [0]) {
9903 if (!accessing->aname.public_key_token [0])
9905 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9914 * If klass is a generic type or if it is derived from a generic type, return the
9915 * MonoClass of the generic definition
9916 * Returns NULL if not found
9919 get_generic_definition_class (MonoClass *klass)
9922 if (klass->generic_class && klass->generic_class->container_class)
9923 return klass->generic_class->container_class;
9924 klass = klass->parent;
9930 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9933 for (i = 0; i < ginst->type_argc; ++i) {
9934 MonoType *type = ginst->type_argv[i];
9935 switch (type->type) {
9936 case MONO_TYPE_SZARRAY:
9937 if (!can_access_type (access_klass, type->data.klass))
9940 case MONO_TYPE_ARRAY:
9941 if (!can_access_type (access_klass, type->data.array->eklass))
9945 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9948 case MONO_TYPE_CLASS:
9949 case MONO_TYPE_VALUETYPE:
9950 case MONO_TYPE_GENERICINST:
9951 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9961 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9965 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9968 if (access_klass->element_class && !access_klass->enumtype)
9969 access_klass = access_klass->element_class;
9971 if (member_klass->element_class && !member_klass->enumtype)
9972 member_klass = member_klass->element_class;
9974 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9976 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9979 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9982 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9985 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9988 /*Non nested type with nested visibility. We just fail it.*/
9989 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9992 switch (access_level) {
9993 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9994 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9996 case TYPE_ATTRIBUTE_PUBLIC:
9999 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10002 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10003 return is_nesting_type (member_klass, access_klass);
10005 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10006 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10008 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10009 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10011 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10012 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10013 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10015 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10016 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10017 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10022 /* FIXME: check visibility of type, too */
10024 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10026 MonoClass *member_generic_def;
10027 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10030 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10031 access_klass->generic_container) &&
10032 (member_generic_def = get_generic_definition_class (member_klass))) {
10033 MonoClass *access_container;
10035 if (access_klass->generic_container)
10036 access_container = access_klass;
10038 access_container = access_klass->generic_class->container_class;
10040 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10044 /* Partition I 8.5.3.2 */
10045 /* the access level values are the same for fields and methods */
10046 switch (access_level) {
10047 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10048 /* same compilation unit */
10049 return access_klass->image == member_klass->image;
10050 case FIELD_ATTRIBUTE_PRIVATE:
10051 return access_klass == member_klass;
10052 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10053 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10054 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10057 case FIELD_ATTRIBUTE_ASSEMBLY:
10058 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10059 case FIELD_ATTRIBUTE_FAMILY:
10060 if (is_valid_family_access (access_klass, member_klass, context_klass))
10063 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10064 if (is_valid_family_access (access_klass, member_klass, context_klass))
10066 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10067 case FIELD_ATTRIBUTE_PUBLIC:
10074 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10076 /* FIXME: check all overlapping fields */
10077 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10079 MonoClass *nested = method->klass->nested_in;
10081 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10084 nested = nested->nested_in;
10091 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10093 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10095 MonoClass *nested = method->klass->nested_in;
10097 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10100 nested = nested->nested_in;
10105 * with generics calls to explicit interface implementations can be expressed
10106 * directly: the method is private, but we must allow it. This may be opening
10107 * a hole or the generics code should handle this differently.
10108 * Maybe just ensure the interface type is public.
10110 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10116 * mono_method_can_access_method_full:
10117 * @method: The caller method
10118 * @called: The called method
10119 * @context_klass: The static type on stack of the owner @called object used
10121 * This function must be used with instance calls, as they have more strict family accessibility.
10122 * It can be used with static methods, but context_klass should be NULL.
10124 * Returns: TRUE if caller have proper visibility and acessibility to @called
10127 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10129 MonoClass *access_class = method->klass;
10130 MonoClass *member_class = called->klass;
10131 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10133 MonoClass *nested = access_class->nested_in;
10135 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10138 nested = nested->nested_in;
10145 can = can_access_type (access_class, member_class);
10147 MonoClass *nested = access_class->nested_in;
10149 can = can_access_type (nested, member_class);
10152 nested = nested->nested_in;
10159 if (called->is_inflated) {
10160 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10161 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10170 * mono_method_can_access_field_full:
10171 * @method: The caller method
10172 * @field: The accessed field
10173 * @context_klass: The static type on stack of the owner @field object used
10175 * This function must be used with instance fields, as they have more strict family accessibility.
10176 * It can be used with static fields, but context_klass should be NULL.
10178 * Returns: TRUE if caller have proper visibility and acessibility to @field
10181 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10183 MonoClass *access_class = method->klass;
10184 MonoClass *member_class = field->parent;
10185 /* FIXME: check all overlapping fields */
10186 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10188 MonoClass *nested = access_class->nested_in;
10190 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10193 nested = nested->nested_in;
10200 can = can_access_type (access_class, member_class);
10202 MonoClass *nested = access_class->nested_in;
10204 can = can_access_type (nested, member_class);
10207 nested = nested->nested_in;
10217 * mono_class_can_access_class:
10218 * @source_class: The source class
10219 * @target_class: The accessed class
10221 * This function returns is @target_class is visible to @source_class
10223 * Returns: TRUE if source have proper visibility and acessibility to target
10226 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10228 return can_access_type (source_class, target_class);
10232 * mono_type_is_valid_enum_basetype:
10233 * @type: The MonoType to check
10235 * Returns: TRUE if the type can be used as the basetype of an enum
10237 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10238 switch (type->type) {
10241 case MONO_TYPE_BOOLEAN:
10244 case MONO_TYPE_CHAR:
10258 * mono_class_is_valid_enum:
10259 * @klass: An enum class to be validated
10261 * This method verify the required properties an enum should have.
10263 * Returns: TRUE if the informed enum class is valid
10265 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10266 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10267 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10269 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10270 MonoClassField * field;
10271 gpointer iter = NULL;
10272 gboolean found_base_field = FALSE;
10274 g_assert (klass->enumtype);
10275 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10276 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10280 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10283 while ((field = mono_class_get_fields (klass, &iter))) {
10284 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10285 if (found_base_field)
10287 found_base_field = TRUE;
10288 if (!mono_type_is_valid_enum_basetype (field->type))
10293 if (!found_base_field)
10296 if (klass->method.count > 0)
10303 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10305 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10309 * mono_class_setup_interface_id:
10311 * Initializes MonoClass::interface_id if required.
10313 * LOCKING: Acquires the loader lock.
10316 mono_class_setup_interface_id (MonoClass *class)
10318 mono_loader_lock ();
10319 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10320 class->interface_id = mono_get_unique_iid (class);
10321 mono_loader_unlock ();
10325 * mono_class_alloc_ext:
10327 * Allocate klass->ext if not already done.
10330 mono_class_alloc_ext (MonoClass *klass)
10337 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10338 mono_image_lock (klass->image);
10339 mono_memory_barrier ();
10342 class_ext_size += sizeof (MonoClassExt);
10343 mono_image_unlock (klass->image);
10347 * mono_class_setup_interfaces:
10349 * Initialize class->interfaces/interfaces_count.
10350 * LOCKING: Acquires the loader lock.
10351 * This function can fail the type.
10354 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10356 int i, interface_count;
10357 MonoClass **interfaces;
10359 mono_error_init (error);
10361 if (klass->interfaces_inited)
10364 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10365 MonoType *args [1];
10367 /* generic IList, ICollection, IEnumerable */
10368 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10369 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10371 args [0] = &klass->element_class->byval_arg;
10372 interfaces [0] = mono_class_bind_generic_parameters (
10373 mono_defaults.generic_ilist_class, 1, args, FALSE);
10374 if (interface_count > 1)
10375 interfaces [1] = mono_class_bind_generic_parameters (
10376 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10377 } else if (klass->generic_class) {
10378 MonoClass *gklass = klass->generic_class->container_class;
10380 mono_class_setup_interfaces (gklass, error);
10381 if (!mono_error_ok (error)) {
10382 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10386 interface_count = gklass->interface_count;
10387 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10388 for (i = 0; i < interface_count; i++) {
10389 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10390 if (!mono_error_ok (error)) {
10391 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10396 interface_count = 0;
10400 mono_image_lock (klass->image);
10402 if (!klass->interfaces_inited) {
10403 klass->interface_count = interface_count;
10404 klass->interfaces = interfaces;
10406 mono_memory_barrier ();
10408 klass->interfaces_inited = TRUE;
10411 mono_image_unlock (klass->image);
10415 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10417 MonoClass *class = field->parent;
10418 MonoImage *image = class->image;
10419 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10420 int field_idx = field - class->fields;
10422 mono_error_init (error);
10425 MonoClassField *gfield = >d->fields [field_idx];
10426 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10427 if (!mono_error_ok (error)) {
10428 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10429 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10433 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10434 if (!mono_error_ok (error)) {
10435 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10436 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10441 guint32 cols [MONO_FIELD_SIZE];
10442 MonoGenericContainer *container = NULL;
10443 int idx = class->field.first + field_idx;
10445 /*FIXME, in theory we do not lazy load SRE fields*/
10446 g_assert (!image_is_dynamic (image));
10448 if (class->generic_container) {
10449 container = class->generic_container;
10451 container = gtd->generic_container;
10452 g_assert (container);
10455 /* class->field.first and idx points into the fieldptr table */
10456 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10458 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10459 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10460 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10464 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10466 mono_metadata_decode_value (sig, &sig);
10467 /* FIELD signature == 0x06 */
10468 g_assert (*sig == 0x06);
10469 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10471 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10476 mono_field_resolve_flags (MonoClassField *field)
10478 MonoClass *class = field->parent;
10479 MonoImage *image = class->image;
10480 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10481 int field_idx = field - class->fields;
10485 MonoClassField *gfield = >d->fields [field_idx];
10486 return mono_field_get_flags (gfield);
10488 int idx = class->field.first + field_idx;
10490 /*FIXME, in theory we do not lazy load SRE fields*/
10491 g_assert (!image_is_dynamic (image));
10493 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10498 * mono_class_setup_basic_field_info:
10499 * @class: The class to initialize
10501 * Initializes the class->fields array of fields.
10502 * Aquires the loader lock.
10505 mono_class_setup_basic_field_info_locking (MonoClass *class)
10507 mono_loader_lock ();
10508 mono_class_setup_basic_field_info (class);
10509 mono_loader_unlock ();
10513 * mono_class_get_fields_lazy:
10514 * @klass: the MonoClass to act on
10516 * This routine is an iterator routine for retrieving the fields in a class.
10517 * Only minimal information about fields are loaded. Accessors must be used
10518 * for all MonoClassField returned.
10520 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10521 * iterate over all of the elements. When no more values are
10522 * available, the return value is NULL.
10524 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10527 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10529 MonoClassField* field;
10533 mono_class_setup_basic_field_info_locking (klass);
10534 if (!klass->fields)
10536 /* start from the first */
10537 if (klass->field.count) {
10538 return *iter = &klass->fields [0];
10546 if (field < &klass->fields [klass->field.count]) {
10547 return *iter = field;
10553 mono_class_full_name (MonoClass *klass)
10555 return mono_type_full_name (&klass->byval_arg);