2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
50 gboolean mono_align_small_structs = FALSE;
53 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
54 guint32 classes_size, class_ext_size;
56 /* Low level lock which protects data structures in this module */
57 static mono_mutex_t classes_mutex;
59 /* Function supplied by the runtime to find classes by name using information from the AOT file */
60 static MonoGetClassFromName get_class_from_name = NULL;
62 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
63 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
64 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
65 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
66 static int generic_array_methods (MonoClass *class);
67 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
69 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
70 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
71 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
72 static guint32 mono_field_resolve_flags (MonoClassField *field);
73 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
74 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation;
100 static GSList *gclass_recorded_list;
101 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
106 mono_locks_acquire (&classes_mutex, ClassesLock);
110 classes_unlock (void)
112 mono_locks_release (&classes_mutex, ClassesLock);
116 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
119 enable_gclass_recording (void)
121 ++record_gclass_instantiation;
125 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
128 disable_gclass_recording (gclass_record_func func, void *user_data)
130 GSList **head = &gclass_recorded_list;
132 g_assert (record_gclass_instantiation > 0);
133 --record_gclass_instantiation;
136 GSList *node = *head;
137 if (func ((MonoClass*)node->data, user_data)) {
139 g_slist_free_1 (node);
145 /* We automatically discard all recorded gclasses when disabled. */
146 if (!record_gclass_instantiation && gclass_recorded_list) {
147 g_slist_free (gclass_recorded_list);
148 gclass_recorded_list = NULL;
153 * mono_class_from_typeref:
154 * @image: a MonoImage
155 * @type_token: a TypeRef token
157 * Creates the MonoClass* structure representing the type defined by
158 * the typeref token valid inside @image.
159 * Returns: the MonoClass* representing the typeref token, NULL ifcould
163 mono_class_from_typeref (MonoImage *image, guint32 type_token)
166 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
167 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
172 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
174 guint32 cols [MONO_TYPEREF_SIZE];
175 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
177 const char *name, *nspace;
178 MonoClass *res = NULL;
181 mono_error_init (error);
183 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
186 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
188 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
189 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
191 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
192 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
193 case MONO_RESOLUTION_SCOPE_MODULE:
195 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
196 This is not the observed behavior of existing implementations.
197 The defacto behavior is that it's just a typedef in disguise.
199 /* a typedef in disguise */
200 res = mono_class_from_name_checked (image, nspace, name, error);
203 case MONO_RESOLUTION_SCOPE_MODULEREF:
204 module = mono_image_load_module (image, idx);
206 res = mono_class_from_name_checked (module, nspace, name, error);
209 case MONO_RESOLUTION_SCOPE_TYPEREF: {
210 MonoClass *enclosing;
213 if (idx == mono_metadata_token_index (type_token)) {
214 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
218 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
219 if (!mono_error_ok (error))
222 if (enclosing->nested_classes_inited && enclosing->ext) {
223 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
224 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
226 if (strcmp (res->name, name) == 0)
230 /* Don't call mono_class_init as we might've been called by it recursively */
231 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
233 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
234 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
235 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
237 if (strcmp (nname, name) == 0)
238 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
240 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
243 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
246 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
250 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
251 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
255 if (!image->references || !image->references [idx - 1])
256 mono_assembly_load_reference (image, idx - 1);
257 g_assert (image->references [idx - 1]);
259 /* If the assembly did not load, register this as a type load exception */
260 if (image->references [idx - 1] == REFERENCE_MISSING){
261 MonoAssemblyName aname;
264 mono_assembly_get_assemblyref (image, idx - 1, &aname);
265 human_name = mono_stringify_assembly_name (&aname);
266 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
270 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
273 /* Generic case, should be avoided for when a better error is possible. */
274 if (!res && mono_error_ok (error)) {
275 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
276 mono_error_set_from_loader_error (error);
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
283 g_assert (!mono_loader_get_last_error ());
289 mono_image_memdup (MonoImage *image, void *data, guint size)
291 void *res = mono_image_alloc (image, size);
292 memcpy (res, data, size);
296 /* Copy everything mono_metadata_free_array free. */
298 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
301 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
303 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
307 a = g_memdup (a, sizeof (MonoArrayType));
309 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
311 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
316 /* Copy everything mono_metadata_free_method_signature free. */
318 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
322 sig = mono_metadata_signature_dup_full (image, sig);
324 sig->ret = mono_metadata_type_dup (image, sig->ret);
325 for (i = 0; i < sig->param_count; ++i)
326 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
332 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
334 MonoAssembly *ta = klass->image->assembly;
337 name = mono_stringify_assembly_name (&ta->aname);
338 g_string_append_printf (str, ", %s", name);
343 mono_type_name_check_byref (MonoType *type, GString *str)
346 g_string_append_c (str, '&');
350 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
351 MonoTypeNameFormat format)
355 switch (type->type) {
356 case MONO_TYPE_ARRAY: {
357 int i, rank = type->data.array->rank;
358 MonoTypeNameFormat nested_format;
360 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
361 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
363 mono_type_get_name_recurse (
364 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
365 g_string_append_c (str, '[');
367 g_string_append_c (str, '*');
368 for (i = 1; i < rank; i++)
369 g_string_append_c (str, ',');
370 g_string_append_c (str, ']');
372 mono_type_name_check_byref (type, str);
374 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
375 _mono_type_get_assembly_name (type->data.array->eklass, str);
378 case MONO_TYPE_SZARRAY: {
379 MonoTypeNameFormat nested_format;
381 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
382 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
384 mono_type_get_name_recurse (
385 &type->data.klass->byval_arg, str, FALSE, nested_format);
386 g_string_append (str, "[]");
388 mono_type_name_check_byref (type, str);
390 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
391 _mono_type_get_assembly_name (type->data.klass, str);
394 case MONO_TYPE_PTR: {
395 MonoTypeNameFormat nested_format;
397 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
398 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
400 mono_type_get_name_recurse (
401 type->data.type, str, FALSE, nested_format);
402 g_string_append_c (str, '*');
404 mono_type_name_check_byref (type, str);
406 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
407 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
412 if (!mono_generic_param_info (type->data.generic_param))
413 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
415 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
417 mono_type_name_check_byref (type, str);
421 klass = mono_class_from_mono_type (type);
422 if (klass->nested_in) {
423 mono_type_get_name_recurse (
424 &klass->nested_in->byval_arg, str, TRUE, format);
425 if (format == MONO_TYPE_NAME_FORMAT_IL)
426 g_string_append_c (str, '.');
428 g_string_append_c (str, '+');
429 } else if (*klass->name_space) {
430 g_string_append (str, klass->name_space);
431 g_string_append_c (str, '.');
433 if (format == MONO_TYPE_NAME_FORMAT_IL) {
434 char *s = strchr (klass->name, '`');
435 int len = s ? s - klass->name : strlen (klass->name);
437 g_string_append_len (str, klass->name, len);
439 g_string_append (str, klass->name);
442 if (klass->generic_class) {
443 MonoGenericClass *gclass = klass->generic_class;
444 MonoGenericInst *inst = gclass->context.class_inst;
445 MonoTypeNameFormat nested_format;
448 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
449 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
451 if (format == MONO_TYPE_NAME_FORMAT_IL)
452 g_string_append_c (str, '<');
454 g_string_append_c (str, '[');
455 for (i = 0; i < inst->type_argc; i++) {
456 MonoType *t = inst->type_argv [i];
459 g_string_append_c (str, ',');
460 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
461 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
462 g_string_append_c (str, '[');
463 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
464 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
465 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
466 g_string_append_c (str, ']');
468 if (format == MONO_TYPE_NAME_FORMAT_IL)
469 g_string_append_c (str, '>');
471 g_string_append_c (str, ']');
472 } else if (klass->generic_container &&
473 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
474 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
477 if (format == MONO_TYPE_NAME_FORMAT_IL)
478 g_string_append_c (str, '<');
480 g_string_append_c (str, '[');
481 for (i = 0; i < klass->generic_container->type_argc; i++) {
483 g_string_append_c (str, ',');
484 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
486 if (format == MONO_TYPE_NAME_FORMAT_IL)
487 g_string_append_c (str, '>');
489 g_string_append_c (str, ']');
492 mono_type_name_check_byref (type, str);
494 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
495 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
496 _mono_type_get_assembly_name (klass, str);
502 * mono_type_get_name_full:
504 * @format: the format for the return string.
507 * Returns: the string representation in a number of formats:
509 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
510 * returned in the formatrequired by System.Reflection, this is the
511 * inverse of mono_reflection_parse_type ().
513 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
514 * be used by the IL assembler.
516 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
518 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
521 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
525 result = g_string_new ("");
527 mono_type_get_name_recurse (type, result, FALSE, format);
529 return g_string_free (result, FALSE);
533 * mono_type_get_full_name:
536 * Returns: the string representation for type as required by System.Reflection.
537 * The inverse of mono_reflection_parse_type ().
540 mono_type_get_full_name (MonoClass *class)
542 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
546 * mono_type_get_name:
549 * Returns: the string representation for type as it would be represented in IL code.
552 mono_type_get_name (MonoType *type)
554 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
558 * mono_type_get_underlying_type:
561 * Returns: the MonoType for the underlying integer type if @type
562 * is an enum and byref is false, otherwise the type itself.
565 mono_type_get_underlying_type (MonoType *type)
567 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.klass);
569 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
570 return mono_class_enum_basetype (type->data.generic_class->container_class);
575 * mono_class_is_open_constructed_type:
578 * Returns TRUE if type represents a generics open constructed type.
579 * IOW, not all type parameters required for the instantiation have
580 * been provided or it's a generic type definition.
582 * An open constructed type means it's a non realizable type. Not to
583 * be mixed up with an abstract type - we can't cast or dispatch to
584 * an open type, for example.
587 mono_class_is_open_constructed_type (MonoType *t)
593 case MONO_TYPE_SZARRAY:
594 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
595 case MONO_TYPE_ARRAY:
596 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
598 return mono_class_is_open_constructed_type (t->data.type);
599 case MONO_TYPE_GENERICINST:
600 return t->data.generic_class->context.class_inst->is_open;
601 case MONO_TYPE_CLASS:
602 case MONO_TYPE_VALUETYPE:
603 return t->data.klass->generic_container != NULL;
610 This is a simple function to catch the most common bad instances of generic types.
611 Specially those that might lead to further failures in the runtime.
614 is_valid_generic_argument (MonoType *type)
616 switch (type->type) {
618 //case MONO_TYPE_TYPEDBYREF:
626 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
628 mono_error_init (error);
630 switch (type->type) {
631 case MONO_TYPE_MVAR: {
633 int num = mono_type_get_generic_param_num (type);
634 MonoGenericInst *inst = context->method_inst;
635 if (!inst || !inst->type_argv)
637 if (num >= inst->type_argc) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
640 num, info ? info->name : "", inst->type_argc);
644 if (!is_valid_generic_argument (inst->type_argv [num])) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
647 num, info ? info->name : "", inst->type_argv [num]->type);
651 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
652 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
653 * ->byref and ->attrs from @type are propagated to the returned type.
655 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
656 nt->byref = type->byref;
657 nt->attrs = type->attrs;
660 case MONO_TYPE_VAR: {
662 int num = mono_type_get_generic_param_num (type);
663 MonoGenericInst *inst = context->class_inst;
666 if (num >= inst->type_argc) {
667 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
668 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
669 num, info ? info->name : "", inst->type_argc);
672 if (!is_valid_generic_argument (inst->type_argv [num])) {
673 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
674 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
675 num, info ? info->name : "", inst->type_argv [num]->type);
678 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
679 nt->byref = type->byref;
680 nt->attrs = type->attrs;
683 case MONO_TYPE_SZARRAY: {
684 MonoClass *eclass = type->data.klass;
685 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
686 if (!inflated || !mono_error_ok (error))
688 nt = mono_metadata_type_dup (image, type);
689 nt->data.klass = mono_class_from_mono_type (inflated);
690 mono_metadata_free_type (inflated);
693 case MONO_TYPE_ARRAY: {
694 MonoClass *eclass = type->data.array->eklass;
695 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
696 if (!inflated || !mono_error_ok (error))
698 nt = mono_metadata_type_dup (image, type);
699 nt->data.array->eklass = mono_class_from_mono_type (inflated);
700 mono_metadata_free_type (inflated);
703 case MONO_TYPE_GENERICINST: {
704 MonoGenericClass *gclass = type->data.generic_class;
705 MonoGenericInst *inst;
707 if (!gclass->context.class_inst->is_open)
710 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
711 if (!mono_error_ok (error))
713 if (inst != gclass->context.class_inst)
714 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
716 if (gclass == type->data.generic_class)
719 nt = mono_metadata_type_dup (image, type);
720 nt->data.generic_class = gclass;
723 case MONO_TYPE_CLASS:
724 case MONO_TYPE_VALUETYPE: {
725 MonoClass *klass = type->data.klass;
726 MonoGenericContainer *container = klass->generic_container;
727 MonoGenericInst *inst;
728 MonoGenericClass *gclass = NULL;
734 /* We can't use context->class_inst directly, since it can have more elements */
735 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
736 if (!mono_error_ok (error))
738 if (inst == container->context.class_inst)
741 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
743 nt = mono_metadata_type_dup (image, type);
744 nt->type = MONO_TYPE_GENERICINST;
745 nt->data.generic_class = gclass;
755 mono_generic_class_get_context (MonoGenericClass *gclass)
757 return &gclass->context;
761 mono_class_get_context (MonoClass *class)
763 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
767 * mono_class_get_generic_container:
769 * Return the generic container of KLASS which should be a generic type definition.
771 MonoGenericContainer*
772 mono_class_get_generic_container (MonoClass *klass)
774 g_assert (klass->is_generic);
776 return klass->generic_container;
780 * mono_class_get_generic_class:
782 * Return the MonoGenericClass of KLASS, which should be a generic instance.
785 mono_class_get_generic_class (MonoClass *klass)
787 g_assert (klass->is_inflated);
789 return klass->generic_class;
793 * mono_class_inflate_generic_type_with_mempool:
794 * @mempool: a mempool
796 * @context: a generics context
797 * @error: error context
799 * The same as mono_class_inflate_generic_type, but allocates the MonoType
800 * from mempool if it is non-NULL. If it is NULL, the MonoType is
801 * allocated on the heap and is owned by the caller.
802 * The returned type can potentially be the same as TYPE, so it should not be
803 * modified by the caller, and it should be freed using mono_metadata_free_type ().
806 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
808 MonoType *inflated = NULL;
809 mono_error_init (error);
812 inflated = inflate_generic_type (image, type, context, error);
813 if (!mono_error_ok (error))
817 MonoType *shared = mono_metadata_get_shared_type (type);
822 return mono_metadata_type_dup (image, type);
826 mono_stats.inflated_type_count++;
831 * mono_class_inflate_generic_type:
833 * @context: a generics context
835 * If @type is a generic type and @context is not NULL, instantiate it using the
836 * generics context @context.
838 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
839 * on the heap and is owned by the caller. Returns NULL on error.
841 * @deprecated Please use mono_class_inflate_generic_type_checked instead
844 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
848 result = mono_class_inflate_generic_type_checked (type, context, &error);
850 if (!mono_error_ok (&error)) {
851 mono_error_cleanup (&error);
858 * mono_class_inflate_generic_type:
860 * @context: a generics context
861 * @error: error context to use
863 * If @type is a generic type and @context is not NULL, instantiate it using the
864 * generics context @context.
866 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
867 * on the heap and is owned by the caller.
870 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
872 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
876 * mono_class_inflate_generic_type_no_copy:
878 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
882 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
884 MonoType *inflated = NULL;
886 mono_error_init (error);
888 inflated = inflate_generic_type (image, type, context, error);
889 if (!mono_error_ok (error))
896 mono_stats.inflated_type_count++;
901 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
906 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
907 if (!mono_error_ok (error))
910 res = mono_class_from_mono_type (inflated);
911 mono_metadata_free_type (inflated);
916 * mono_class_inflate_generic_class:
918 * Inflate the class GKLASS with CONTEXT.
921 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
926 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
927 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
934 static MonoGenericContext
935 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
937 MonoGenericInst *class_inst = NULL;
938 MonoGenericInst *method_inst = NULL;
939 MonoGenericContext res = { NULL, NULL };
941 mono_error_init (error);
943 if (context->class_inst) {
944 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
945 if (!mono_error_ok (error))
949 if (context->method_inst) {
950 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
951 if (!mono_error_ok (error))
955 res.class_inst = class_inst;
956 res.method_inst = method_inst;
962 * mono_class_inflate_generic_method:
963 * @method: a generic method
964 * @context: a generics context
966 * Instantiate the generic method @method using the generics context @context.
968 * Returns: the new instantiated method
971 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
973 return mono_class_inflate_generic_method_full (method, NULL, context);
977 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
979 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
983 * mono_class_inflate_generic_method_full:
985 * Instantiate method @method with the generic context @context.
986 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
987 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
990 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
993 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
994 if (!mono_error_ok (&error))
995 /*FIXME do proper error handling - on this case, kill this function. */
996 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1002 * mono_class_inflate_generic_method_full_checked:
1003 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1006 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1009 MonoMethodInflated *iresult, *cached;
1010 MonoMethodSignature *sig;
1011 MonoGenericContext tmp_context;
1012 gboolean is_mb_open = FALSE;
1014 mono_error_init (error);
1016 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1017 while (method->is_inflated) {
1018 MonoGenericContext *method_context = mono_method_get_context (method);
1019 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1021 tmp_context = inflate_generic_context (method_context, context, error);
1022 if (!mono_error_ok (error))
1024 context = &tmp_context;
1026 if (mono_metadata_generic_context_equal (method_context, context))
1029 method = imethod->declaring;
1033 * A method only needs to be inflated if the context has argument for which it is
1036 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1037 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1040 if (!((method->is_generic && context->method_inst) ||
1041 (method->klass->generic_container && context->class_inst)))
1045 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1046 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1047 * This is opposite to the way non-SRE MethodInfos behave.
1049 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1051 * void Example<T> () {
1055 * In Example, the method token must be encoded as: "void Example<!!0>()"
1057 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1058 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1060 * On the other hand, inflating a non-SRE generic method with its own arguments should
1061 * return itself. For example:
1063 * MethodInfo m = ... //m is a generic method definition
1064 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1067 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1068 * what happens with regular methods.
1070 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1071 * everything should behave like a regular type or method.
1074 is_mb_open = method->is_generic &&
1075 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1076 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1078 iresult = g_new0 (MonoMethodInflated, 1);
1079 iresult->context = *context;
1080 iresult->declaring = method;
1081 iresult->method.method.is_mb_open = is_mb_open;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 /* This can happen with some callers like mono_object_get_virtual_method () */
1094 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = NULL;
1097 cached = mono_method_inflated_lookup (iresult, FALSE);
1100 return (MonoMethod*)cached;
1103 mono_stats.inflated_method_count++;
1105 inflated_methods_size += sizeof (MonoMethodInflated);
1107 sig = mono_method_signature (method);
1109 char *name = mono_type_get_full_name (method->klass);
1110 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1116 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1118 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1121 result = (MonoMethod *) iresult;
1122 result->is_inflated = TRUE;
1123 result->is_generic = FALSE;
1124 result->sre_method = FALSE;
1125 result->signature = NULL;
1126 result->is_mb_open = is_mb_open;
1128 if (!context->method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1138 if (!klass_hint || !klass_hint->generic_class ||
1139 klass_hint->generic_class->container_class != method->klass ||
1140 klass_hint->generic_class->context.class_inst != context->class_inst)
1143 if (method->klass->generic_container)
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1169 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1177 * mono_get_inflated_method:
1179 * Obsolete. We keep it around since it's mentioned in the public API.
1182 mono_get_inflated_method (MonoMethod *method)
1188 * mono_method_get_context_general:
1190 * @uninflated: handle uninflated methods?
1192 * Returns the generic context of a method or NULL if it doesn't have
1193 * one. For an inflated method that's the context stored in the
1194 * method. Otherwise it's in the method's generic container or in the
1195 * generic container of the method's class.
1198 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1200 if (method->is_inflated) {
1201 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1202 return &imethod->context;
1206 if (method->is_generic)
1207 return &(mono_method_get_generic_container (method)->context);
1208 if (method->klass->generic_container)
1209 return &method->klass->generic_container->context;
1214 * mono_method_get_context:
1217 * Returns the generic context for method if it's inflated, otherwise
1221 mono_method_get_context (MonoMethod *method)
1223 return mono_method_get_context_general (method, FALSE);
1227 * mono_method_get_generic_container:
1229 * Returns the generic container of METHOD, which should be a generic method definition.
1230 * Returns NULL if METHOD is not a generic method definition.
1231 * LOCKING: Acquires the loader lock.
1233 MonoGenericContainer*
1234 mono_method_get_generic_container (MonoMethod *method)
1236 MonoGenericContainer *container;
1238 if (!method->is_generic)
1241 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1242 g_assert (container);
1248 * mono_method_set_generic_container:
1250 * Sets the generic container of METHOD to CONTAINER.
1251 * LOCKING: Acquires the image lock.
1254 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1256 g_assert (method->is_generic);
1258 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1262 * mono_class_find_enum_basetype:
1263 * @class: The enum class
1265 * Determine the basetype of an enum by iterating through its fields. We do this
1266 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1269 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1271 MonoGenericContainer *container = NULL;
1272 MonoImage *m = class->image;
1273 const int top = class->field.count;
1276 g_assert (class->enumtype);
1278 mono_error_init (error);
1280 if (class->generic_container)
1281 container = class->generic_container;
1282 else if (class->generic_class) {
1283 MonoClass *gklass = class->generic_class->container_class;
1285 container = gklass->generic_container;
1286 g_assert (container);
1290 * Fetch all the field information.
1292 for (i = 0; i < top; i++){
1294 guint32 cols [MONO_FIELD_SIZE];
1295 int idx = class->field.first + i;
1298 /* class->field.first and idx points into the fieldptr table */
1299 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1301 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1304 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1305 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1309 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1310 mono_metadata_decode_value (sig, &sig);
1311 /* FIELD signature == 0x06 */
1313 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1317 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1319 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1320 mono_error_set_from_loader_error (error);
1322 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1325 if (class->generic_class) {
1326 //FIXME do we leak here?
1327 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1328 if (!mono_error_ok (error))
1330 ftype->attrs = cols [MONO_FIELD_FLAGS];
1335 mono_error_set_type_load_class (error, class, "Could not find base type");
1338 g_assert (!mono_loader_get_last_error ());
1343 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1346 mono_type_has_exceptions (MonoType *type)
1348 switch (type->type) {
1349 case MONO_TYPE_CLASS:
1350 case MONO_TYPE_VALUETYPE:
1351 case MONO_TYPE_SZARRAY:
1352 return type->data.klass->exception_type;
1353 case MONO_TYPE_ARRAY:
1354 return type->data.array->eklass->exception_type;
1355 case MONO_TYPE_GENERICINST:
1356 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1365 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1369 mono_class_alloc (MonoClass *class, int size)
1371 if (class->generic_class)
1372 return mono_image_set_alloc (class->generic_class->owner, size);
1374 return mono_image_alloc (class->image, size);
1378 mono_class_alloc0 (MonoClass *class, int size)
1382 res = mono_class_alloc (class, size);
1383 memset (res, 0, size);
1387 #define mono_class_new0(class,struct_type, n_structs) \
1388 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1391 * mono_class_setup_basic_field_info:
1392 * @class: The class to initialize
1394 * Initializes the class->fields.
1395 * LOCKING: Assumes the loader lock is held.
1398 mono_class_setup_basic_field_info (MonoClass *class)
1400 MonoClassField *field;
1408 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1409 image = class->image;
1410 top = class->field.count;
1412 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1414 * This happens when a generic instance of an unfinished generic typebuilder
1415 * is used as an element type for creating an array type. We can't initialize
1416 * the fields of this class using the fields of gklass, since gklass is not
1417 * finished yet, fields could be added to it later.
1423 mono_class_setup_basic_field_info (gtd);
1425 top = gtd->field.count;
1426 class->field.first = gtd->field.first;
1427 class->field.count = gtd->field.count;
1430 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1433 * Fetch all the field information.
1435 for (i = 0; i < top; i++){
1436 field = &class->fields [i];
1437 field->parent = class;
1440 field->name = mono_field_get_name (>d->fields [i]);
1442 int idx = class->field.first + i;
1443 /* class->field.first and idx points into the fieldptr table */
1444 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1445 /* The name is needed for fieldrefs */
1446 field->name = mono_metadata_string_heap (image, name_idx);
1452 * mono_class_setup_fields:
1453 * @class: The class to initialize
1455 * Initializes the class->fields.
1456 * LOCKING: Assumes the loader lock is held.
1459 mono_class_setup_fields (MonoClass *class)
1462 MonoImage *m = class->image;
1464 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1465 int i, blittable = TRUE;
1466 guint32 real_size = 0;
1467 guint32 packing_size = 0;
1468 gboolean explicit_size;
1469 MonoClassField *field;
1470 MonoGenericContainer *container = NULL;
1471 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1474 * FIXME: We have a race condition here. It's possible that this function returns
1475 * to its caller with `instance_size` set to `0` instead of the actual size. This
1476 * is not a problem when the function is called recursively on the same class,
1477 * because the size will be initialized by the outer invocation. What follows is a
1478 * description of how it can occur in other cases, too. There it is a problem,
1479 * because it can lead to the GC being asked to allocate an object of size `0`,
1480 * which SGen chokes on. The race condition is triggered infrequently by
1481 * `tests/sgen-suspend.cs`.
1483 * This function is called for a class whenever one of its subclasses is inited.
1484 * For example, it's called for every subclass of Object. What it does is this:
1486 * if (class->setup_fields_called)
1489 * class->instance_size = 0;
1491 * class->setup_fields_called = 1;
1492 * ... critical point
1493 * class->instance_size = actual_instance_size;
1495 * The last two steps are sometimes reversed, but that only changes the way in which
1496 * the race condition works.
1498 * Assume thread A goes through this function and makes it to the critical point.
1499 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1500 * immediately, but `instance_size` is incorrect.
1502 * The other case looks like this:
1504 * if (class->setup_fields_called)
1506 * ... critical point X
1507 * class->instance_size = 0;
1508 * ... critical point Y
1509 * class->instance_size = actual_instance_size;
1511 * class->setup_fields_called = 1;
1513 * Assume thread A goes through the function and makes it to critical point X. Now
1514 * thread B runs through the whole of the function, returning, assuming
1515 * `instance_size` is set. At that point thread A gets to run and makes it to
1516 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1519 if (class->setup_fields_called)
1522 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1524 * This happens when a generic instance of an unfinished generic typebuilder
1525 * is used as an element type for creating an array type. We can't initialize
1526 * the fields of this class using the fields of gklass, since gklass is not
1527 * finished yet, fields could be added to it later.
1532 mono_class_setup_basic_field_info (class);
1533 top = class->field.count;
1536 mono_class_setup_fields (gtd);
1537 if (gtd->exception_type) {
1538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1543 class->instance_size = 0;
1545 class->sizes.class_size = 0;
1547 if (class->parent) {
1548 /* For generic instances, class->parent might not have been initialized */
1549 mono_class_init (class->parent);
1550 if (!class->parent->size_inited) {
1551 mono_class_setup_fields (class->parent);
1552 if (class->parent->exception_type) {
1553 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1557 class->instance_size += class->parent->instance_size;
1558 class->min_align = class->parent->min_align;
1559 /* we use |= since it may have been set already */
1560 class->has_references |= class->parent->has_references;
1561 blittable = class->parent->blittable;
1563 class->instance_size = sizeof (MonoObject);
1564 class->min_align = 1;
1567 /* We can't really enable 16 bytes alignment until the GC supports it.
1568 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1569 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1570 Bug #506144 is an example of this issue.
1572 if (class->simd_type)
1573 class->min_align = 16;
1575 /* Get the real size */
1576 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1578 if (explicit_size) {
1579 if ((packing_size & 0xffffff00) != 0) {
1580 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1581 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1584 class->packing_size = packing_size;
1585 real_size += class->instance_size;
1589 if (explicit_size && real_size) {
1590 class->instance_size = MAX (real_size, class->instance_size);
1592 class->blittable = blittable;
1593 mono_memory_barrier ();
1594 class->size_inited = 1;
1595 class->fields_inited = 1;
1596 class->setup_fields_called = 1;
1600 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(class->image == mono_defaults.corlib && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
1603 /* Prevent infinite loops if the class references itself */
1604 class->setup_fields_called = 1;
1606 if (class->generic_container) {
1607 container = class->generic_container;
1609 container = gtd->generic_container;
1610 g_assert (container);
1614 * Fetch all the field information.
1616 for (i = 0; i < top; i++){
1617 int idx = class->field.first + i;
1618 field = &class->fields [i];
1620 field->parent = class;
1623 mono_field_resolve_type (field, &error);
1624 if (!mono_error_ok (&error)) {
1625 /*mono_field_resolve_type already failed class*/
1626 mono_error_cleanup (&error);
1630 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1631 g_assert (field->type);
1634 if (mono_field_is_deleted (field))
1637 MonoClassField *gfield = >d->fields [i];
1638 field->offset = gfield->offset;
1640 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1642 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1643 field->offset = offset;
1645 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1646 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1649 if (field->offset < -1) { /*-1 is used to encode special static fields */
1650 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1653 if (class->generic_container) {
1654 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1660 /* Only do these checks if we still think this type is blittable */
1661 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1665 MonoClass *field_class = mono_class_from_mono_type (field->type);
1667 mono_class_setup_fields (field_class);
1668 if (field_class->exception_type) {
1669 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1673 if (!field_class || !field_class->blittable)
1678 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1679 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1680 blittable = class->element_class->blittable;
1683 if (mono_type_has_exceptions (field->type)) {
1684 char *class_name = mono_type_get_full_name (class);
1685 char *type_name = mono_type_full_name (field->type);
1687 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1689 g_free (class_name);
1693 /* The def_value of fields is compute lazily during vtable creation */
1696 if (class == mono_defaults.string_class)
1699 class->blittable = blittable;
1701 if (class->enumtype && !mono_class_enum_basetype (class)) {
1702 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 if (explicit_size && real_size) {
1706 class->instance_size = MAX (real_size, class->instance_size);
1709 if (class->exception_type)
1711 mono_class_layout_fields (class);
1713 /*valuetypes can't be neither bigger than 1Mb or empty. */
1714 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1715 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1717 mono_memory_barrier ();
1718 class->fields_inited = 1;
1722 * mono_class_setup_fields_locking:
1723 * @class: The class to initialize
1725 * Initializes the class->fields array of fields.
1726 * Aquires the loader lock.
1729 mono_class_setup_fields_locking (MonoClass *class)
1731 /* This can be checked without locks */
1732 if (class->fields_inited)
1734 mono_loader_lock ();
1735 mono_class_setup_fields (class);
1736 mono_loader_unlock ();
1740 * mono_class_has_references:
1742 * Returns whenever @klass->has_references is set, initializing it if needed.
1743 * Aquires the loader lock.
1746 mono_class_has_references (MonoClass *klass)
1748 if (klass->init_pending) {
1749 /* Be conservative */
1752 mono_class_init (klass);
1754 return klass->has_references;
1759 * mono_type_get_basic_type_from_generic:
1762 * Returns a closed type corresponding to the possibly open type
1766 mono_type_get_basic_type_from_generic (MonoType *type)
1768 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1769 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1770 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1771 return &mono_defaults.object_class->byval_arg;
1776 * mono_class_layout_fields:
1779 * Compute the placement of fields inside an object or struct, according to
1780 * the layout rules and set the following fields in @class:
1781 * - has_references (if the class contains instance references firled or structs that contain references)
1782 * - has_static_refs (same, but for static fields)
1783 * - instance_size (size of the object in memory)
1784 * - class_size (size needed for the static fields)
1785 * - size_inited (flag set when the instance_size is set)
1787 * LOCKING: this is supposed to be called with the loader lock held.
1790 mono_class_layout_fields (MonoClass *class)
1793 const int top = class->field.count;
1794 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1795 guint32 pass, passes, real_size;
1796 gboolean gc_aware_layout = FALSE;
1797 gboolean has_static_fields = FALSE;
1798 MonoClassField *field;
1801 * When we do generic sharing we need to have layout
1802 * information for open generic classes (either with a generic
1803 * context containing type variables or with a generic
1804 * container), so we don't return in that case anymore.
1808 * Enable GC aware auto layout: in this mode, reference
1809 * fields are grouped together inside objects, increasing collector
1811 * Requires that all classes whose layout is known to native code be annotated
1812 * with [StructLayout (LayoutKind.Sequential)]
1813 * Value types have gc_aware_layout disabled by default, as per
1814 * what the default is for other runtimes.
1816 /* corlib is missing [StructLayout] directives in many places */
1817 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1818 if (!class->valuetype)
1819 gc_aware_layout = TRUE;
1822 /* Compute klass->has_references */
1824 * Process non-static fields first, since static fields might recursively
1825 * refer to the class itself.
1827 for (i = 0; i < top; i++) {
1830 field = &class->fields [i];
1832 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1833 ftype = mono_type_get_underlying_type (field->type);
1834 ftype = mono_type_get_basic_type_from_generic (ftype);
1835 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1836 class->has_references = TRUE;
1840 for (i = 0; i < top; i++) {
1843 field = &class->fields [i];
1845 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1846 ftype = mono_type_get_underlying_type (field->type);
1847 ftype = mono_type_get_basic_type_from_generic (ftype);
1848 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1849 class->has_static_refs = TRUE;
1853 for (i = 0; i < top; i++) {
1856 field = &class->fields [i];
1858 ftype = mono_type_get_underlying_type (field->type);
1859 ftype = mono_type_get_basic_type_from_generic (ftype);
1860 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1861 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1862 class->has_static_refs = TRUE;
1864 class->has_references = TRUE;
1869 * Compute field layout and total size (not considering static fields)
1873 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1874 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1876 if (gc_aware_layout)
1881 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1884 if (class->parent) {
1885 mono_class_setup_fields (class->parent);
1886 if (class->parent->exception_type) {
1887 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1890 real_size = class->parent->instance_size;
1892 real_size = sizeof (MonoObject);
1895 for (pass = 0; pass < passes; ++pass) {
1896 for (i = 0; i < top; i++){
1901 field = &class->fields [i];
1903 if (mono_field_is_deleted (field))
1905 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1908 ftype = mono_type_get_underlying_type (field->type);
1909 ftype = mono_type_get_basic_type_from_generic (ftype);
1910 if (gc_aware_layout) {
1911 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1920 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1921 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1922 /* This field is a hack inserted by MCS to empty structures */
1926 size = mono_type_size (field->type, &align);
1928 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1929 align = class->packing_size ? MIN (class->packing_size, align): align;
1930 /* if the field has managed references, we need to force-align it
1933 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1934 align = MAX (align, sizeof (gpointer));
1936 class->min_align = MAX (align, class->min_align);
1937 field->offset = real_size;
1939 field->offset += align - 1;
1940 field->offset &= ~(align - 1);
1942 /*TypeBuilders produce all sort of weird things*/
1943 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1944 real_size = field->offset + size;
1947 class->instance_size = MAX (real_size, class->instance_size);
1949 if (class->instance_size & (class->min_align - 1)) {
1950 class->instance_size += class->min_align - 1;
1951 class->instance_size &= ~(class->min_align - 1);
1955 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1959 for (i = 0; i < top; i++) {
1964 field = &class->fields [i];
1967 * There must be info about all the fields in a type if it
1968 * uses explicit layout.
1970 if (mono_field_is_deleted (field))
1972 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1975 size = mono_type_size (field->type, &align);
1976 align = class->packing_size ? MIN (class->packing_size, align): align;
1977 class->min_align = MAX (align, class->min_align);
1980 * When we get here, field->offset is already set by the
1981 * loader (for either runtime fields or fields loaded from metadata).
1982 * The offset is from the start of the object: this works for both
1983 * classes and valuetypes.
1985 field->offset += sizeof (MonoObject);
1986 ftype = mono_type_get_underlying_type (field->type);
1987 ftype = mono_type_get_basic_type_from_generic (ftype);
1988 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1989 if (field->offset % sizeof (gpointer)) {
1990 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1997 real_size = MAX (real_size, size + field->offset);
2000 if (class->has_references) {
2001 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2003 /* Check for overlapping reference and non-reference fields */
2004 for (i = 0; i < top; i++) {
2007 field = &class->fields [i];
2009 if (mono_field_is_deleted (field))
2011 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2013 ftype = mono_type_get_underlying_type (field->type);
2014 if (MONO_TYPE_IS_REFERENCE (ftype))
2015 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2017 for (i = 0; i < top; i++) {
2018 field = &class->fields [i];
2020 if (mono_field_is_deleted (field))
2022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2025 // FIXME: Too much code does this
2027 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2028 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);
2029 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2033 g_free (ref_bitmap);
2036 class->instance_size = MAX (real_size, class->instance_size);
2037 if (class->instance_size & (class->min_align - 1)) {
2038 class->instance_size += class->min_align - 1;
2039 class->instance_size &= ~(class->min_align - 1);
2045 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2047 * This leads to all kinds of problems with nested structs, so only
2048 * enable it when a MONO_DEBUG property is set.
2050 * For small structs, set min_align to at least the struct size to improve
2051 * performance, and since the JIT memset/memcpy code assumes this and generates
2052 * unaligned accesses otherwise. See #78990 for a testcase.
2054 if (mono_align_small_structs) {
2055 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2056 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2060 mono_memory_barrier ();
2061 class->size_inited = 1;
2064 * Compute static field layout and size
2066 for (i = 0; i < top; i++){
2070 field = &class->fields [i];
2072 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2074 if (mono_field_is_deleted (field))
2077 if (mono_type_has_exceptions (field->type)) {
2078 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2082 has_static_fields = TRUE;
2084 size = mono_type_size (field->type, &align);
2085 field->offset = class->sizes.class_size;
2086 /*align is always non-zero here*/
2087 field->offset += align - 1;
2088 field->offset &= ~(align - 1);
2089 class->sizes.class_size = field->offset + size;
2092 if (has_static_fields && class->sizes.class_size == 0)
2093 /* Simplify code which depends on class_size != 0 if the class has static fields */
2094 class->sizes.class_size = 8;
2098 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2102 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2103 method->klass = class;
2104 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2105 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2106 method->signature = sig;
2107 method->name = name;
2110 if (name [0] == '.') {
2111 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2113 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2119 * mono_class_setup_methods:
2122 * Initializes the 'methods' array in CLASS.
2123 * Calling this method should be avoided if possible since it allocates a lot
2124 * of long-living MonoMethod structures.
2125 * Methods belonging to an interface are assigned a sequential slot starting
2128 * On failure this function sets class->exception_type
2131 mono_class_setup_methods (MonoClass *class)
2134 MonoMethod **methods;
2139 if (class->generic_class) {
2141 MonoClass *gklass = class->generic_class->container_class;
2143 mono_class_init (gklass);
2144 if (!gklass->exception_type)
2145 mono_class_setup_methods (gklass);
2146 if (gklass->exception_type) {
2147 /* FIXME make exception_data less opaque so it's possible to dup it here */
2148 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2152 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2153 count = gklass->method.count;
2154 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2156 for (i = 0; i < count; i++) {
2157 methods [i] = mono_class_inflate_generic_method_full_checked (
2158 gklass->methods [i], class, mono_class_get_context (class), &error);
2159 if (!mono_error_ok (&error)) {
2160 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2161 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)));
2164 mono_error_cleanup (&error);
2168 } else if (class->rank) {
2170 MonoMethod *amethod;
2171 MonoMethodSignature *sig;
2172 int count_generic = 0, first_generic = 0;
2174 gboolean jagged_ctor = FALSE;
2176 count = 3 + (class->rank > 1? 2: 1);
2178 mono_class_setup_interfaces (class, &error);
2179 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2181 if (class->rank == 1 && class->element_class->rank) {
2183 class->method.count ++;
2186 if (class->interface_count) {
2187 count_generic = generic_array_methods (class);
2188 first_generic = count;
2189 count += class->interface_count * count_generic;
2192 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2194 sig = mono_metadata_signature_alloc (class->image, class->rank);
2195 sig->ret = &mono_defaults.void_class->byval_arg;
2196 sig->pinvoke = TRUE;
2197 sig->hasthis = TRUE;
2198 for (i = 0; i < class->rank; ++i)
2199 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2201 amethod = create_array_method (class, ".ctor", sig);
2202 methods [method_num++] = amethod;
2203 if (class->rank > 1) {
2204 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2205 sig->ret = &mono_defaults.void_class->byval_arg;
2206 sig->pinvoke = TRUE;
2207 sig->hasthis = TRUE;
2208 for (i = 0; i < class->rank * 2; ++i)
2209 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2211 amethod = create_array_method (class, ".ctor", sig);
2212 methods [method_num++] = amethod;
2216 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2217 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2218 sig->ret = &mono_defaults.void_class->byval_arg;
2219 sig->pinvoke = TRUE;
2220 sig->hasthis = TRUE;
2221 for (i = 0; i < class->rank + 1; ++i)
2222 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2223 amethod = create_array_method (class, ".ctor", sig);
2224 methods [method_num++] = amethod;
2227 /* element Get (idx11, [idx2, ...]) */
2228 sig = mono_metadata_signature_alloc (class->image, class->rank);
2229 sig->ret = &class->element_class->byval_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, "Get", sig);
2235 methods [method_num++] = amethod;
2236 /* element& Address (idx11, [idx2, ...]) */
2237 sig = mono_metadata_signature_alloc (class->image, class->rank);
2238 sig->ret = &class->element_class->this_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 amethod = create_array_method (class, "Address", sig);
2244 methods [method_num++] = amethod;
2245 /* void Set (idx11, [idx2, ...], element) */
2246 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2247 sig->ret = &mono_defaults.void_class->byval_arg;
2248 sig->pinvoke = TRUE;
2249 sig->hasthis = TRUE;
2250 for (i = 0; i < class->rank; ++i)
2251 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2252 sig->params [i] = &class->element_class->byval_arg;
2253 amethod = create_array_method (class, "Set", sig);
2254 methods [method_num++] = amethod;
2256 for (i = 0; i < class->interface_count; i++)
2257 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2261 count = class->method.count;
2262 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2263 for (i = 0; i < count; ++i) {
2264 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2265 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2267 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)));
2268 mono_error_cleanup (&error);
2273 if (MONO_CLASS_IS_INTERFACE (class)) {
2275 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2276 for (i = 0; i < count; ++i) {
2277 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2278 methods [i]->slot = slot++;
2282 mono_image_lock (class->image);
2284 if (!class->methods) {
2285 class->method.count = count;
2287 /* Needed because of the double-checking locking pattern */
2288 mono_memory_barrier ();
2290 class->methods = methods;
2293 mono_image_unlock (class->image);
2297 * mono_class_get_method_by_index:
2299 * Returns class->methods [index], initializing class->methods if neccesary.
2301 * LOCKING: Acquires the loader lock.
2304 mono_class_get_method_by_index (MonoClass *class, int index)
2307 /* Avoid calling setup_methods () if possible */
2308 if (class->generic_class && !class->methods) {
2309 MonoClass *gklass = class->generic_class->container_class;
2312 m = mono_class_inflate_generic_method_full_checked (
2313 gklass->methods [index], class, mono_class_get_context (class), &error);
2314 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2316 * If setup_methods () is called later for this class, no duplicates are created,
2317 * since inflate_generic_method guarantees that only one instance of a method
2318 * is created for each context.
2321 mono_class_setup_methods (class);
2322 g_assert (m == class->methods [index]);
2326 mono_class_setup_methods (class);
2327 if (class->exception_type) /*FIXME do proper error handling*/
2329 g_assert (index >= 0 && index < class->method.count);
2330 return class->methods [index];
2335 * mono_class_get_inflated_method:
2337 * Given an inflated class CLASS and a method METHOD which should be a method of
2338 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2341 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2343 MonoClass *gklass = class->generic_class->container_class;
2346 g_assert (method->klass == gklass);
2348 mono_class_setup_methods (gklass);
2349 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2351 for (i = 0; i < gklass->method.count; ++i) {
2352 if (gklass->methods [i] == method) {
2353 if (class->methods) {
2354 return class->methods [i];
2357 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2358 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2368 * mono_class_get_vtable_entry:
2370 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2371 * LOCKING: Acquires the loader lock.
2374 mono_class_get_vtable_entry (MonoClass *class, int offset)
2378 if (class->rank == 1) {
2380 * szarrays do not overwrite any methods of Array, so we can avoid
2381 * initializing their vtables in some cases.
2383 mono_class_setup_vtable (class->parent);
2384 if (offset < class->parent->vtable_size)
2385 return class->parent->vtable [offset];
2388 if (class->generic_class) {
2390 MonoClass *gklass = class->generic_class->container_class;
2391 mono_class_setup_vtable (gklass);
2392 m = gklass->vtable [offset];
2394 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2395 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2397 mono_class_setup_vtable (class);
2398 if (class->exception_type)
2400 m = class->vtable [offset];
2407 * mono_class_get_vtable_size:
2409 * Return the vtable size for KLASS.
2412 mono_class_get_vtable_size (MonoClass *klass)
2414 mono_class_setup_vtable (klass);
2416 return klass->vtable_size;
2420 * mono_class_setup_properties:
2422 * Initialize class->ext.property and class->ext.properties.
2424 * This method can fail the class.
2427 mono_class_setup_properties (MonoClass *class)
2429 guint startm, endm, i, j;
2430 guint32 cols [MONO_PROPERTY_SIZE];
2431 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2432 MonoProperty *properties;
2436 if (class->ext && class->ext->properties)
2439 if (class->generic_class) {
2440 MonoClass *gklass = class->generic_class->container_class;
2442 mono_class_init (gklass);
2443 mono_class_setup_properties (gklass);
2444 if (gklass->exception_type) {
2445 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2449 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2451 for (i = 0; i < gklass->ext->property.count; i++) {
2453 MonoProperty *prop = &properties [i];
2455 *prop = gklass->ext->properties [i];
2458 prop->get = mono_class_inflate_generic_method_full_checked (
2459 prop->get, class, mono_class_get_context (class), &error);
2461 prop->set = mono_class_inflate_generic_method_full_checked (
2462 prop->set, class, mono_class_get_context (class), &error);
2464 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2465 prop->parent = class;
2468 first = gklass->ext->property.first;
2469 count = gklass->ext->property.count;
2471 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2472 count = last - first;
2475 mono_class_setup_methods (class);
2476 if (class->exception_type)
2480 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2481 for (i = first; i < last; ++i) {
2482 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2483 properties [i - first].parent = class;
2484 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2485 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2487 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2488 for (j = startm; j < endm; ++j) {
2491 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2493 if (class->image->uncompressed_metadata) {
2495 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2496 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2497 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2499 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2502 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2503 case METHOD_SEMANTIC_SETTER:
2504 properties [i - first].set = method;
2506 case METHOD_SEMANTIC_GETTER:
2507 properties [i - first].get = method;
2516 mono_class_alloc_ext (class);
2518 mono_image_lock (class->image);
2520 if (class->ext->properties) {
2521 /* We leak 'properties' which was allocated from the image mempool */
2522 mono_image_unlock (class->image);
2526 class->ext->property.first = first;
2527 class->ext->property.count = count;
2529 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2530 mono_memory_barrier ();
2532 /* Leave this assignment as the last op in the function */
2533 class->ext->properties = properties;
2535 mono_image_unlock (class->image);
2539 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2541 MonoMethod **om, **retval;
2544 for (om = methods, count = 0; *om; ++om, ++count)
2547 retval = g_new0 (MonoMethod*, count + 1);
2549 for (om = methods, count = 0; *om; ++om, ++count) {
2551 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2552 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2558 /*This method can fail the class.*/
2560 mono_class_setup_events (MonoClass *class)
2563 guint startm, endm, i, j;
2564 guint32 cols [MONO_EVENT_SIZE];
2565 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2569 if (class->ext && class->ext->events)
2572 if (class->generic_class) {
2573 MonoClass *gklass = class->generic_class->container_class;
2574 MonoGenericContext *context = NULL;
2576 mono_class_setup_events (gklass);
2577 if (gklass->exception_type) {
2578 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2582 first = gklass->ext->event.first;
2583 count = gklass->ext->event.count;
2585 events = mono_class_new0 (class, MonoEvent, count);
2588 context = mono_class_get_context (class);
2590 for (i = 0; i < count; i++) {
2592 MonoEvent *event = &events [i];
2593 MonoEvent *gevent = &gklass->ext->events [i];
2595 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2597 event->parent = class;
2598 event->name = gevent->name;
2599 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2600 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2601 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2602 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2603 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2604 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2606 #ifndef MONO_SMALL_CONFIG
2607 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2609 event->attrs = gevent->attrs;
2612 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2613 count = last - first;
2616 mono_class_setup_methods (class);
2617 if (class->exception_type) {
2618 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2623 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2624 for (i = first; i < last; ++i) {
2625 MonoEvent *event = &events [i - first];
2627 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2628 event->parent = class;
2629 event->attrs = cols [MONO_EVENT_FLAGS];
2630 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2632 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2633 for (j = startm; j < endm; ++j) {
2636 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2638 if (class->image->uncompressed_metadata) {
2640 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2641 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2642 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2644 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2647 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2648 case METHOD_SEMANTIC_ADD_ON:
2649 event->add = method;
2651 case METHOD_SEMANTIC_REMOVE_ON:
2652 event->remove = method;
2654 case METHOD_SEMANTIC_FIRE:
2655 event->raise = method;
2657 case METHOD_SEMANTIC_OTHER: {
2658 #ifndef MONO_SMALL_CONFIG
2661 if (event->other == NULL) {
2662 event->other = g_new0 (MonoMethod*, 2);
2664 while (event->other [n])
2666 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2668 event->other [n] = method;
2669 /* NULL terminated */
2670 event->other [n + 1] = NULL;
2681 mono_class_alloc_ext (class);
2683 mono_image_lock (class->image);
2685 if (class->ext->events) {
2686 mono_image_unlock (class->image);
2690 class->ext->event.first = first;
2691 class->ext->event.count = count;
2693 /* Flush any pending writes as we do double checked locking on class->ext.events */
2694 mono_memory_barrier ();
2696 /* Leave this assignment as the last op in the function */
2697 class->ext->events = events;
2699 mono_image_unlock (class->image);
2703 * Global pool of interface IDs, represented as a bitset.
2704 * LOCKING: Protected by the classes lock.
2706 static MonoBitSet *global_interface_bitset = NULL;
2709 * mono_unload_interface_ids:
2710 * @bitset: bit set of interface IDs
2712 * When an image is unloaded, the interface IDs associated with
2713 * the image are put back in the global pool of IDs so the numbers
2717 mono_unload_interface_ids (MonoBitSet *bitset)
2720 mono_bitset_sub (global_interface_bitset, bitset);
2725 mono_unload_interface_id (MonoClass *class)
2727 if (global_interface_bitset && class->interface_id) {
2729 mono_bitset_clear (global_interface_bitset, class->interface_id);
2735 * mono_get_unique_iid:
2738 * Assign a unique integer ID to the interface represented by @class.
2739 * The ID will positive and as small as possible.
2740 * LOCKING: Acquires the classes lock.
2741 * Returns: the new ID.
2744 mono_get_unique_iid (MonoClass *class)
2748 g_assert (MONO_CLASS_IS_INTERFACE (class));
2752 if (!global_interface_bitset) {
2753 global_interface_bitset = mono_bitset_new (128, 0);
2756 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2758 int old_size = mono_bitset_size (global_interface_bitset);
2759 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2760 mono_bitset_free (global_interface_bitset);
2761 global_interface_bitset = new_set;
2764 mono_bitset_set (global_interface_bitset, iid);
2765 /* set the bit also in the per-image set */
2766 if (!class->generic_class) {
2767 if (class->image->interface_bitset) {
2768 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2769 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2770 mono_bitset_free (class->image->interface_bitset);
2771 class->image->interface_bitset = new_set;
2774 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2776 mono_bitset_set (class->image->interface_bitset, iid);
2781 #ifndef MONO_SMALL_CONFIG
2782 if (mono_print_vtable) {
2784 char *type_name = mono_type_full_name (&class->byval_arg);
2785 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2786 generic_id = class->generic_class->context.class_inst->id;
2787 g_assert (generic_id != 0);
2791 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2796 g_assert (iid <= 65535);
2801 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2806 mono_class_setup_interfaces (klass, error);
2807 if (!mono_error_ok (error))
2810 for (i = 0; i < klass->interface_count; i++) {
2811 ic = klass->interfaces [i];
2814 *res = g_ptr_array_new ();
2815 g_ptr_array_add (*res, ic);
2816 mono_class_init (ic);
2817 if (ic->exception_type) {
2818 mono_error_set_type_load_class (error, ic, "Error Loading class");
2822 collect_implemented_interfaces_aux (ic, res, error);
2823 if (!mono_error_ok (error))
2829 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2831 GPtrArray *res = NULL;
2833 collect_implemented_interfaces_aux (klass, &res, error);
2834 if (!mono_error_ok (error)) {
2836 g_ptr_array_free (res, TRUE);
2843 compare_interface_ids (const void *p_key, const void *p_element) {
2844 const MonoClass *key = p_key;
2845 const MonoClass *element = *(MonoClass**) p_element;
2847 return (key->interface_id - element->interface_id);
2850 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2852 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2853 MonoClass **result = mono_binary_search (
2855 klass->interfaces_packed,
2856 klass->interface_offsets_count,
2857 sizeof (MonoClass *),
2858 compare_interface_ids);
2860 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2867 * mono_class_interface_offset_with_variance:
2869 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2870 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2872 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2874 * FIXME figure out MS disambiguation rules and fix this function.
2877 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2878 int i = mono_class_interface_offset (klass, itf);
2879 *non_exact_match = FALSE;
2883 if (!mono_class_has_variant_generic_params (itf))
2886 for (i = 0; i < klass->interface_offsets_count; i++) {
2887 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2888 *non_exact_match = TRUE;
2889 return klass->interface_offsets_packed [i];
2897 print_implemented_interfaces (MonoClass *klass) {
2900 GPtrArray *ifaces = NULL;
2902 int ancestor_level = 0;
2904 name = mono_type_get_full_name (klass);
2905 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2908 for (i = 0; i < klass->interface_offsets_count; i++)
2909 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2910 klass->interfaces_packed [i]->interface_id,
2911 klass->interface_offsets_packed [i],
2912 klass->interfaces_packed [i]->method.count,
2913 klass->interfaces_packed [i]->name_space,
2914 klass->interfaces_packed [i]->name );
2915 printf ("Interface flags: ");
2916 for (i = 0; i <= klass->max_interface_id; i++)
2917 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2918 printf ("(%d,T)", i);
2920 printf ("(%d,F)", i);
2922 printf ("Dump interface flags:");
2923 #ifdef COMPRESSED_INTERFACE_BITMAP
2925 const uint8_t* p = klass->interface_bitmap;
2926 i = klass->max_interface_id;
2928 printf (" %d x 00 %02X", p [0], p [1]);
2934 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2935 printf (" %02X", klass->interface_bitmap [i]);
2938 while (klass != NULL) {
2939 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2940 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2941 if (!mono_error_ok (&error)) {
2942 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2943 mono_error_cleanup (&error);
2944 } else if (ifaces) {
2945 for (i = 0; i < ifaces->len; i++) {
2946 MonoClass *ic = g_ptr_array_index (ifaces, i);
2947 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2948 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2950 mono_class_interface_offset (klass, ic),
2955 g_ptr_array_free (ifaces, TRUE);
2958 klass = klass->parent;
2963 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2966 args [0] = &arg0->byval_arg;
2968 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2972 array_class_get_if_rank (MonoClass *class, guint rank)
2974 return rank ? mono_array_class_get (class, rank) : class;
2978 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2980 valuetype_types [0] = eclass;
2981 if (eclass == mono_defaults.int16_class)
2982 valuetype_types [1] = mono_defaults.uint16_class;
2983 else if (eclass == mono_defaults.uint16_class)
2984 valuetype_types [1] = mono_defaults.int16_class;
2985 else if (eclass == mono_defaults.int32_class)
2986 valuetype_types [1] = mono_defaults.uint32_class;
2987 else if (eclass == mono_defaults.uint32_class)
2988 valuetype_types [1] = mono_defaults.int32_class;
2989 else if (eclass == mono_defaults.int64_class)
2990 valuetype_types [1] = mono_defaults.uint64_class;
2991 else if (eclass == mono_defaults.uint64_class)
2992 valuetype_types [1] = mono_defaults.int64_class;
2993 else if (eclass == mono_defaults.byte_class)
2994 valuetype_types [1] = mono_defaults.sbyte_class;
2995 else if (eclass == mono_defaults.sbyte_class)
2996 valuetype_types [1] = mono_defaults.byte_class;
2997 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2998 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3001 /* this won't be needed once bug #325495 is completely fixed
3002 * though we'll need something similar to know which interfaces to allow
3003 * in arrays when they'll be lazyly created
3005 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3006 * MS returns diferrent types based on which instance is called. For example:
3007 * object obj = new byte[10][];
3008 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3009 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3012 * Fixing this should kill quite some code, save some bits and improve compatibility.
3015 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3017 MonoClass *eclass = class->element_class;
3018 static MonoClass* generic_icollection_class = NULL;
3019 static MonoClass* generic_ienumerable_class = NULL;
3020 static MonoClass* generic_ienumerator_class = NULL;
3021 static MonoClass* generic_ireadonlylist_class = NULL;
3022 static MonoClass* generic_ireadonlycollection_class = NULL;
3023 MonoClass *valuetype_types[2] = { NULL, NULL };
3024 MonoClass **interfaces = NULL;
3025 int i, nifaces, interface_count, real_count, original_rank;
3027 gboolean internal_enumerator;
3028 gboolean eclass_is_valuetype;
3030 if (!mono_defaults.generic_ilist_class) {
3034 internal_enumerator = FALSE;
3035 eclass_is_valuetype = FALSE;
3036 original_rank = eclass->rank;
3037 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3038 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3040 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3042 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3043 original_rank = eclass->rank;
3045 eclass = eclass->element_class;
3046 internal_enumerator = TRUE;
3047 *is_enumerator = TRUE;
3055 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3056 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3058 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3060 if (!generic_icollection_class) {
3061 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3062 "System.Collections.Generic", "ICollection`1");
3063 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3064 "System.Collections.Generic", "IEnumerable`1");
3065 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3066 "System.Collections.Generic", "IEnumerator`1");
3067 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3068 "System.Collections.Generic", "IReadOnlyList`1");
3069 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3070 "System.Collections.Generic", "IReadOnlyCollection`1");
3073 mono_class_init (eclass);
3076 * Arrays in 2.0 need to implement a number of generic interfaces
3077 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3078 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3079 * We collect the types needed to build the
3080 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3081 * the generic interfaces needed to implement.
3083 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3084 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3086 if (eclass->valuetype) {
3087 nifaces = generic_ireadonlylist_class ? 5 : 3;
3088 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3090 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3091 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3092 if (internal_enumerator) {
3094 if (valuetype_types [1])
3098 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3099 interfaces [0] = valuetype_types [0];
3100 if (valuetype_types [1])
3101 interfaces [nifaces] = valuetype_types [1];
3103 eclass_is_valuetype = TRUE;
3106 int idepth = eclass->idepth;
3107 if (!internal_enumerator)
3109 nifaces = generic_ireadonlylist_class ? 2 : 3;
3111 // FIXME: This doesn't seem to work/required for generic params
3112 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3113 mono_class_setup_interface_offsets (eclass);
3115 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3116 /* we add object for interfaces and the supertypes for the other
3117 * types. The last of the supertypes is the element class itself which we
3118 * already created the explicit interfaces for (so we include it for IEnumerator
3119 * and exclude it for arrays).
3121 if (MONO_CLASS_IS_INTERFACE (eclass))
3124 interface_count += idepth;
3125 if (eclass->rank && eclass->element_class->valuetype) {
3126 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3127 if (valuetype_types [1])
3130 /* IList, ICollection, IEnumerable, IReadOnlyList */
3131 interface_count *= nifaces;
3132 real_count = interface_count;
3133 if (internal_enumerator) {
3134 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3135 if (valuetype_types [1])
3138 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3139 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3140 interfaces [0] = mono_defaults.object_class;
3144 for (i = 0; i < idepth; i++) {
3145 mono_class_init (eclass->supertypes [i]);
3146 interfaces [j] = eclass->supertypes [i];
3150 if (all_interfaces) {
3151 for (i = 0; i < eclass->interface_offsets_count; i++) {
3152 interfaces [j] = eclass->interfaces_packed [i];
3156 for (i = 0; i < eclass->interface_count; i++) {
3157 interfaces [j] = eclass->interfaces [i];
3161 if (valuetype_types [1]) {
3162 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3167 /* instantiate the generic interfaces */
3168 for (i = 0; i < interface_count; i += nifaces) {
3169 MonoClass *iface = interfaces [i];
3171 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3172 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3174 if (eclass->valuetype) {
3175 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3176 if (generic_ireadonlylist_class) {
3177 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3178 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3181 if (!generic_ireadonlylist_class)
3182 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3185 if (internal_enumerator) {
3187 /* instantiate IEnumerator<iface> */
3188 for (i = 0; i < interface_count; i++) {
3189 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3191 j = interface_count;
3192 if (!eclass_is_valuetype) {
3193 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3194 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3197 for (i = 0; i < eclass->idepth; i++) {
3198 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3202 for (i = 0; i < eclass->interface_offsets_count; i++) {
3203 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3207 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3209 if (valuetype_types [1])
3210 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3214 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3215 for (i = 0; i < real_count; ++i) {
3216 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3217 g_print ("%s implements %s\n", type_name, name);
3228 find_array_interface (MonoClass *klass, const char *name)
3231 for (i = 0; i < klass->interface_count; ++i) {
3232 if (strcmp (klass->interfaces [i]->name, name) == 0)
3239 * Return the number of virtual methods.
3240 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3241 * Return -1 on failure.
3242 * FIXME It would be nice if this information could be cached somewhere.
3245 count_virtual_methods (MonoClass *class)
3249 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3251 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3252 mono_class_setup_methods (class);
3253 if (class->exception_type)
3256 for (i = 0; i < class->method.count; ++i) {
3257 flags = class->methods [i]->flags;
3258 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3262 for (i = 0; i < class->method.count; ++i) {
3263 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3265 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3273 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3281 m = (l + num_ifaces) / 2;
3282 if (interfaces_full [m] == ic)
3284 if (l == num_ifaces)
3286 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3295 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3297 int i = find_interface (num_ifaces, interfaces_full, ic);
3299 return interface_offsets_full [i];
3304 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3306 int i = find_interface (num_ifaces, interfaces_full, ic);
3310 interface_offsets_full [i] = offset;
3313 for (i = 0; i < num_ifaces; ++i) {
3314 if (interfaces_full [i]) {
3316 if (interfaces_full [i]->interface_id < ic->interface_id)
3319 while (end < num_ifaces && interfaces_full [end]) end++;
3320 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3321 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3323 interfaces_full [i] = ic;
3324 interface_offsets_full [i] = offset;
3330 #ifdef COMPRESSED_INTERFACE_BITMAP
3333 * Compressed interface bitmap design.
3335 * Interface bitmaps take a large amount of memory, because their size is
3336 * linear with the maximum interface id assigned in the process (each interface
3337 * is assigned a unique id as it is loaded). The number of interface classes
3338 * is high because of the many implicit interfaces implemented by arrays (we'll
3339 * need to lazy-load them in the future).
3340 * Most classes implement a very small number of interfaces, so the bitmap is
3341 * sparse. This bitmap needs to be checked by interface casts, so access to the
3342 * needed bit must be fast and doable with few jit instructions.
3344 * The current compression format is as follows:
3345 * *) it is a sequence of one or more two-byte elements
3346 * *) the first byte in the element is the count of empty bitmap bytes
3347 * at the current bitmap position
3348 * *) the second byte in the element is an actual bitmap byte at the current
3351 * As an example, the following compressed bitmap bytes:
3352 * 0x07 0x01 0x00 0x7
3353 * correspond to the following bitmap:
3354 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3356 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3357 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3358 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3362 * mono_compress_bitmap:
3363 * @dest: destination buffer
3364 * @bitmap: bitmap buffer
3365 * @size: size of @bitmap in bytes
3367 * This is a mono internal function.
3368 * The @bitmap data is compressed into a format that is small but
3369 * still searchable in few instructions by the JIT and runtime.
3370 * The compressed data is stored in the buffer pointed to by the
3371 * @dest array. Passing a #NULL value for @dest allows to just compute
3372 * the size of the buffer.
3373 * This compression algorithm assumes the bits set in the bitmap are
3374 * few and far between, like in interface bitmaps.
3375 * Returns: the size of the compressed bitmap in bytes.
3378 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3382 const uint8_t *end = bitmap + size;
3383 while (bitmap < end) {
3384 if (*bitmap || numz == 255) {
3408 * mono_class_interface_match:
3409 * @bitmap: a compressed bitmap buffer
3410 * @id: the index to check in the bitmap
3412 * This is a mono internal function.
3413 * Checks if a bit is set in a compressed interface bitmap. @id must
3414 * be already checked for being smaller than the maximum id encoded in the
3417 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3421 mono_class_interface_match (const uint8_t *bitmap, int id)
3424 id -= bitmap [0] * 8;
3428 return bitmap [1] & (1 << id);
3437 * LOCKING: this is supposed to be called with the loader lock held.
3438 * Return -1 on failure and set exception_type
3441 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3445 int i, j, max_iid, num_ifaces;
3446 MonoClass **interfaces_full = NULL;
3447 int *interface_offsets_full = NULL;
3449 GPtrArray **ifaces_array = NULL;
3450 int interface_offsets_count;
3451 MonoClass **array_interfaces = NULL;
3452 int num_array_interfaces;
3453 int is_enumerator = FALSE;
3455 mono_class_setup_supertypes (class);
3457 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3458 * implicit interfaces have the property that they are assigned the same slot in the
3459 * vtables for compatible interfaces
3461 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3463 /* compute maximum number of slots and maximum interface id */
3465 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3466 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3467 for (j = 0; j < class->idepth; j++) {
3468 k = class->supertypes [j];
3469 num_ifaces += k->interface_count;
3470 for (i = 0; i < k->interface_count; i++) {
3471 ic = k->interfaces [i];
3474 mono_class_init (ic);
3476 if (max_iid < ic->interface_id)
3477 max_iid = ic->interface_id;
3479 ifaces = mono_class_get_implemented_interfaces (k, &error);
3480 if (!mono_error_ok (&error)) {
3481 char *name = mono_type_get_full_name (k);
3482 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)));
3484 mono_error_cleanup (&error);
3489 num_ifaces += ifaces->len;
3490 for (i = 0; i < ifaces->len; ++i) {
3491 ic = g_ptr_array_index (ifaces, i);
3492 if (max_iid < ic->interface_id)
3493 max_iid = ic->interface_id;
3495 ifaces_array [j] = ifaces;
3499 for (i = 0; i < num_array_interfaces; ++i) {
3500 ic = array_interfaces [i];
3501 mono_class_init (ic);
3502 if (max_iid < ic->interface_id)
3503 max_iid = ic->interface_id;
3506 if (MONO_CLASS_IS_INTERFACE (class)) {
3508 if (max_iid < class->interface_id)
3509 max_iid = class->interface_id;
3511 class->max_interface_id = max_iid;
3512 /* compute vtable offset for interfaces */
3513 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3514 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3516 for (i = 0; i < num_ifaces; i++) {
3517 interface_offsets_full [i] = -1;
3520 /* skip the current class */
3521 for (j = 0; j < class->idepth - 1; j++) {
3522 k = class->supertypes [j];
3523 ifaces = ifaces_array [j];
3526 for (i = 0; i < ifaces->len; ++i) {
3528 ic = g_ptr_array_index (ifaces, i);
3530 /*Force the sharing of interface offsets between parent and subtypes.*/
3531 io = mono_class_interface_offset (k, ic);
3533 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3538 g_assert (class == class->supertypes [class->idepth - 1]);
3539 ifaces = ifaces_array [class->idepth - 1];
3541 for (i = 0; i < ifaces->len; ++i) {
3543 ic = g_ptr_array_index (ifaces, i);
3544 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3546 count = count_virtual_methods (ic);
3548 char *name = mono_type_get_full_name (ic);
3549 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3558 if (MONO_CLASS_IS_INTERFACE (class))
3559 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3561 if (num_array_interfaces) {
3562 if (is_enumerator) {
3563 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3564 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3565 g_assert (ienumerator_offset >= 0);
3566 for (i = 0; i < num_array_interfaces; ++i) {
3567 ic = array_interfaces [i];
3568 if (strcmp (ic->name, "IEnumerator`1") == 0)
3569 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3571 g_assert_not_reached ();
3572 /*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);*/
3575 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3576 int ilist_iface_idx = find_array_interface (class, "IList`1");
3577 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3578 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3579 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3580 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3581 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3582 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3583 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3584 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3585 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3586 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3587 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3588 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3589 for (i = 0; i < num_array_interfaces; ++i) {
3591 ic = array_interfaces [i];
3592 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3593 offset = ilist_offset;
3594 else if (strcmp (ic->name, "ICollection`1") == 0)
3595 offset = icollection_offset;
3596 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3597 offset = ienumerable_offset;
3598 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3599 offset = ireadonlylist_offset;
3600 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3601 offset = ireadonlycollection_offset;
3603 g_assert_not_reached ();
3604 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3605 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3610 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3611 if (interface_offsets_full [i] != -1) {
3612 interface_offsets_count ++;
3617 * We might get called multiple times:
3618 * - mono_class_init ()
3619 * - mono_class_setup_vtable ().
3620 * - mono_class_setup_interface_offsets ().
3621 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3622 * means we have to overwrite those when called from other places (#4440).
3624 if (class->interfaces_packed) {
3626 g_assert (class->interface_offsets_count == interface_offsets_count);
3630 class->interface_offsets_count = interface_offsets_count;
3631 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3632 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3633 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3634 #ifdef COMPRESSED_INTERFACE_BITMAP
3635 bitmap = g_malloc0 (bsize);
3637 bitmap = mono_class_alloc0 (class, bsize);
3639 for (i = 0; i < interface_offsets_count; i++) {
3640 int id = interfaces_full [i]->interface_id;
3641 bitmap [id >> 3] |= (1 << (id & 7));
3642 class->interfaces_packed [i] = interfaces_full [i];
3643 class->interface_offsets_packed [i] = interface_offsets_full [i];
3644 /*if (num_array_interfaces)
3645 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]);*/
3647 #ifdef COMPRESSED_INTERFACE_BITMAP
3648 i = mono_compress_bitmap (NULL, bitmap, bsize);
3649 class->interface_bitmap = mono_class_alloc0 (class, i);
3650 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3653 class->interface_bitmap = bitmap;
3658 g_free (interfaces_full);
3659 g_free (interface_offsets_full);
3660 g_free (array_interfaces);
3661 for (i = 0; i < class->idepth; i++) {
3662 ifaces = ifaces_array [i];
3664 g_ptr_array_free (ifaces, TRUE);
3666 g_free (ifaces_array);
3668 //printf ("JUST DONE: ");
3669 //print_implemented_interfaces (class);
3675 * Setup interface offsets for interfaces.
3677 * - class->max_interface_id
3678 * - class->interface_offsets_count
3679 * - class->interfaces_packed
3680 * - class->interface_offsets_packed
3681 * - class->interface_bitmap
3683 * This function can fail @class.
3686 mono_class_setup_interface_offsets (MonoClass *class)
3688 mono_loader_lock ();
3690 setup_interface_offsets (class, 0, FALSE);
3692 mono_loader_unlock ();
3695 /*Checks if @klass has @parent as one of it's parents type gtd
3699 * Bar<T> : Foo<Bar<Bar<T>>>
3703 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3705 klass = mono_class_get_generic_type_definition (klass);
3706 parent = mono_class_get_generic_type_definition (parent);
3707 mono_class_setup_supertypes (klass);
3708 mono_class_setup_supertypes (parent);
3710 return klass->idepth >= parent->idepth &&
3711 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3715 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3717 MonoGenericInst *ginst;
3719 if (!class->generic_class) {
3720 mono_class_setup_vtable_full (class, in_setup);
3721 return class->exception_type == 0;
3724 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3725 if (class->generic_class->container_class->exception_type) {
3726 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3730 ginst = class->generic_class->context.class_inst;
3731 for (i = 0; i < ginst->type_argc; ++i) {
3733 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3735 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3736 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3737 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3739 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3740 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3748 * mono_class_setup_vtable:
3750 * Creates the generic vtable of CLASS.
3751 * Initializes the following fields in MonoClass:
3754 * Plus all the fields initialized by setup_interface_offsets ().
3755 * If there is an error during vtable construction, class->exception_type is set.
3757 * LOCKING: Acquires the loader lock.
3760 mono_class_setup_vtable (MonoClass *class)
3762 mono_class_setup_vtable_full (class, NULL);
3766 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3768 MonoMethod **overrides;
3769 MonoGenericContext *context;
3777 if (MONO_CLASS_IS_INTERFACE (class)) {
3778 /* This sets method->slot for all methods if this is an interface */
3779 mono_class_setup_methods (class);
3783 if (class->exception_type)
3786 if (g_list_find (in_setup, class))
3789 mono_loader_lock ();
3791 if (class->vtable) {
3792 mono_loader_unlock ();
3796 mono_stats.generic_vtable_count ++;
3797 in_setup = g_list_prepend (in_setup, class);
3799 if (class->generic_class) {
3800 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3801 mono_loader_unlock ();
3802 g_list_remove (in_setup, class);
3806 context = mono_class_get_context (class);
3807 type_token = class->generic_class->container_class->type_token;
3809 context = (MonoGenericContext *) class->generic_container;
3810 type_token = class->type_token;
3813 if (image_is_dynamic (class->image)) {
3814 /* Generic instances can have zero method overrides without causing any harm.
3815 * This is true since we don't do layout all over again for them, we simply inflate
3816 * the layout of the parent.
3818 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3820 /* The following call fails if there are missing methods in the type */
3821 /* FIXME it's probably a good idea to avoid this for generic instances. */
3822 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3826 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3828 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3832 mono_loader_unlock ();
3833 g_list_remove (in_setup, class);
3838 #define DEBUG_INTERFACE_VTABLE_CODE 0
3839 #define TRACE_INTERFACE_VTABLE_CODE 0
3840 #define VERIFY_INTERFACE_VTABLE_CODE 0
3841 #define VTABLE_SELECTOR (1)
3843 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3844 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3845 if (!(VTABLE_SELECTOR)) break; \
3849 #define DEBUG_INTERFACE_VTABLE(stmt)
3852 #if TRACE_INTERFACE_VTABLE_CODE
3853 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3854 if (!(VTABLE_SELECTOR)) break; \
3858 #define TRACE_INTERFACE_VTABLE(stmt)
3861 #if VERIFY_INTERFACE_VTABLE_CODE
3862 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3863 if (!(VTABLE_SELECTOR)) break; \
3867 #define VERIFY_INTERFACE_VTABLE(stmt)
3871 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3873 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3877 GString *res = g_string_new ("");
3879 g_string_append_c (res, '(');
3880 for (i = 0; i < sig->param_count; ++i) {
3882 g_string_append_c (res, ',');
3883 mono_type_get_desc (res, sig->params [i], include_namespace);
3885 g_string_append (res, ")=>");
3886 if (sig->ret != NULL) {
3887 mono_type_get_desc (res, sig->ret, include_namespace);
3889 g_string_append (res, "NULL");
3892 g_string_free (res, FALSE);
3896 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3897 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3898 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3899 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3907 is_wcf_hack_disabled (void)
3909 static gboolean disabled;
3910 static gboolean inited = FALSE;
3912 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3919 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3921 MonoMethodSignature *cmsig, *imsig;
3922 if (strcmp (im->name, cm->name) == 0) {
3923 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3924 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3927 if (! slot_is_empty) {
3928 if (require_newslot) {
3929 if (! interface_is_explicitly_implemented_by_class) {
3930 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3933 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3934 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3938 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3941 cmsig = mono_method_signature (cm);
3942 imsig = mono_method_signature (im);
3943 if (!cmsig || !imsig) {
3944 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3948 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3949 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3950 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3951 TRACE_INTERFACE_VTABLE (printf ("]"));
3954 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3955 if (mono_security_core_clr_enabled ())
3956 mono_security_core_clr_check_override (class, cm, im);
3958 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3959 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3960 char *body_name = mono_method_full_name (cm, TRUE);
3961 char *decl_name = mono_method_full_name (im, TRUE);
3962 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));
3970 MonoClass *ic = im->klass;
3971 const char *ic_name_space = ic->name_space;
3972 const char *ic_name = ic->name;
3975 if (! require_newslot) {
3976 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3979 if (cm->klass->rank == 0) {
3980 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3983 cmsig = mono_method_signature (cm);
3984 imsig = mono_method_signature (im);
3985 if (!cmsig || !imsig) {
3986 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3990 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3991 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3992 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3993 TRACE_INTERFACE_VTABLE (printf ("]"));
3996 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3997 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4000 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4001 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4004 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))) {
4005 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4009 subname = strstr (cm->name, ic_name_space);
4010 if (subname != cm->name) {
4011 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4014 subname += strlen (ic_name_space);
4015 if (subname [0] != '.') {
4016 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4020 if (strstr (subname, ic_name) != subname) {
4021 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4024 subname += strlen (ic_name);
4025 if (subname [0] != '.') {
4026 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4030 if (strcmp (subname, im->name) != 0) {
4031 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4035 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4036 if (mono_security_core_clr_enabled ())
4037 mono_security_core_clr_check_override (class, cm, im);
4039 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4040 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4041 char *body_name = mono_method_full_name (cm, TRUE);
4042 char *decl_name = mono_method_full_name (im, TRUE);
4043 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));
4053 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4055 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4056 MonoMethod *method = key;
4057 MonoMethod *override = value;
4058 MonoClass *method_class = mono_method_get_class (method);
4059 MonoClass *override_class = mono_method_get_class (override);
4061 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4062 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4063 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4066 print_overrides (GHashTable *override_map, const char *message) {
4068 printf ("Override map \"%s\" START:\n", message);
4069 g_hash_table_foreach (override_map, foreach_override, NULL);
4070 printf ("Override map \"%s\" END.\n", message);
4072 printf ("Override map \"%s\" EMPTY.\n", message);
4076 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4077 char *full_name = mono_type_full_name (&class->byval_arg);
4081 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4083 if (print_interfaces) {
4084 print_implemented_interfaces (class);
4085 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4088 if (class->parent) {
4089 parent_size = class->parent->vtable_size;
4093 for (i = 0; i < size; ++i) {
4094 MonoMethod *cm = vtable [i];
4095 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4096 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4098 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4106 #if VERIFY_INTERFACE_VTABLE_CODE
4108 mono_method_try_get_vtable_index (MonoMethod *method)
4110 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4111 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4112 if (imethod->declaring->is_generic)
4113 return imethod->declaring->slot;
4115 return method->slot;
4119 mono_class_verify_vtable (MonoClass *class)
4122 char *full_name = mono_type_full_name (&class->byval_arg);
4124 printf ("*** Verifying VTable of class '%s' \n", full_name);
4128 if (!class->methods)
4131 for (i = 0; i < class->method.count; ++i) {
4132 MonoMethod *cm = class->methods [i];
4135 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4139 full_name = mono_method_full_name (cm, TRUE);
4141 slot = mono_method_try_get_vtable_index (cm);
4143 if (slot >= class->vtable_size) {
4144 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4148 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4149 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4150 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4151 g_free (other_name);
4154 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4161 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4163 char *method_signature;
4166 for (index = 0; index < onum; ++index) {
4167 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4168 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4170 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4171 type_name = mono_type_full_name (&class->byval_arg);
4172 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4173 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4174 g_free (method_signature);
4176 mono_class_setup_methods (class);
4177 if (class->exception_type) {
4178 char *name = mono_type_get_full_name (class);
4179 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4183 for (index = 0; index < class->method.count; ++index) {
4184 MonoMethod *cm = class->methods [index];
4185 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4187 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4188 g_free (method_signature);
4193 mono_method_get_method_definition (MonoMethod *method)
4195 while (method->is_inflated)
4196 method = ((MonoMethodInflated*)method)->declaring;
4201 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4205 for (i = 0; i < onum; ++i) {
4206 MonoMethod *decl = overrides [i * 2];
4207 MonoMethod *body = overrides [i * 2 + 1];
4209 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4210 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4214 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4215 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4216 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4218 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4222 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4223 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4224 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4226 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4230 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4231 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4235 body = mono_method_get_method_definition (body);
4236 decl = mono_method_get_method_definition (decl);
4238 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4239 char *body_name = mono_method_full_name (body, TRUE);
4240 char *decl_name = mono_method_full_name (decl, TRUE);
4241 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));
4251 mono_class_need_stelemref_method (MonoClass *class)
4253 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4257 * LOCKING: this is supposed to be called with the loader lock held.
4260 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4264 MonoMethod **vtable;
4265 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4266 GPtrArray *ifaces = NULL;
4267 GHashTable *override_map = NULL;
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))) {
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)) {
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 if (mono_security_core_clr_enabled ())
4611 mono_security_core_clr_check_override (class, cm, m1);
4613 slot = mono_method_get_vtable_slot (m1);
4617 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4618 char *body_name = mono_method_full_name (cm, TRUE);
4619 char *decl_name = mono_method_full_name (m1, TRUE);
4620 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));
4626 g_assert (cm->slot < max_vtsize);
4628 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4629 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4630 mono_method_full_name (m1, 1), m1,
4631 mono_method_full_name (cm, 1), cm));
4632 g_hash_table_insert (override_map, m1, cm);
4636 if (k->exception_type)
4646 /*Non final newslot methods must be given a non-interface vtable slot*/
4647 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4651 cm->slot = cur_slot++;
4653 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4654 vtable [cm->slot] = cm;
4657 /* override non interface methods */
4658 for (i = 0; i < onum; i++) {
4659 MonoMethod *decl = overrides [i*2];
4660 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4661 g_assert (decl->slot != -1);
4662 vtable [decl->slot] = overrides [i*2 + 1];
4663 overrides [i * 2 + 1]->slot = decl->slot;
4665 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4666 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4667 mono_method_full_name (decl, 1), decl,
4668 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4669 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4671 if (mono_security_core_clr_enabled ())
4672 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4677 * If a method occupies more than one place in the vtable, and it is
4678 * overriden, then change the other occurances too.
4683 for (i = 0; i < max_vtsize; ++i)
4685 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4687 cm = g_hash_table_lookup (override_map, vtable [i]);
4692 g_hash_table_destroy (override_map);
4693 override_map = NULL;
4696 g_slist_free (virt_methods);
4697 virt_methods = NULL;
4699 /* Ensure that all vtable slots are filled with concrete instance methods */
4700 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4701 for (i = 0; i < cur_slot; ++i) {
4702 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4703 char *type_name = mono_type_get_full_name (class);
4704 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4705 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));
4707 g_free (method_name);
4713 if (class->generic_class) {
4714 MonoClass *gklass = class->generic_class->container_class;
4716 mono_class_init (gklass);
4718 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4720 /* Check that the vtable_size value computed in mono_class_init () is correct */
4721 if (class->vtable_size)
4722 g_assert (cur_slot == class->vtable_size);
4723 class->vtable_size = cur_slot;
4726 /* Try to share the vtable with our parent. */
4727 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4728 mono_memory_barrier ();
4729 class->vtable = class->parent->vtable;
4731 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4732 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4733 mono_memory_barrier ();
4734 class->vtable = tmp;
4737 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4738 if (mono_print_vtable) {
4741 print_implemented_interfaces (class);
4743 for (i = 0; i <= max_iid; i++)
4744 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4747 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4748 class->vtable_size, icount);
4750 for (i = 0; i < cur_slot; ++i) {
4755 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4756 mono_method_full_name (cm, TRUE));
4762 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4763 class->name, max_iid);
4765 for (i = 0; i < class->interface_count; i++) {
4766 ic = class->interfaces [i];
4767 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4768 mono_class_interface_offset (class, ic),
4769 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4772 for (k = class->parent; k ; k = k->parent) {
4773 for (i = 0; i < k->interface_count; i++) {
4774 ic = k->interfaces [i];
4775 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4776 mono_class_interface_offset (class, ic),
4777 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4783 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4788 char *name = mono_type_get_full_name (class);
4789 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4792 g_hash_table_destroy (override_map);
4794 g_slist_free (virt_methods);
4799 * mono_method_get_vtable_slot:
4801 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4802 * LOCKING: Acquires the loader lock.
4804 * FIXME Use proper MonoError machinery here.
4807 mono_method_get_vtable_slot (MonoMethod *method)
4809 if (method->slot == -1) {
4810 mono_class_setup_vtable (method->klass);
4811 if (method->klass->exception_type)
4813 if (method->slot == -1) {
4817 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4818 g_assert (method->klass->generic_class);
4819 gklass = method->klass->generic_class->container_class;
4820 mono_class_setup_methods (method->klass);
4821 g_assert (method->klass->methods);
4822 for (i = 0; i < method->klass->method.count; ++i) {
4823 if (method->klass->methods [i] == method)
4826 g_assert (i < method->klass->method.count);
4827 g_assert (gklass->methods);
4828 method->slot = gklass->methods [i]->slot;
4830 g_assert (method->slot != -1);
4832 return method->slot;
4836 * mono_method_get_vtable_index:
4839 * Returns the index into the runtime vtable to access the method or,
4840 * in the case of a virtual generic method, the virtual generic method
4841 * thunk. Returns -1 on failure.
4843 * FIXME Use proper MonoError machinery here.
4846 mono_method_get_vtable_index (MonoMethod *method)
4848 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4849 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4850 if (imethod->declaring->is_generic)
4851 return mono_method_get_vtable_slot (imethod->declaring);
4853 return mono_method_get_vtable_slot (method);
4856 static MonoMethod *default_ghc = NULL;
4857 static MonoMethod *default_finalize = NULL;
4858 static int finalize_slot = -1;
4859 static int ghc_slot = -1;
4862 initialize_object_slots (MonoClass *class)
4867 if (class == mono_defaults.object_class) {
4868 mono_class_setup_vtable (class);
4869 for (i = 0; i < class->vtable_size; ++i) {
4870 MonoMethod *cm = class->vtable [i];
4872 if (!strcmp (cm->name, "GetHashCode"))
4874 else if (!strcmp (cm->name, "Finalize"))
4878 g_assert (ghc_slot > 0);
4879 default_ghc = class->vtable [ghc_slot];
4881 g_assert (finalize_slot > 0);
4882 default_finalize = class->vtable [finalize_slot];
4887 MonoMethod *array_method;
4889 } GenericArrayMethodInfo;
4891 static int generic_array_method_num = 0;
4892 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4895 generic_array_methods (MonoClass *class)
4897 int i, count_generic = 0;
4898 GList *list = NULL, *tmp;
4899 if (generic_array_method_num)
4900 return generic_array_method_num;
4901 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4902 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4903 for (i = 0; i < class->parent->method.count; i++) {
4904 MonoMethod *m = class->parent->methods [i];
4905 if (!strncmp (m->name, "InternalArray__", 15)) {
4907 list = g_list_prepend (list, m);
4910 list = g_list_reverse (list);
4911 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4913 for (tmp = list; tmp; tmp = tmp->next) {
4914 const char *mname, *iname;
4916 MonoMethod *m = tmp->data;
4917 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4918 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4920 generic_array_method_info [i].array_method = m;
4921 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4922 iname = "System.Collections.Generic.ICollection`1.";
4923 mname = m->name + 27;
4924 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4925 iname = "System.Collections.Generic.IEnumerable`1.";
4926 mname = m->name + 27;
4927 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4928 iname = "System.Collections.Generic.IReadOnlyList`1.";
4929 mname = m->name + strlen (ireadonlylist_prefix);
4930 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4931 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4932 mname = m->name + strlen (ireadonlycollection_prefix);
4933 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4934 iname = "System.Collections.Generic.IList`1.";
4935 mname = m->name + 15;
4937 g_assert_not_reached ();
4940 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4941 strcpy (name, iname);
4942 strcpy (name + strlen (iname), mname);
4943 generic_array_method_info [i].name = name;
4946 /*g_print ("array generic methods: %d\n", count_generic);*/
4948 generic_array_method_num = count_generic;
4950 return generic_array_method_num;
4954 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4956 MonoGenericContext tmp_context;
4959 tmp_context.class_inst = NULL;
4960 tmp_context.method_inst = iface->generic_class->context.class_inst;
4961 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4963 for (i = 0; i < generic_array_method_num; i++) {
4965 MonoMethod *m = generic_array_method_info [i].array_method;
4966 MonoMethod *inflated;
4968 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4969 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4970 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4975 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4977 int null_length = strlen ("(null)");
4978 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4979 char *s = mono_image_alloc (image, len);
4982 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4983 g_assert (result == len - 1);
4989 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4991 gpointer exception_data = NULL;
4993 switch (error->exception_type) {
4994 case MONO_EXCEPTION_TYPE_LOAD:
4995 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4998 case MONO_EXCEPTION_MISSING_METHOD:
4999 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5002 case MONO_EXCEPTION_MISSING_FIELD: {
5003 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5004 const char *class_name;
5007 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5009 class_name = error->klass->name;
5011 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5014 g_free ((void*)class_name);
5018 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5021 if (error->ref_only)
5022 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.";
5024 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5026 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5030 case MONO_EXCEPTION_BAD_IMAGE:
5031 exception_data = error->msg;
5035 g_assert_not_reached ();
5038 mono_class_set_failure (class, error->exception_type, exception_data);
5043 * @class: the class to initialize
5045 * Compute the instance_size, class_size and other infos that cannot be
5046 * computed at mono_class_get() time. Also compute vtable_size if possible.
5047 * Returns TRUE on success or FALSE if there was a problem in loading
5048 * the type (incorrect assemblies, missing assemblies, methods, etc).
5050 * LOCKING: Acquires the loader lock.
5053 mono_class_init (MonoClass *class)
5056 MonoCachedClassInfo cached_info;
5057 gboolean has_cached_info;
5061 /* Double-checking locking pattern */
5062 if (class->inited || class->exception_type)
5063 return class->exception_type == MONO_EXCEPTION_NONE;
5065 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5067 /* We do everything inside the lock to prevent races */
5068 mono_loader_lock ();
5070 if (class->inited || class->exception_type) {
5071 mono_loader_unlock ();
5072 /* Somebody might have gotten in before us */
5073 return class->exception_type == MONO_EXCEPTION_NONE;
5076 if (class->init_pending) {
5077 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5081 class->init_pending = 1;
5083 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5084 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5089 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5090 MonoClass *element_class = class->element_class;
5091 if (!element_class->inited)
5092 mono_class_init (element_class);
5093 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5094 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5099 mono_stats.initialized_class_count++;
5101 if (class->generic_class && !class->generic_class->is_dynamic) {
5102 MonoClass *gklass = class->generic_class->container_class;
5104 mono_stats.generic_class_count++;
5106 class->method = gklass->method;
5107 class->field = gklass->field;
5109 mono_class_init (gklass);
5110 // FIXME: Why is this needed ?
5111 if (!gklass->exception_type)
5112 mono_class_setup_methods (gklass);
5113 if (gklass->exception_type) {
5114 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5118 if (MONO_CLASS_IS_INTERFACE (class))
5119 class->interface_id = mono_get_unique_iid (class);
5122 if (class->parent && !class->parent->inited)
5123 mono_class_init (class->parent);
5125 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5127 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5128 class->nested_classes_inited = TRUE;
5131 * Computes the size used by the fields, and their locations
5133 if (has_cached_info) {
5134 class->instance_size = cached_info.instance_size;
5135 class->sizes.class_size = cached_info.class_size;
5136 class->packing_size = cached_info.packing_size;
5137 class->min_align = cached_info.min_align;
5138 class->blittable = cached_info.blittable;
5139 class->has_references = cached_info.has_references;
5140 class->has_static_refs = cached_info.has_static_refs;
5141 class->no_special_static_fields = cached_info.no_special_static_fields;
5144 if (!class->size_inited){
5145 mono_class_setup_fields (class);
5146 if (class->exception_type || mono_loader_get_last_error ())
5150 /* Initialize arrays */
5152 class->method.count = 3 + (class->rank > 1? 2: 1);
5154 if (class->interface_count) {
5155 int count_generic = generic_array_methods (class);
5156 class->method.count += class->interface_count * count_generic;
5160 mono_class_setup_supertypes (class);
5163 initialize_object_slots (class);
5166 * Initialize the rest of the data without creating a generic vtable if possible.
5167 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5168 * also avoid computing a generic vtable.
5170 if (has_cached_info) {
5172 class->vtable_size = cached_info.vtable_size;
5173 class->has_finalize = cached_info.has_finalize;
5174 class->has_finalize_inited = TRUE;
5175 class->ghcimpl = cached_info.ghcimpl;
5176 class->has_cctor = cached_info.has_cctor;
5177 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5178 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5179 * The first slot if for array with.
5181 static int szarray_vtable_size[2] = { 0 };
5183 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5186 if (!szarray_vtable_size [slot]) {
5187 mono_class_setup_vtable (class);
5188 szarray_vtable_size [slot] = class->vtable_size;
5190 class->vtable_size = szarray_vtable_size[slot];
5192 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5193 MonoClass *gklass = class->generic_class->container_class;
5195 /* Generic instance case */
5196 class->ghcimpl = gklass->ghcimpl;
5197 class->has_cctor = gklass->has_cctor;
5199 mono_class_setup_vtable (gklass);
5200 if (gklass->exception_type) {
5201 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5205 class->vtable_size = gklass->vtable_size;
5209 /* ghcimpl is not currently used
5211 if (class->parent) {
5212 MonoMethod *cmethod = class->vtable [ghc_slot];
5213 if (cmethod->is_inflated)
5214 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5215 if (cmethod == default_ghc) {
5221 /* C# doesn't allow interfaces to have cctors */
5222 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5223 MonoMethod *cmethod = NULL;
5225 if (class->type_token) {
5226 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5227 /* The find_method function ignores the 'flags' argument */
5228 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5229 class->has_cctor = 1;
5231 mono_class_setup_methods (class);
5232 if (class->exception_type)
5235 for (i = 0; i < class->method.count; ++i) {
5236 MonoMethod *method = class->methods [i];
5237 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5238 (strcmp (".cctor", method->name) == 0)) {
5239 class->has_cctor = 1;
5247 if (class->parent) {
5248 int first_iface_slot;
5249 /* This will compute class->parent->vtable_size for some classes */
5250 mono_class_init (class->parent);
5251 if (class->parent->exception_type) {
5252 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5255 if (mono_loader_get_last_error ())
5257 if (!class->parent->vtable_size) {
5258 /* FIXME: Get rid of this somehow */
5259 mono_class_setup_vtable (class->parent);
5260 if (class->parent->exception_type) {
5261 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5264 if (mono_loader_get_last_error ())
5267 first_iface_slot = class->parent->vtable_size;
5268 if (mono_class_need_stelemref_method (class))
5270 setup_interface_offsets (class, first_iface_slot, TRUE);
5272 setup_interface_offsets (class, 0, TRUE);
5275 if (mono_security_core_clr_enabled ())
5276 mono_security_core_clr_check_inheritance (class);
5278 if (mono_loader_get_last_error ()) {
5279 if (class->exception_type == MONO_EXCEPTION_NONE) {
5280 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5282 mono_loader_clear_error ();
5285 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5286 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5291 /* Because of the double-checking locking pattern */
5292 mono_memory_barrier ();
5294 class->init_pending = 0;
5296 mono_loader_unlock ();
5298 return class->exception_type == MONO_EXCEPTION_NONE;
5302 * mono_class_has_finalizer:
5304 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5308 mono_class_has_finalizer (MonoClass *klass)
5310 MonoClass *class = klass;
5311 gboolean has_finalize = FALSE;
5313 if (klass->has_finalize_inited)
5314 return klass->has_finalize;
5316 /* Interfaces and valuetypes are not supposed to have finalizers */
5317 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5318 MonoMethod *cmethod = NULL;
5320 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5321 } else if (class->generic_class) {
5322 MonoClass *gklass = class->generic_class->container_class;
5324 has_finalize = mono_class_has_finalizer (gklass);
5325 } else if (class->parent && class->parent->has_finalize) {
5326 has_finalize = TRUE;
5328 if (class->parent) {
5330 * Can't search in metadata for a method named Finalize, because that
5331 * ignores overrides.
5333 mono_class_setup_vtable (class);
5334 if (class->exception_type || mono_loader_get_last_error ())
5337 cmethod = class->vtable [finalize_slot];
5341 g_assert (class->vtable_size > finalize_slot);
5343 if (class->parent) {
5344 if (cmethod->is_inflated)
5345 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5346 if (cmethod != default_finalize)
5347 has_finalize = TRUE;
5353 mono_image_lock (klass->image);
5355 if (!klass->has_finalize_inited) {
5356 klass->has_finalize = has_finalize ? 1 : 0;
5358 mono_memory_barrier ();
5359 klass->has_finalize_inited = TRUE;
5362 mono_image_unlock (klass->image);
5364 return klass->has_finalize;
5368 mono_is_corlib_image (MonoImage *image)
5370 /* FIXME: allow the dynamic case for our compilers and with full trust */
5371 if (image_is_dynamic (image))
5372 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5374 return image == mono_defaults.corlib;
5378 * LOCKING: this assumes the loader lock is held
5381 mono_class_setup_mono_type (MonoClass *class)
5383 const char *name = class->name;
5384 const char *nspace = class->name_space;
5385 gboolean is_corlib = mono_is_corlib_image (class->image);
5387 class->this_arg.byref = 1;
5388 class->this_arg.data.klass = class;
5389 class->this_arg.type = MONO_TYPE_CLASS;
5390 class->byval_arg.data.klass = class;
5391 class->byval_arg.type = MONO_TYPE_CLASS;
5393 if (is_corlib && !strcmp (nspace, "System")) {
5394 if (!strcmp (name, "ValueType")) {
5396 * do not set the valuetype bit for System.ValueType.
5397 * class->valuetype = 1;
5399 class->blittable = TRUE;
5400 } else if (!strcmp (name, "Enum")) {
5402 * do not set the valuetype bit for System.Enum.
5403 * class->valuetype = 1;
5405 class->valuetype = 0;
5406 class->enumtype = 0;
5407 } else if (!strcmp (name, "Object")) {
5408 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5409 } else if (!strcmp (name, "String")) {
5410 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5411 } else if (!strcmp (name, "TypedReference")) {
5412 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5416 if (class->valuetype) {
5417 int t = MONO_TYPE_VALUETYPE;
5419 if (is_corlib && !strcmp (nspace, "System")) {
5422 if (!strcmp (name, "Boolean")) {
5423 t = MONO_TYPE_BOOLEAN;
5424 } else if (!strcmp(name, "Byte")) {
5426 class->blittable = TRUE;
5430 if (!strcmp (name, "Char")) {
5435 if (!strcmp (name, "Double")) {
5437 class->blittable = TRUE;
5441 if (!strcmp (name, "Int32")) {
5443 class->blittable = TRUE;
5444 } else if (!strcmp(name, "Int16")) {
5446 class->blittable = TRUE;
5447 } else if (!strcmp(name, "Int64")) {
5449 class->blittable = TRUE;
5450 } else if (!strcmp(name, "IntPtr")) {
5452 class->blittable = TRUE;
5456 if (!strcmp (name, "Single")) {
5458 class->blittable = TRUE;
5459 } else if (!strcmp(name, "SByte")) {
5461 class->blittable = TRUE;
5465 if (!strcmp (name, "UInt32")) {
5467 class->blittable = TRUE;
5468 } else if (!strcmp(name, "UInt16")) {
5470 class->blittable = TRUE;
5471 } else if (!strcmp(name, "UInt64")) {
5473 class->blittable = TRUE;
5474 } else if (!strcmp(name, "UIntPtr")) {
5476 class->blittable = TRUE;
5480 if (!strcmp (name, "TypedReference")) {
5481 t = MONO_TYPE_TYPEDBYREF;
5482 class->blittable = TRUE;
5486 if (!strcmp (name, "Void")) {
5494 class->this_arg.type = class->byval_arg.type = t;
5497 if (MONO_CLASS_IS_INTERFACE (class))
5498 class->interface_id = mono_get_unique_iid (class);
5504 * COM initialization is delayed until needed.
5505 * However when a [ComImport] attribute is present on a type it will trigger
5506 * the initialization. This is not a problem unless the BCL being executed
5507 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5510 init_com_from_comimport (MonoClass *class)
5512 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5513 if (mono_security_core_clr_enabled ()) {
5514 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5515 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5516 /* but it can not be made available for application (i.e. user code) since all COM calls
5517 * are considered native calls. In this case we fail with a TypeLoadException (just like
5518 * Silverlight 2 does */
5519 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5524 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5526 #endif /*DISABLE_COM*/
5529 * LOCKING: this assumes the loader lock is held
5532 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5534 gboolean system_namespace;
5535 gboolean is_corlib = mono_is_corlib_image (class->image);
5537 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5539 /* if root of the hierarchy */
5540 if (system_namespace && !strcmp (class->name, "Object")) {
5541 class->parent = NULL;
5542 class->instance_size = sizeof (MonoObject);
5545 if (!strcmp (class->name, "<Module>")) {
5546 class->parent = NULL;
5547 class->instance_size = 0;
5551 if (!MONO_CLASS_IS_INTERFACE (class)) {
5552 /* Imported COM Objects always derive from __ComObject. */
5554 if (MONO_CLASS_IS_IMPORT (class)) {
5555 init_com_from_comimport (class);
5556 if (parent == mono_defaults.object_class)
5557 parent = mono_class_get_com_object_class ();
5561 /* set the parent to something useful and safe, but mark the type as broken */
5562 parent = mono_defaults.object_class;
5563 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5566 class->parent = parent;
5568 if (parent->generic_class && !parent->name) {
5570 * If the parent is a generic instance, we may get
5571 * called before it is fully initialized, especially
5572 * before it has its name.
5577 #ifndef DISABLE_REMOTING
5578 class->marshalbyref = parent->marshalbyref;
5579 class->contextbound = parent->contextbound;
5582 class->delegate = parent->delegate;
5584 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5585 mono_class_set_is_com_object (class);
5587 if (system_namespace) {
5588 #ifndef DISABLE_REMOTING
5589 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5590 class->marshalbyref = 1;
5592 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5593 class->contextbound = 1;
5595 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5596 class->delegate = 1;
5599 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5600 (strcmp (class->parent->name_space, "System") == 0)))
5601 class->valuetype = 1;
5602 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5603 class->valuetype = class->enumtype = 1;
5605 /*class->enumtype = class->parent->enumtype; */
5607 /* initialize com types if COM interfaces are present */
5609 if (MONO_CLASS_IS_IMPORT (class))
5610 init_com_from_comimport (class);
5612 class->parent = NULL;
5618 * mono_class_setup_supertypes:
5621 * Build the data structure needed to make fast type checks work.
5622 * This currently sets two fields in @class:
5623 * - idepth: distance between @class and System.Object in the type
5625 * - supertypes: array of classes: each element has a class in the hierarchy
5626 * starting from @class up to System.Object
5628 * LOCKING: This function is atomic, in case of contention we waste memory.
5631 mono_class_setup_supertypes (MonoClass *class)
5634 MonoClass **supertypes;
5636 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5640 if (class->parent && !class->parent->supertypes)
5641 mono_class_setup_supertypes (class->parent);
5643 class->idepth = class->parent->idepth + 1;
5647 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5648 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5650 if (class->parent) {
5651 supertypes [class->idepth - 1] = class;
5652 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5654 supertypes [0] = class;
5657 mono_atomic_store_release (&class->supertypes, supertypes);
5661 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5663 MonoClass *gtd = (MonoClass*)user_data;
5664 /* Only try to fix generic instances of @gtd */
5665 if (gclass->generic_class->container_class != gtd)
5668 /* Check if the generic instance has no parent. */
5669 if (gtd->parent && !gclass->parent)
5670 mono_generic_class_setup_parent (gclass, gtd);
5676 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5678 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5679 mono_error_set_type_load_class (error, class, msg);
5683 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5685 MonoLoaderError *lerror = mono_loader_get_last_error ();
5688 set_failure_from_loader_error (class, lerror);
5689 mono_error_set_from_loader_error (error);
5693 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5694 mono_error_set_type_load_class (error, class, msg);
5699 * mono_class_create_from_typedef:
5700 * @image: image where the token is valid
5701 * @type_token: typedef token
5702 * @error: used to return any error found while creating the type
5704 * Create the MonoClass* representing the specified type token.
5705 * @type_token must be a TypeDef token.
5707 * FIXME: don't return NULL on failure, just the the caller figure it out.
5710 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5712 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5713 MonoClass *class, *parent = NULL;
5714 guint32 cols [MONO_TYPEDEF_SIZE];
5715 guint32 cols_next [MONO_TYPEDEF_SIZE];
5716 guint tidx = mono_metadata_token_index (type_token);
5717 MonoGenericContext *context = NULL;
5718 const char *name, *nspace;
5720 MonoClass **interfaces;
5721 guint32 field_last, method_last;
5722 guint32 nesting_tokeen;
5724 mono_error_init (error);
5726 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5727 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5728 g_assert (!mono_loader_get_last_error ());
5732 mono_loader_lock ();
5734 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5735 mono_loader_unlock ();
5736 g_assert (!mono_loader_get_last_error ());
5740 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5742 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5743 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5745 class = mono_image_alloc0 (image, sizeof (MonoClass));
5748 class->name_space = nspace;
5750 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5752 class->image = image;
5753 class->type_token = type_token;
5754 class->flags = cols [MONO_TYPEDEF_FLAGS];
5756 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5758 classes_size += sizeof (MonoClass);
5761 * Check whether we're a generic type definition.
5763 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5764 if (class->generic_container) {
5765 class->is_generic = 1;
5766 class->generic_container->owner.klass = class;
5767 context = &class->generic_container->context;
5770 if (class->generic_container)
5771 enable_gclass_recording ();
5773 if (cols [MONO_TYPEDEF_EXTENDS]) {
5775 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5777 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5778 /*WARNING: this must satisfy mono_metadata_type_hash*/
5779 class->this_arg.byref = 1;
5780 class->this_arg.data.klass = class;
5781 class->this_arg.type = MONO_TYPE_CLASS;
5782 class->byval_arg.data.klass = class;
5783 class->byval_arg.type = MONO_TYPE_CLASS;
5785 parent = mono_class_get_checked (image, parent_token, error);
5786 if (parent && context) /* Always inflate */
5787 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5789 if (parent == NULL) {
5790 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5791 goto parent_failure;
5794 for (tmp = parent; tmp; tmp = tmp->parent) {
5796 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5797 goto parent_failure;
5799 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5800 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5801 goto parent_failure;
5806 mono_class_setup_parent (class, parent);
5808 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5809 mono_class_setup_mono_type (class);
5811 if (class->generic_container)
5812 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5815 * This might access class->byval_arg for recursion generated by generic constraints,
5816 * so it has to come after setup_mono_type ().
5818 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5819 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5820 if (!mono_error_ok (error)) {
5821 /*FIXME implement a mono_class_set_failure_from_mono_error */
5822 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5823 mono_loader_unlock ();
5824 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5825 g_assert (!mono_loader_get_last_error ());
5830 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5834 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5838 class->cast_class = class->element_class = class;
5840 if (!class->enumtype) {
5841 if (!mono_metadata_interfaces_from_typedef_full (
5842 image, type_token, &interfaces, &icount, FALSE, context, error)){
5844 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5845 mono_loader_unlock ();
5846 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5850 class->interfaces = interfaces;
5851 class->interface_count = icount;
5852 class->interfaces_inited = 1;
5855 /*g_print ("Load class %s\n", name);*/
5858 * Compute the field and method lists
5860 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5861 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5863 if (tt->rows > tidx){
5864 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5865 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5866 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5868 field_last = image->tables [MONO_TABLE_FIELD].rows;
5869 method_last = image->tables [MONO_TABLE_METHOD].rows;
5872 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5873 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5874 class->field.count = field_last - class->field.first;
5876 class->field.count = 0;
5878 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5879 class->method.count = method_last - class->method.first;
5881 class->method.count = 0;
5883 /* reserve space to store vector pointer in arrays */
5884 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5885 class->instance_size += 2 * sizeof (gpointer);
5886 g_assert (class->field.count == 0);
5889 if (class->enumtype) {
5890 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5891 if (!enum_basetype) {
5892 /*set it to a default value as the whole runtime can't handle this to be null*/
5893 class->cast_class = class->element_class = mono_defaults.int32_class;
5894 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5895 mono_loader_unlock ();
5896 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5897 g_assert (!mono_loader_get_last_error ());
5900 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5904 * If we're a generic type definition, load the constraints.
5905 * We must do this after the class has been constructed to make certain recursive scenarios
5908 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5909 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)));
5910 mono_loader_unlock ();
5911 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5912 g_assert (!mono_loader_get_last_error ());
5916 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5917 if (!strncmp (name, "Vector", 6))
5918 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");
5921 mono_loader_unlock ();
5923 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5924 g_assert (!mono_loader_get_last_error ());
5929 mono_class_setup_mono_type (class);
5930 mono_loader_unlock ();
5931 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5932 g_assert (!mono_loader_get_last_error ());
5936 /** is klass Nullable<T>? */
5938 mono_class_is_nullable (MonoClass *klass)
5940 return klass->generic_class != NULL &&
5941 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5945 /** if klass is T? return T */
5947 mono_class_get_nullable_param (MonoClass *klass)
5949 g_assert (mono_class_is_nullable (klass));
5950 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5954 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5958 MonoGenericClass *gclass = klass->generic_class;
5960 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5961 if (!mono_error_ok (&error)) {
5962 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5963 klass->parent = mono_defaults.object_class;
5964 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5965 mono_error_cleanup (&error);
5969 mono_class_setup_parent (klass, klass->parent);
5971 if (klass->enumtype) {
5972 klass->cast_class = gtd->cast_class;
5973 klass->element_class = gtd->element_class;
5979 * Create the `MonoClass' for an instantiation of a generic type.
5980 * We only do this if we actually need it.
5983 mono_generic_class_get_class (MonoGenericClass *gclass)
5985 MonoClass *klass, *gklass;
5987 if (gclass->cached_class)
5988 return gclass->cached_class;
5990 mono_loader_lock ();
5991 if (gclass->cached_class) {
5992 mono_loader_unlock ();
5993 return gclass->cached_class;
5996 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5998 gklass = gclass->container_class;
6000 if (record_gclass_instantiation > 0)
6001 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6003 if (gklass->nested_in) {
6004 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6005 klass->nested_in = gklass->nested_in;
6008 klass->name = gklass->name;
6009 klass->name_space = gklass->name_space;
6011 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6013 klass->image = gklass->image;
6014 klass->flags = gklass->flags;
6015 klass->type_token = gklass->type_token;
6016 klass->field.count = gklass->field.count;
6018 klass->is_inflated = 1;
6019 klass->generic_class = gclass;
6021 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6022 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6023 klass->this_arg.byref = TRUE;
6024 klass->enumtype = gklass->enumtype;
6025 klass->valuetype = gklass->valuetype;
6027 klass->cast_class = klass->element_class = klass;
6029 if (mono_class_is_nullable (klass))
6030 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6033 * We're not interested in the nested classes of a generic instance.
6034 * We use the generic type definition to look for nested classes.
6037 mono_generic_class_setup_parent (klass, gklass);
6039 if (gclass->is_dynamic) {
6041 * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
6042 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6043 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6045 if (!gklass->wastypebuilder)
6048 mono_class_setup_supertypes (klass);
6050 if (klass->enumtype) {
6052 * For enums, gklass->fields might not been set, but instance_size etc. is
6053 * already set in mono_reflection_create_internal_class (). For non-enums,
6054 * these will be computed normally in mono_class_layout_fields ().
6056 klass->instance_size = gklass->instance_size;
6057 klass->sizes.class_size = gklass->sizes.class_size;
6058 mono_memory_barrier ();
6059 klass->size_inited = 1;
6063 mono_memory_barrier ();
6064 gclass->cached_class = klass;
6066 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6068 inflated_classes ++;
6069 inflated_classes_size += sizeof (MonoClass);
6071 mono_loader_unlock ();
6077 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6079 MonoClass *klass, **ptr;
6081 MonoGenericContainer *container = mono_generic_param_owner (param);
6085 image = mono_defaults.corlib;
6087 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6088 classes_size += sizeof (MonoClass);
6091 klass->name = pinfo->name;
6093 int n = mono_generic_param_num (param);
6094 klass->name = mono_image_alloc0 (image, 16);
6095 sprintf ((char*)klass->name, "%d", n);
6100 MonoMethod *omethod = container->owner.method;
6101 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6103 MonoClass *oklass = container->owner.klass;
6104 klass->name_space = oklass ? oklass->name_space : "";
6107 klass->name_space = "";
6110 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6114 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6118 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6119 klass->parent = pinfo->constraints [0];
6121 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6122 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6124 klass->parent = mono_defaults.object_class;
6127 if (count - pos > 0) {
6128 klass->interface_count = count - pos;
6129 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6130 klass->interfaces_inited = TRUE;
6131 for (i = pos; i < count; i++)
6132 klass->interfaces [i - pos] = pinfo->constraints [i];
6135 klass->image = image;
6137 klass->inited = TRUE;
6138 klass->cast_class = klass->element_class = klass;
6139 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6141 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6142 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6143 klass->this_arg.byref = TRUE;
6145 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6146 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6148 /*Init these fields to sane values*/
6149 klass->min_align = 1;
6151 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6152 * constrained to, the JIT depends on this.
6154 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6155 mono_memory_barrier ();
6156 klass->size_inited = 1;
6157 klass->setup_fields_called = 1;
6159 mono_class_setup_supertypes (klass);
6161 if (count - pos > 0) {
6162 mono_class_setup_vtable (klass->parent);
6163 if (klass->parent->exception_type)
6164 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6166 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6172 #define FAST_CACHE_SIZE 16
6175 * LOCKING: Takes the image lock depending on @take_lock.
6178 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6180 int n = mono_generic_param_num (param);
6181 MonoImage *image = param->image;
6182 MonoClass *klass = NULL;
6187 if (param->gshared_constraint) {
6188 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6191 mono_image_lock (image);
6192 klass = g_hash_table_lookup (ht, param);
6194 mono_image_unlock (image);
6199 if (n < FAST_CACHE_SIZE) {
6201 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6203 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6205 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6208 mono_image_lock (image);
6209 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6211 mono_image_unlock (image);
6218 * LOCKING: Image lock (param->image) must be held
6221 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6223 int n = mono_generic_param_num (param);
6224 MonoImage *image = param->image;
6228 if (param->gshared_constraint) {
6229 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6231 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6232 mono_memory_barrier ();
6234 image->mvar_cache_constrained = ht;
6236 image->var_cache_constrained = ht;
6238 g_hash_table_insert (ht, param, klass);
6239 } else if (n < FAST_CACHE_SIZE) {
6241 /* Requires locking to avoid droping an already published class */
6242 if (!image->mvar_cache_fast)
6243 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6244 image->mvar_cache_fast [n] = klass;
6246 if (!image->var_cache_fast)
6247 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6248 image->var_cache_fast [n] = klass;
6251 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6253 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6255 ht = g_hash_table_new (NULL, NULL);
6256 mono_memory_barrier ();
6258 image->mvar_cache_slow = ht;
6260 image->var_cache_slow = ht;
6263 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6268 * LOCKING: Acquires the image lock (@image).
6271 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6273 MonoGenericContainer *container = mono_generic_param_owner (param);
6274 MonoGenericParamInfo *pinfo = NULL;
6275 MonoClass *klass, *klass2;
6278 pinfo = mono_generic_param_info (param);
6279 klass = pinfo->pklass;
6282 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6287 if (!image && container) {
6289 MonoMethod *method = container->owner.method;
6290 image = (method && method->klass) ? method->klass->image : NULL;
6292 MonoClass *klass = container->owner.klass;
6293 // FIXME: 'klass' should not be null
6294 // But, monodis creates GenericContainers without associating a owner to it
6295 image = klass ? klass->image : NULL;
6299 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6301 mono_memory_barrier ();
6303 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6304 image = mono_defaults.corlib;
6306 mono_image_lock (image);
6308 klass2 = pinfo->pklass;
6310 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6316 pinfo->pklass = klass;
6318 set_anon_gparam_class (param, is_mvar, klass);
6320 mono_image_unlock (image);
6322 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6324 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6326 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6332 mono_ptr_class_get (MonoType *type)
6335 MonoClass *el_class;
6339 el_class = mono_class_from_mono_type (type);
6340 image = el_class->image;
6342 mono_image_lock (image);
6343 if (image->ptr_cache) {
6344 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6345 mono_image_unlock (image);
6349 mono_image_unlock (image);
6351 result = mono_image_alloc0 (image, sizeof (MonoClass));
6353 classes_size += sizeof (MonoClass);
6355 result->parent = NULL; /* no parent for PTR types */
6356 result->name_space = el_class->name_space;
6357 name = g_strdup_printf ("%s*", el_class->name);
6358 result->name = mono_image_strdup (image, name);
6361 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6363 result->image = el_class->image;
6364 result->inited = TRUE;
6365 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6366 /* Can pointers get boxed? */
6367 result->instance_size = sizeof (gpointer);
6368 result->cast_class = result->element_class = el_class;
6369 result->blittable = TRUE;
6371 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6372 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6373 result->this_arg.byref = TRUE;
6375 mono_class_setup_supertypes (result);
6377 mono_image_lock (image);
6378 if (image->ptr_cache) {
6380 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6381 mono_image_unlock (image);
6382 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6386 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6388 g_hash_table_insert (image->ptr_cache, el_class, result);
6389 mono_image_unlock (image);
6391 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6397 mono_fnptr_class_get (MonoMethodSignature *sig)
6400 static GHashTable *ptr_hash = NULL;
6402 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6404 mono_loader_lock ();
6407 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6409 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6410 mono_loader_unlock ();
6413 result = g_new0 (MonoClass, 1);
6415 result->parent = NULL; /* no parent for PTR types */
6416 result->name_space = "System";
6417 result->name = "MonoFNPtrFakeClass";
6419 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6421 result->image = mono_defaults.corlib; /* need to fix... */
6422 result->inited = TRUE;
6423 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6424 /* Can pointers get boxed? */
6425 result->instance_size = sizeof (gpointer);
6426 result->cast_class = result->element_class = result;
6427 result->blittable = TRUE;
6429 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6430 result->this_arg.data.method = result->byval_arg.data.method = sig;
6431 result->this_arg.byref = TRUE;
6432 result->blittable = TRUE;
6434 mono_class_setup_supertypes (result);
6436 g_hash_table_insert (ptr_hash, sig, result);
6438 mono_loader_unlock ();
6440 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6446 mono_class_from_mono_type (MonoType *type)
6448 switch (type->type) {
6449 case MONO_TYPE_OBJECT:
6450 return type->data.klass? type->data.klass: mono_defaults.object_class;
6451 case MONO_TYPE_VOID:
6452 return type->data.klass? type->data.klass: mono_defaults.void_class;
6453 case MONO_TYPE_BOOLEAN:
6454 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6455 case MONO_TYPE_CHAR:
6456 return type->data.klass? type->data.klass: mono_defaults.char_class;
6458 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6460 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6462 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6464 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6466 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6468 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6470 return type->data.klass? type->data.klass: mono_defaults.int_class;
6472 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6474 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6476 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6478 return type->data.klass? type->data.klass: mono_defaults.single_class;
6480 return type->data.klass? type->data.klass: mono_defaults.double_class;
6481 case MONO_TYPE_STRING:
6482 return type->data.klass? type->data.klass: mono_defaults.string_class;
6483 case MONO_TYPE_TYPEDBYREF:
6484 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6485 case MONO_TYPE_ARRAY:
6486 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6488 return mono_ptr_class_get (type->data.type);
6489 case MONO_TYPE_FNPTR:
6490 return mono_fnptr_class_get (type->data.method);
6491 case MONO_TYPE_SZARRAY:
6492 return mono_array_class_get (type->data.klass, 1);
6493 case MONO_TYPE_CLASS:
6494 case MONO_TYPE_VALUETYPE:
6495 return type->data.klass;
6496 case MONO_TYPE_GENERICINST:
6497 return mono_generic_class_get_class (type->data.generic_class);
6499 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6500 case MONO_TYPE_MVAR:
6501 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6503 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6504 g_assert_not_reached ();
6511 * mono_type_retrieve_from_typespec
6512 * @image: context where the image is created
6513 * @type_spec: typespec token
6514 * @context: the generic context used to evaluate generic instantiations in
6517 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6519 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6521 *did_inflate = FALSE;
6526 if (context && (context->class_inst || context->method_inst)) {
6527 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6529 if (!mono_error_ok (error)) {
6530 g_assert (!mono_loader_get_last_error ());
6536 *did_inflate = TRUE;
6543 * mono_class_create_from_typespec
6544 * @image: context where the image is created
6545 * @type_spec: typespec token
6546 * @context: the generic context used to evaluate generic instantiations in
6549 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6552 gboolean inflated = FALSE;
6553 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6554 if (!mono_error_ok (error))
6556 ret = mono_class_from_mono_type (t);
6558 mono_metadata_free_type (t);
6563 * mono_bounded_array_class_get:
6564 * @element_class: element class
6565 * @rank: the dimension of the array class
6566 * @bounded: whenever the array has non-zero bounds
6568 * Returns: a class object describing the array with element type @element_type and
6572 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6576 MonoClass *parent = NULL;
6577 GSList *list, *rootlist = NULL;
6580 gboolean corlib_type = FALSE;
6582 g_assert (rank <= 255);
6585 /* bounded only matters for one-dimensional arrays */
6588 image = eclass->image;
6590 if (rank == 1 && !bounded) {
6592 * This case is very frequent not just during compilation because of calls
6593 * from mono_class_from_mono_type (), mono_array_new (),
6594 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6596 mono_mutex_lock (&image->szarray_cache_lock);
6597 if (!image->szarray_cache)
6598 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6599 class = g_hash_table_lookup (image->szarray_cache, eclass);
6600 mono_mutex_unlock (&image->szarray_cache_lock);
6604 mono_loader_lock ();
6606 mono_loader_lock ();
6608 if (!image->array_cache)
6609 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6611 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6612 for (; list; list = list->next) {
6614 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6615 mono_loader_unlock ();
6622 /* for the building corlib use System.Array from it */
6623 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6624 parent = mono_class_from_name (image, "System", "Array");
6627 parent = mono_defaults.array_class;
6628 if (!parent->inited)
6629 mono_class_init (parent);
6632 class = mono_image_alloc0 (image, sizeof (MonoClass));
6634 class->image = image;
6635 class->name_space = eclass->name_space;
6636 nsize = strlen (eclass->name);
6637 name = g_malloc (nsize + 2 + rank + 1);
6638 memcpy (name, eclass->name, nsize);
6641 memset (name + nsize + 1, ',', rank - 1);
6643 name [nsize + rank] = '*';
6644 name [nsize + rank + bounded] = ']';
6645 name [nsize + rank + bounded + 1] = 0;
6646 class->name = mono_image_strdup (image, name);
6649 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6651 classes_size += sizeof (MonoClass);
6653 class->type_token = 0;
6654 /* all arrays are marked serializable and sealed, bug #42779 */
6655 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6656 class->parent = parent;
6657 class->instance_size = mono_class_instance_size (class->parent);
6659 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6660 /*Arrays of those two types are invalid.*/
6661 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6662 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6663 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6664 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6665 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6667 /* element_size -1 is ok as this is not an instantitable type*/
6668 class->sizes.element_size = -1;
6670 class->sizes.element_size = mono_class_array_element_size (eclass);
6672 mono_class_setup_supertypes (class);
6674 if (eclass->generic_class)
6675 mono_class_init (eclass);
6676 if (!eclass->size_inited)
6677 mono_class_setup_fields (eclass);
6678 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6679 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6681 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6685 if (eclass->enumtype)
6686 class->cast_class = eclass->element_class;
6688 class->cast_class = eclass;
6690 switch (class->cast_class->byval_arg.type) {
6692 class->cast_class = mono_defaults.byte_class;
6695 class->cast_class = mono_defaults.int16_class;
6698 #if SIZEOF_VOID_P == 4
6702 class->cast_class = mono_defaults.int32_class;
6705 #if SIZEOF_VOID_P == 8
6709 class->cast_class = mono_defaults.int64_class;
6715 class->element_class = eclass;
6717 if ((rank > 1) || bounded) {
6718 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6719 class->byval_arg.type = MONO_TYPE_ARRAY;
6720 class->byval_arg.data.array = at;
6721 at->eklass = eclass;
6723 /* FIXME: complete.... */
6725 class->byval_arg.type = MONO_TYPE_SZARRAY;
6726 class->byval_arg.data.klass = eclass;
6728 class->this_arg = class->byval_arg;
6729 class->this_arg.byref = 1;
6734 class->generic_container = eclass->generic_container;
6736 if (rank == 1 && !bounded) {
6737 MonoClass *prev_class;
6739 mono_mutex_lock (&image->szarray_cache_lock);
6740 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6742 /* Someone got in before us */
6745 g_hash_table_insert (image->szarray_cache, eclass, class);
6746 mono_mutex_unlock (&image->szarray_cache_lock);
6748 list = g_slist_append (rootlist, class);
6749 g_hash_table_insert (image->array_cache, eclass, list);
6752 mono_loader_unlock ();
6754 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6760 * mono_array_class_get:
6761 * @element_class: element class
6762 * @rank: the dimension of the array class
6764 * Returns: a class object describing the array with element type @element_type and
6768 mono_array_class_get (MonoClass *eclass, guint32 rank)
6770 return mono_bounded_array_class_get (eclass, rank, FALSE);
6774 * mono_class_instance_size:
6777 * Returns: the size of an object instance
6780 mono_class_instance_size (MonoClass *klass)
6782 if (!klass->size_inited)
6783 mono_class_init (klass);
6785 return klass->instance_size;
6789 * mono_class_min_align:
6792 * Returns: minimm alignment requirements
6795 mono_class_min_align (MonoClass *klass)
6797 if (!klass->size_inited)
6798 mono_class_init (klass);
6800 return klass->min_align;
6804 * mono_class_value_size:
6807 * This function is used for value types, and return the
6808 * space and the alignment to store that kind of value object.
6810 * Returns: the size of a value of kind @klass
6813 mono_class_value_size (MonoClass *klass, guint32 *align)
6817 /* fixme: check disable, because we still have external revereces to
6818 * mscorlib and Dummy Objects
6820 /*g_assert (klass->valuetype);*/
6822 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6825 *align = klass->min_align;
6831 * mono_class_data_size:
6834 * Returns: the size of the static class data
6837 mono_class_data_size (MonoClass *klass)
6840 mono_class_init (klass);
6841 /* This can happen with dynamically created types */
6842 if (!klass->fields_inited)
6843 mono_class_setup_fields_locking (klass);
6845 /* in arrays, sizes.class_size is unioned with element_size
6846 * and arrays have no static fields
6850 return klass->sizes.class_size;
6854 * Auxiliary routine to mono_class_get_field
6856 * Takes a field index instead of a field token.
6858 static MonoClassField *
6859 mono_class_get_field_idx (MonoClass *class, int idx)
6861 mono_class_setup_fields_locking (class);
6862 if (class->exception_type)
6866 if (class->image->uncompressed_metadata) {
6868 * class->field.first points to the FieldPtr table, while idx points into the
6869 * Field table, so we have to do a search.
6871 /*FIXME this is broken for types with multiple fields with the same name.*/
6872 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6875 for (i = 0; i < class->field.count; ++i)
6876 if (mono_field_get_name (&class->fields [i]) == name)
6877 return &class->fields [i];
6878 g_assert_not_reached ();
6880 if (class->field.count) {
6881 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6882 return &class->fields [idx - class->field.first];
6886 class = class->parent;
6892 * mono_class_get_field:
6893 * @class: the class to lookup the field.
6894 * @field_token: the field token
6896 * Returns: A MonoClassField representing the type and offset of
6897 * the field, or a NULL value if the field does not belong to this
6901 mono_class_get_field (MonoClass *class, guint32 field_token)
6903 int idx = mono_metadata_token_index (field_token);
6905 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6907 return mono_class_get_field_idx (class, idx - 1);
6911 * mono_class_get_field_from_name:
6912 * @klass: the class to lookup the field.
6913 * @name: the field name
6915 * Search the class @klass and it's parents for a field with the name @name.
6917 * Returns: the MonoClassField pointer of the named field or NULL
6920 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6922 return mono_class_get_field_from_name_full (klass, name, NULL);
6926 * mono_class_get_field_from_name_full:
6927 * @klass: the class to lookup the field.
6928 * @name: the field name
6929 * @type: the type of the fields. This optional.
6931 * Search the class @klass and it's parents for a field with the name @name and type @type.
6933 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6934 * of its generic type definition.
6936 * Returns: the MonoClassField pointer of the named field or NULL
6939 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6943 mono_class_setup_fields_locking (klass);
6944 if (klass->exception_type)
6948 for (i = 0; i < klass->field.count; ++i) {
6949 MonoClassField *field = &klass->fields [i];
6951 if (strcmp (name, mono_field_get_name (field)) != 0)
6955 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6956 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6961 klass = klass->parent;
6967 * mono_class_get_field_token:
6968 * @field: the field we need the token of
6970 * Get the token of a field. Note that the tokesn is only valid for the image
6971 * the field was loaded from. Don't use this function for fields in dynamic types.
6973 * Returns: the token representing the field in the image it was loaded from.
6976 mono_class_get_field_token (MonoClassField *field)
6978 MonoClass *klass = field->parent;
6981 mono_class_setup_fields_locking (klass);
6986 for (i = 0; i < klass->field.count; ++i) {
6987 if (&klass->fields [i] == field) {
6988 int idx = klass->field.first + i + 1;
6990 if (klass->image->uncompressed_metadata)
6991 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6992 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6995 klass = klass->parent;
6998 g_assert_not_reached ();
7003 mono_field_get_index (MonoClassField *field)
7005 int index = field - field->parent->fields;
7007 g_assert (index >= 0 && index < field->parent->field.count);
7013 * mono_class_get_field_default_value:
7015 * Return the default value of the field as a pointer into the metadata blob.
7018 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7021 guint32 constant_cols [MONO_CONSTANT_SIZE];
7023 MonoClass *klass = field->parent;
7025 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7027 if (!klass->ext || !klass->ext->field_def_values) {
7028 MonoFieldDefaultValue *def_values;
7030 mono_class_alloc_ext (klass);
7032 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7034 mono_image_lock (klass->image);
7035 mono_memory_barrier ();
7036 if (!klass->ext->field_def_values)
7037 klass->ext->field_def_values = def_values;
7038 mono_image_unlock (klass->image);
7041 field_index = mono_field_get_index (field);
7043 if (!klass->ext->field_def_values [field_index].data) {
7044 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7048 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7050 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7051 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7052 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7055 *def_type = klass->ext->field_def_values [field_index].def_type;
7056 return klass->ext->field_def_values [field_index].data;
7060 mono_property_get_index (MonoProperty *prop)
7062 int index = prop - prop->parent->ext->properties;
7064 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7070 * mono_class_get_property_default_value:
7072 * Return the default value of the field as a pointer into the metadata blob.
7075 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7078 guint32 constant_cols [MONO_CONSTANT_SIZE];
7079 MonoClass *klass = property->parent;
7081 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7083 * We don't cache here because it is not used by C# so it's quite rare, but
7084 * we still do the lookup in klass->ext because that is where the data
7085 * is stored for dynamic assemblies.
7088 if (image_is_dynamic (klass->image)) {
7089 int prop_index = mono_property_get_index (property);
7090 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7091 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7092 return klass->ext->prop_def_values [prop_index].data;
7096 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7100 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7101 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7102 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7106 mono_class_get_event_token (MonoEvent *event)
7108 MonoClass *klass = event->parent;
7113 for (i = 0; i < klass->ext->event.count; ++i) {
7114 if (&klass->ext->events [i] == event)
7115 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7118 klass = klass->parent;
7121 g_assert_not_reached ();
7126 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7130 gpointer iter = NULL;
7131 while ((p = mono_class_get_properties (klass, &iter))) {
7132 if (! strcmp (name, p->name))
7135 klass = klass->parent;
7141 mono_class_get_property_token (MonoProperty *prop)
7143 MonoClass *klass = prop->parent;
7147 gpointer iter = NULL;
7148 while ((p = mono_class_get_properties (klass, &iter))) {
7149 if (&klass->ext->properties [i] == prop)
7150 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7154 klass = klass->parent;
7157 g_assert_not_reached ();
7162 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7164 const char *name, *nspace;
7165 if (image_is_dynamic (image))
7166 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7168 switch (type_token & 0xff000000){
7169 case MONO_TOKEN_TYPE_DEF: {
7170 guint32 cols [MONO_TYPEDEF_SIZE];
7171 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7172 guint tidx = mono_metadata_token_index (type_token);
7174 if (tidx > tt->rows)
7175 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7177 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7178 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7179 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7180 if (strlen (nspace) == 0)
7181 return g_strdup_printf ("%s", name);
7183 return g_strdup_printf ("%s.%s", nspace, name);
7186 case MONO_TOKEN_TYPE_REF: {
7188 guint32 cols [MONO_TYPEREF_SIZE];
7189 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7190 guint tidx = mono_metadata_token_index (type_token);
7193 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7195 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7196 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7197 mono_error_cleanup (&error);
7201 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7202 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7203 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7204 if (strlen (nspace) == 0)
7205 return g_strdup_printf ("%s", name);
7207 return g_strdup_printf ("%s.%s", nspace, name);
7210 case MONO_TOKEN_TYPE_SPEC:
7211 return g_strdup_printf ("Typespec 0x%08x", type_token);
7213 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7218 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7220 if (image_is_dynamic (image))
7221 return g_strdup_printf ("DynamicAssembly %s", image->name);
7223 switch (type_token & 0xff000000){
7224 case MONO_TOKEN_TYPE_DEF:
7225 if (image->assembly)
7226 return mono_stringify_assembly_name (&image->assembly->aname);
7227 else if (image->assembly_name)
7228 return g_strdup (image->assembly_name);
7229 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7230 case MONO_TOKEN_TYPE_REF: {
7232 MonoAssemblyName aname;
7233 guint32 cols [MONO_TYPEREF_SIZE];
7234 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7235 guint32 idx = mono_metadata_token_index (type_token);
7238 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7240 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7241 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7242 mono_error_cleanup (&error);
7245 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7247 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7248 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7249 case MONO_RESOLUTION_SCOPE_MODULE:
7251 return g_strdup ("");
7252 case MONO_RESOLUTION_SCOPE_MODULEREF:
7254 return g_strdup ("");
7255 case MONO_RESOLUTION_SCOPE_TYPEREF:
7257 return g_strdup ("");
7258 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7259 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7260 return mono_stringify_assembly_name (&aname);
7262 g_assert_not_reached ();
7266 case MONO_TOKEN_TYPE_SPEC:
7268 return g_strdup ("");
7270 g_assert_not_reached ();
7277 * mono_class_get_full:
7278 * @image: the image where the class resides
7279 * @type_token: the token for the class
7280 * @context: the generic context used to evaluate generic instantiations in
7281 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7283 * Returns: the MonoClass that represents @type_token in @image
7286 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7290 class = mono_class_get_checked (image, type_token, &error);
7292 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7293 class = mono_class_inflate_generic_class_checked (class, context, &error);
7295 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7301 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7305 mono_error_init (error);
7306 class = mono_class_get_checked (image, type_token, error);
7308 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7309 class = mono_class_inflate_generic_class_checked (class, context, error);
7314 * mono_class_get_checked:
7315 * @image: the image where the class resides
7316 * @type_token: the token for the class
7317 * @error: error object to return any error
7319 * Returns: the MonoClass that represents @type_token in @image
7322 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7324 MonoClass *class = NULL;
7326 mono_error_init (error);
7328 if (image_is_dynamic (image)) {
7329 int table = mono_metadata_token_table (type_token);
7331 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7332 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7335 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7339 switch (type_token & 0xff000000){
7340 case MONO_TOKEN_TYPE_DEF:
7341 class = mono_class_create_from_typedef (image, type_token, error);
7343 case MONO_TOKEN_TYPE_REF:
7344 class = mono_class_from_typeref_checked (image, type_token, error);
7346 case MONO_TOKEN_TYPE_SPEC:
7347 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7350 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7354 /* Generic case, should be avoided for when a better error is possible. */
7355 if (!class && mono_error_ok (error)) {
7356 char *name = mono_class_name_from_token (image, type_token);
7357 char *assembly = mono_assembly_name_from_token (image, type_token);
7358 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7366 * mono_type_get_checked:
7367 * @image: the image where the type resides
7368 * @type_token: the token for the type
7369 * @context: the generic context used to evaluate generic instantiations in
7370 * @error: Error handling context
7372 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7374 * Returns: the MonoType that represents @type_token in @image
7377 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7379 MonoType *type = NULL;
7380 gboolean inflated = FALSE;
7382 mono_error_init (error);
7384 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7385 if (image_is_dynamic (image))
7386 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7388 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7389 MonoClass *class = mono_class_get_checked (image, type_token, error);
7392 g_assert (!mono_loader_get_last_error ());
7397 return mono_class_get_type (class);
7400 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7403 g_assert (!mono_loader_get_last_error ());
7408 MonoType *tmp = type;
7409 type = mono_class_get_type (mono_class_from_mono_type (type));
7410 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7411 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7412 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7414 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7416 if (type->type != tmp->type)
7419 mono_metadata_free_type (tmp);
7426 mono_class_get (MonoImage *image, guint32 type_token)
7428 return mono_class_get_full (image, type_token, NULL);
7432 * mono_image_init_name_cache:
7434 * Initializes the class name cache stored in image->name_cache.
7436 * LOCKING: Acquires the corresponding image lock.
7439 mono_image_init_name_cache (MonoImage *image)
7441 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7442 guint32 cols [MONO_TYPEDEF_SIZE];
7445 guint32 i, visib, nspace_index;
7446 GHashTable *name_cache2, *nspace_table;
7448 mono_image_lock (image);
7450 if (image->name_cache) {
7451 mono_image_unlock (image);
7455 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7457 if (image_is_dynamic (image)) {
7458 mono_image_unlock (image);
7462 /* Temporary hash table to avoid lookups in the nspace_table */
7463 name_cache2 = g_hash_table_new (NULL, NULL);
7465 for (i = 1; i <= t->rows; ++i) {
7466 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7467 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7469 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7470 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7472 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7474 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7475 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7477 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7478 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7479 if (!nspace_table) {
7480 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7481 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7482 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7485 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7488 /* Load type names from EXPORTEDTYPES table */
7490 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7491 guint32 cols [MONO_EXP_TYPE_SIZE];
7494 for (i = 0; i < t->rows; ++i) {
7495 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7496 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7497 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7499 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7500 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7501 if (!nspace_table) {
7502 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7503 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7504 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7507 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7511 g_hash_table_destroy (name_cache2);
7512 mono_image_unlock (image);
7515 /*FIXME Only dynamic assemblies should allow this operation.*/
7517 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7518 const char *name, guint32 index)
7520 GHashTable *nspace_table;
7521 GHashTable *name_cache;
7524 mono_image_lock (image);
7526 if (!image->name_cache)
7527 mono_image_init_name_cache (image);
7529 name_cache = image->name_cache;
7530 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7531 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7532 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7535 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7536 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7538 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7540 mono_image_unlock (image);
7549 find_nocase (gpointer key, gpointer value, gpointer user_data)
7551 char *name = (char*)key;
7552 FindUserData *data = (FindUserData*)user_data;
7554 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7555 data->value = value;
7559 * mono_class_from_name_case:
7560 * @image: The MonoImage where the type is looked up in
7561 * @name_space: the type namespace
7562 * @name: the type short name.
7563 * @deprecated: use the _checked variant
7565 * Obtains a MonoClass with a given namespace and a given name which
7566 * is located in the given MonoImage. The namespace and name
7567 * lookups are case insensitive.
7570 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7573 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7574 g_assert (!mono_error_ok (&error));
7579 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7581 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7582 guint32 cols [MONO_TYPEDEF_SIZE];
7587 mono_error_init (error);
7589 if (image_is_dynamic (image)) {
7591 FindUserData user_data;
7593 mono_image_lock (image);
7595 if (!image->name_cache)
7596 mono_image_init_name_cache (image);
7598 user_data.key = name_space;
7599 user_data.value = NULL;
7600 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7602 if (user_data.value) {
7603 GHashTable *nspace_table = (GHashTable*)user_data.value;
7605 user_data.key = name;
7606 user_data.value = NULL;
7608 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7610 if (user_data.value)
7611 token = GPOINTER_TO_UINT (user_data.value);
7614 mono_image_unlock (image);
7617 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7623 /* add a cache if needed */
7624 for (i = 1; i <= t->rows; ++i) {
7625 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7626 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7628 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7629 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7631 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7633 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7634 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7635 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7636 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7642 return_nested_in (MonoClass *class, char *nested)
7645 char *s = strchr (nested, '/');
7646 gpointer iter = NULL;
7653 while ((found = mono_class_get_nested_types (class, &iter))) {
7654 if (strcmp (found->name, nested) == 0) {
7656 return return_nested_in (found, s);
7664 search_modules (MonoImage *image, const char *name_space, const char *name)
7666 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7667 MonoImage *file_image;
7672 * The EXPORTEDTYPES table only contains public types, so have to search the
7674 * Note: image->modules contains the contents of the MODULEREF table, while
7675 * the real module list is in the FILE table.
7677 for (i = 0; i < file_table->rows; i++) {
7678 guint32 cols [MONO_FILE_SIZE];
7679 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7680 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7683 file_image = mono_image_load_file_for_image (image, i + 1);
7685 class = mono_class_from_name (file_image, name_space, name);
7695 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7697 GHashTable *nspace_table;
7698 MonoImage *loaded_image;
7705 mono_error_init (error);
7707 if ((nested = strchr (name, '/'))) {
7708 int pos = nested - name;
7709 int len = strlen (name);
7712 memcpy (buf, name, len + 1);
7714 nested = buf + pos + 1;
7718 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7719 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7720 gboolean res = get_class_from_name (image, name_space, name, &class);
7723 class = search_modules (image, name_space, name);
7725 return class ? return_nested_in (class, nested) : NULL;
7731 mono_image_lock (image);
7733 if (!image->name_cache)
7734 mono_image_init_name_cache (image);
7736 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7739 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7741 mono_image_unlock (image);
7743 if (!token && image_is_dynamic (image) && image->modules) {
7744 /* Search modules as well */
7745 for (i = 0; i < image->module_count; ++i) {
7746 MonoImage *module = image->modules [i];
7748 class = mono_class_from_name (module, name_space, name);
7755 class = search_modules (image, name_space, name);
7763 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7764 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7765 guint32 cols [MONO_EXP_TYPE_SIZE];
7768 idx = mono_metadata_token_index (token);
7770 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7772 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7773 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7774 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7777 class = mono_class_from_name (loaded_image, name_space, name);
7779 return return_nested_in (class, nested);
7781 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7782 guint32 assembly_idx;
7784 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7786 mono_assembly_load_reference (image, assembly_idx - 1);
7787 g_assert (image->references [assembly_idx - 1]);
7788 if (image->references [assembly_idx - 1] == (gpointer)-1)
7791 /* FIXME: Cycle detection */
7792 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7794 g_error ("not yet implemented");
7798 token = MONO_TOKEN_TYPE_DEF | token;
7800 class = mono_class_get_checked (image, token, error);
7802 return return_nested_in (class, nested);
7807 * mono_class_from_name:
7808 * @image: The MonoImage where the type is looked up in
7809 * @name_space: the type namespace
7810 * @name: the type short name.
7812 * Obtains a MonoClass with a given namespace and a given name which
7813 * is located in the given MonoImage.
7815 * To reference nested classes, use the "/" character as a separator.
7816 * For example use "Foo/Bar" to reference the class Bar that is nested
7817 * inside Foo, like this: "class Foo { class Bar {} }".
7820 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7825 klass = mono_class_from_name_checked (image, name_space, name, &error);
7826 if (!mono_error_ok (&error)) {
7827 mono_loader_set_error_from_mono_error (&error);
7828 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7834 * mono_class_is_subclass_of:
7835 * @klass: class to probe if it is a subclass of another one
7836 * @klassc: the class we suspect is the base class
7837 * @check_interfaces: whether we should perform interface checks
7839 * This method determines whether @klass is a subclass of @klassc.
7841 * If the @check_interfaces flag is set, then if @klassc is an interface
7842 * this method return true if the @klass implements the interface or
7843 * if @klass is an interface, if one of its base classes is @klass.
7845 * If @check_interfaces is false then, then if @klass is not an interface
7846 * then it returns true if the @klass is a subclass of @klassc.
7848 * if @klass is an interface and @klassc is System.Object, then this function
7853 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7854 gboolean check_interfaces)
7856 /*FIXME test for interfaces with variant generic arguments*/
7858 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7859 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7861 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7864 for (i = 0; i < klass->interface_count; i ++) {
7865 MonoClass *ic = klass->interfaces [i];
7870 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7875 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7878 if (klassc == mono_defaults.object_class)
7885 mono_type_is_generic_argument (MonoType *type)
7887 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7891 mono_class_has_variant_generic_params (MonoClass *klass)
7894 MonoGenericContainer *container;
7896 if (!klass->generic_class)
7899 container = klass->generic_class->container_class->generic_container;
7901 for (i = 0; i < container->type_argc; ++i)
7902 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7909 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7911 if (target == candidate)
7914 if (check_for_reference_conv &&
7915 mono_type_is_generic_argument (&target->byval_arg) &&
7916 mono_type_is_generic_argument (&candidate->byval_arg)) {
7917 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7918 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7920 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7923 if (!mono_class_is_assignable_from (target, candidate))
7929 * @container the generic container from the GTD
7930 * @klass: the class to be assigned to
7931 * @oklass: the source class
7933 * Both klass and oklass must be instances of the same generic interface.
7934 * Return true if @klass can be assigned to a @klass variable
7937 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7940 MonoType **klass_argv, **oklass_argv;
7941 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7942 MonoGenericContainer *container = klass_gtd->generic_container;
7944 if (klass == oklass)
7947 /*Viable candidates are instances of the same generic interface*/
7948 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7951 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7952 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7954 for (j = 0; j < container->type_argc; ++j) {
7955 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7956 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7958 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7962 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7963 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7965 if (param1_class != param2_class) {
7966 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7967 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7969 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7970 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7980 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7982 MonoGenericParam *gparam, *ogparam;
7983 MonoGenericParamInfo *tinfo, *cinfo;
7984 MonoClass **candidate_class;
7985 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7988 if (target == candidate)
7990 if (target->byval_arg.type != candidate->byval_arg.type)
7993 gparam = target->byval_arg.data.generic_param;
7994 ogparam = candidate->byval_arg.data.generic_param;
7995 tinfo = mono_generic_param_info (gparam);
7996 cinfo = mono_generic_param_info (ogparam);
7998 class_constraint_satisfied = FALSE;
7999 valuetype_constraint_satisfied = FALSE;
8001 /*candidate must have a super set of target's special constraints*/
8002 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8003 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8005 if (cinfo->constraints) {
8006 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8007 MonoClass *cc = *candidate_class;
8009 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8010 class_constraint_satisfied = TRUE;
8011 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8012 valuetype_constraint_satisfied = TRUE;
8015 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8016 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8018 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8020 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8022 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8023 valuetype_constraint_satisfied)) {
8028 /*candidate type constraints must be a superset of target's*/
8029 if (tinfo->constraints) {
8030 MonoClass **target_class;
8031 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8032 MonoClass *tc = *target_class;
8035 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8036 * check it's constraints since it satisfy the constraint by itself.
8038 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8041 if (!cinfo->constraints)
8044 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8045 MonoClass *cc = *candidate_class;
8047 if (mono_class_is_assignable_from (tc, cc))
8051 * This happens when we have the following:
8053 * Bar<K> where K : IFace
8054 * Foo<T, U> where T : U where U : IFace
8056 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8059 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8060 if (mono_gparam_is_assignable_from (target, cc))
8064 if (!*candidate_class)
8069 /*candidate itself must have a constraint that satisfy target*/
8070 if (cinfo->constraints) {
8071 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8072 MonoClass *cc = *candidate_class;
8073 if (mono_class_is_assignable_from (target, cc))
8081 * mono_class_is_assignable_from:
8082 * @klass: the class to be assigned to
8083 * @oklass: the source class
8085 * Return: true if an instance of object oklass can be assigned to an
8086 * instance of object @klass
8089 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8091 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8093 mono_class_init (klass);
8095 if (!oklass->inited)
8096 mono_class_init (oklass);
8098 if (klass->exception_type || oklass->exception_type)
8101 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8102 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8104 return mono_gparam_is_assignable_from (klass, oklass);
8107 if (MONO_CLASS_IS_INTERFACE (klass)) {
8108 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8109 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8110 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8114 for (i = 0; constraints [i]; ++i) {
8115 if (mono_class_is_assignable_from (klass, constraints [i]))
8123 /* interface_offsets might not be set for dynamic classes */
8124 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8126 * oklass might be a generic type parameter but they have
8127 * interface_offsets set.
8129 return mono_reflection_call_is_assignable_to (oklass, klass);
8130 if (!oklass->interface_bitmap)
8131 /* Happens with generic instances of not-yet created dynamic types */
8133 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8136 if (mono_class_has_variant_generic_params (klass)) {
8139 mono_class_setup_interfaces (oklass, &error);
8140 if (!mono_error_ok (&error)) {
8141 mono_error_cleanup (&error);
8145 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8146 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8147 MonoClass *iface = oklass->interfaces_packed [i];
8149 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8154 } else if (klass->delegate) {
8155 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8157 }else if (klass->rank) {
8158 MonoClass *eclass, *eoclass;
8160 if (oklass->rank != klass->rank)
8163 /* vectors vs. one dimensional arrays */
8164 if (oklass->byval_arg.type != klass->byval_arg.type)
8167 eclass = klass->cast_class;
8168 eoclass = oklass->cast_class;
8171 * a is b does not imply a[] is b[] when a is a valuetype, and
8172 * b is a reference type.
8175 if (eoclass->valuetype) {
8176 if ((eclass == mono_defaults.enum_class) ||
8177 (eclass == mono_defaults.enum_class->parent) ||
8178 (eclass == mono_defaults.object_class))
8182 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8183 } else if (mono_class_is_nullable (klass)) {
8184 if (mono_class_is_nullable (oklass))
8185 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8187 return mono_class_is_assignable_from (klass->cast_class, oklass);
8188 } else if (klass == mono_defaults.object_class)
8191 return mono_class_has_parent (oklass, klass);
8194 /*Check if @oklass is variant compatible with @klass.*/
8196 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8199 MonoType **klass_argv, **oklass_argv;
8200 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8201 MonoGenericContainer *container = klass_gtd->generic_container;
8203 /*Viable candidates are instances of the same generic interface*/
8204 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8207 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8208 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8210 for (j = 0; j < container->type_argc; ++j) {
8211 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8212 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8214 if (param1_class->valuetype != param2_class->valuetype)
8218 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8219 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8221 if (param1_class != param2_class) {
8222 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8223 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8225 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8226 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8234 /*Check if @candidate implements the interface @target*/
8236 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8240 gboolean is_variant = mono_class_has_variant_generic_params (target);
8242 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8243 if (mono_class_is_variant_compatible_slow (target, candidate))
8248 if (candidate == target)
8251 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8252 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8253 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8255 if (tb && tb->interfaces) {
8256 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8257 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8258 MonoClass *iface_class;
8260 /* we can't realize the type here since it can do pretty much anything. */
8263 iface_class = mono_class_from_mono_type (iface->type);
8264 if (iface_class == target)
8266 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8268 if (mono_class_implement_interface_slow (target, iface_class))
8273 /*setup_interfaces don't mono_class_init anything*/
8274 /*FIXME this doesn't handle primitive type arrays.
8275 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8276 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8278 mono_class_setup_interfaces (candidate, &error);
8279 if (!mono_error_ok (&error)) {
8280 mono_error_cleanup (&error);
8284 for (i = 0; i < candidate->interface_count; ++i) {
8285 if (candidate->interfaces [i] == target)
8288 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8291 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8295 candidate = candidate->parent;
8296 } while (candidate);
8302 * Check if @oklass can be assigned to @klass.
8303 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8306 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8308 if (candidate == target)
8310 if (target == mono_defaults.object_class)
8313 if (mono_class_has_parent (candidate, target))
8316 /*If target is not an interface there is no need to check them.*/
8317 if (MONO_CLASS_IS_INTERFACE (target))
8318 return mono_class_implement_interface_slow (target, candidate);
8320 if (target->delegate && mono_class_has_variant_generic_params (target))
8321 return mono_class_is_variant_compatible (target, candidate, FALSE);
8324 MonoClass *eclass, *eoclass;
8326 if (target->rank != candidate->rank)
8329 /* vectors vs. one dimensional arrays */
8330 if (target->byval_arg.type != candidate->byval_arg.type)
8333 eclass = target->cast_class;
8334 eoclass = candidate->cast_class;
8337 * a is b does not imply a[] is b[] when a is a valuetype, and
8338 * b is a reference type.
8341 if (eoclass->valuetype) {
8342 if ((eclass == mono_defaults.enum_class) ||
8343 (eclass == mono_defaults.enum_class->parent) ||
8344 (eclass == mono_defaults.object_class))
8348 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8350 /*FIXME properly handle nullables */
8351 /*FIXME properly handle (M)VAR */
8356 * mono_class_get_cctor:
8357 * @klass: A MonoClass pointer
8359 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8362 mono_class_get_cctor (MonoClass *klass)
8364 MonoCachedClassInfo cached_info;
8366 if (image_is_dynamic (klass->image)) {
8368 * has_cctor is not set for these classes because mono_class_init () is
8371 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8374 if (!klass->has_cctor)
8377 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8379 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8380 if (!mono_error_ok (&error))
8381 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8385 if (klass->generic_class && !klass->methods)
8386 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8388 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8392 * mono_class_get_finalizer:
8393 * @klass: The MonoClass pointer
8395 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8398 mono_class_get_finalizer (MonoClass *klass)
8400 MonoCachedClassInfo cached_info;
8403 mono_class_init (klass);
8404 if (!mono_class_has_finalizer (klass))
8407 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8409 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8410 if (!mono_error_ok (&error))
8411 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8414 mono_class_setup_vtable (klass);
8415 return klass->vtable [finalize_slot];
8420 * mono_class_needs_cctor_run:
8421 * @klass: the MonoClass pointer
8422 * @caller: a MonoMethod describing the caller
8424 * Determines whenever the class has a static constructor and whenever it
8425 * needs to be called when executing CALLER.
8428 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8432 method = mono_class_get_cctor (klass);
8434 return (method == caller) ? FALSE : TRUE;
8440 * mono_class_array_element_size:
8443 * Returns: the number of bytes an element of type @klass
8444 * uses when stored into an array.
8447 mono_class_array_element_size (MonoClass *klass)
8449 MonoType *type = &klass->byval_arg;
8452 switch (type->type) {
8455 case MONO_TYPE_BOOLEAN:
8459 case MONO_TYPE_CHAR:
8468 case MONO_TYPE_CLASS:
8469 case MONO_TYPE_STRING:
8470 case MONO_TYPE_OBJECT:
8471 case MONO_TYPE_SZARRAY:
8472 case MONO_TYPE_ARRAY:
8473 return sizeof (gpointer);
8478 case MONO_TYPE_VALUETYPE:
8479 if (type->data.klass->enumtype) {
8480 type = mono_class_enum_basetype (type->data.klass);
8481 klass = klass->element_class;
8484 return mono_class_instance_size (klass) - sizeof (MonoObject);
8485 case MONO_TYPE_GENERICINST:
8486 type = &type->data.generic_class->container_class->byval_arg;
8489 case MONO_TYPE_MVAR: {
8492 return mono_type_size (type, &align);
8494 case MONO_TYPE_VOID:
8498 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8504 * mono_array_element_size:
8505 * @ac: pointer to a #MonoArrayClass
8507 * Returns: the size of single array element.
8510 mono_array_element_size (MonoClass *ac)
8512 g_assert (ac->rank);
8513 return ac->sizes.element_size;
8517 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8518 MonoGenericContext *context)
8521 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8522 g_assert (mono_error_ok (&error));
8527 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8528 MonoGenericContext *context, MonoError *error)
8530 mono_error_init (error);
8532 if (image_is_dynamic (image)) {
8533 MonoClass *tmp_handle_class;
8534 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8536 g_assert (tmp_handle_class);
8538 *handle_class = tmp_handle_class;
8540 if (tmp_handle_class == mono_defaults.typehandle_class)
8541 return &((MonoClass*)obj)->byval_arg;
8546 switch (token & 0xff000000) {
8547 case MONO_TOKEN_TYPE_DEF:
8548 case MONO_TOKEN_TYPE_REF:
8549 case MONO_TOKEN_TYPE_SPEC: {
8552 *handle_class = mono_defaults.typehandle_class;
8553 type = mono_type_get_checked (image, token, context, error);
8557 mono_class_init (mono_class_from_mono_type (type));
8558 /* We return a MonoType* as handle */
8561 case MONO_TOKEN_FIELD_DEF: {
8563 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8565 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8569 *handle_class = mono_defaults.fieldhandle_class;
8570 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8574 mono_class_init (class);
8575 return mono_class_get_field (class, token);
8577 case MONO_TOKEN_METHOD_DEF:
8578 case MONO_TOKEN_METHOD_SPEC: {
8580 meth = mono_get_method_checked (image, token, NULL, context, error);
8582 *handle_class = mono_defaults.methodhandle_class;
8588 case MONO_TOKEN_MEMBER_REF: {
8589 guint32 cols [MONO_MEMBERREF_SIZE];
8591 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8592 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8593 mono_metadata_decode_blob_size (sig, &sig);
8594 if (*sig == 0x6) { /* it's a field */
8596 MonoClassField *field;
8597 field = mono_field_from_token_checked (image, token, &klass, context, error);
8599 *handle_class = mono_defaults.fieldhandle_class;
8603 meth = mono_get_method_checked (image, token, NULL, context, error);
8605 *handle_class = mono_defaults.methodhandle_class;
8610 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8616 * This function might need to call runtime functions so it can't be part
8617 * of the metadata library.
8619 static MonoLookupDynamicToken lookup_dynamic = NULL;
8622 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8624 lookup_dynamic = func;
8628 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8630 MonoClass *handle_class;
8632 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8636 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8638 return lookup_dynamic (image, token, valid_token, handle_class, context);
8641 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8644 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8646 get_cached_class_info = func;
8650 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8652 if (!get_cached_class_info)
8655 return get_cached_class_info (klass, res);
8659 mono_install_get_class_from_name (MonoGetClassFromName func)
8661 get_class_from_name = func;
8665 mono_class_get_image (MonoClass *klass)
8667 return klass->image;
8671 * mono_class_get_element_class:
8672 * @klass: the MonoClass to act on
8674 * Returns: the element class of an array or an enumeration.
8677 mono_class_get_element_class (MonoClass *klass)
8679 return klass->element_class;
8683 * mono_class_is_valuetype:
8684 * @klass: the MonoClass to act on
8686 * Returns: true if the MonoClass represents a ValueType.
8689 mono_class_is_valuetype (MonoClass *klass)
8691 return klass->valuetype;
8695 * mono_class_is_enum:
8696 * @klass: the MonoClass to act on
8698 * Returns: true if the MonoClass represents an enumeration.
8701 mono_class_is_enum (MonoClass *klass)
8703 return klass->enumtype;
8707 * mono_class_enum_basetype:
8708 * @klass: the MonoClass to act on
8710 * Returns: the underlying type representation for an enumeration.
8713 mono_class_enum_basetype (MonoClass *klass)
8715 if (klass->element_class == klass)
8716 /* SRE or broken types */
8719 return &klass->element_class->byval_arg;
8723 * mono_class_get_parent
8724 * @klass: the MonoClass to act on
8726 * Returns: the parent class for this class.
8729 mono_class_get_parent (MonoClass *klass)
8731 return klass->parent;
8735 * mono_class_get_nesting_type;
8736 * @klass: the MonoClass to act on
8738 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8741 mono_class_get_nesting_type (MonoClass *klass)
8743 return klass->nested_in;
8747 * mono_class_get_rank:
8748 * @klass: the MonoClass to act on
8750 * Returns: the rank for the array (the number of dimensions).
8753 mono_class_get_rank (MonoClass *klass)
8759 * mono_class_get_flags:
8760 * @klass: the MonoClass to act on
8762 * The type flags from the TypeDef table from the metadata.
8763 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8766 * Returns: the flags from the TypeDef table.
8769 mono_class_get_flags (MonoClass *klass)
8771 return klass->flags;
8775 * mono_class_get_name
8776 * @klass: the MonoClass to act on
8778 * Returns: the name of the class.
8781 mono_class_get_name (MonoClass *klass)
8787 * mono_class_get_namespace:
8788 * @klass: the MonoClass to act on
8790 * Returns: the namespace of the class.
8793 mono_class_get_namespace (MonoClass *klass)
8795 return klass->name_space;
8799 * mono_class_get_type:
8800 * @klass: the MonoClass to act on
8802 * This method returns the internal Type representation for the class.
8804 * Returns: the MonoType from the class.
8807 mono_class_get_type (MonoClass *klass)
8809 return &klass->byval_arg;
8813 * mono_class_get_type_token
8814 * @klass: the MonoClass to act on
8816 * This method returns type token for the class.
8818 * Returns: the type token for the class.
8821 mono_class_get_type_token (MonoClass *klass)
8823 return klass->type_token;
8827 * mono_class_get_byref_type:
8828 * @klass: the MonoClass to act on
8833 mono_class_get_byref_type (MonoClass *klass)
8835 return &klass->this_arg;
8839 * mono_class_num_fields:
8840 * @klass: the MonoClass to act on
8842 * Returns: the number of static and instance fields in the class.
8845 mono_class_num_fields (MonoClass *klass)
8847 return klass->field.count;
8851 * mono_class_num_methods:
8852 * @klass: the MonoClass to act on
8854 * Returns: the number of methods in the class.
8857 mono_class_num_methods (MonoClass *klass)
8859 return klass->method.count;
8863 * mono_class_num_properties
8864 * @klass: the MonoClass to act on
8866 * Returns: the number of properties in the class.
8869 mono_class_num_properties (MonoClass *klass)
8871 mono_class_setup_properties (klass);
8873 return klass->ext->property.count;
8877 * mono_class_num_events:
8878 * @klass: the MonoClass to act on
8880 * Returns: the number of events in the class.
8883 mono_class_num_events (MonoClass *klass)
8885 mono_class_setup_events (klass);
8887 return klass->ext->event.count;
8891 * mono_class_get_fields:
8892 * @klass: the MonoClass to act on
8894 * This routine is an iterator routine for retrieving the fields in a class.
8896 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8897 * iterate over all of the elements. When no more values are
8898 * available, the return value is NULL.
8900 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8903 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8905 MonoClassField* field;
8909 mono_class_setup_fields_locking (klass);
8910 if (klass->exception_type)
8912 /* start from the first */
8913 if (klass->field.count) {
8914 return *iter = &klass->fields [0];
8922 if (field < &klass->fields [klass->field.count]) {
8923 return *iter = field;
8929 * mono_class_get_methods
8930 * @klass: the MonoClass to act on
8932 * This routine is an iterator routine for retrieving the fields in a class.
8934 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8935 * iterate over all of the elements. When no more values are
8936 * available, the return value is NULL.
8938 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8941 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8943 MonoMethod** method;
8947 mono_class_setup_methods (klass);
8950 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8951 * FIXME we should better report this error to the caller
8953 if (!klass->methods)
8955 /* start from the first */
8956 if (klass->method.count) {
8957 *iter = &klass->methods [0];
8958 return klass->methods [0];
8966 if (method < &klass->methods [klass->method.count]) {
8974 * mono_class_get_virtual_methods:
8976 * Iterate over the virtual methods of KLASS.
8978 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8981 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8983 MonoMethod** method;
8986 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8988 mono_class_setup_methods (klass);
8990 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8991 * FIXME we should better report this error to the caller
8993 if (!klass->methods)
8995 /* start from the first */
8996 method = &klass->methods [0];
9001 while (method < &klass->methods [klass->method.count]) {
9002 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9006 if (method < &klass->methods [klass->method.count]) {
9013 /* Search directly in metadata to avoid calling setup_methods () */
9014 MonoMethod *res = NULL;
9020 start_index = GPOINTER_TO_UINT (*iter);
9023 for (i = start_index; i < klass->method.count; ++i) {
9026 /* class->method.first points into the methodptr table */
9027 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9029 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9033 if (i < klass->method.count) {
9035 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9036 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9038 /* Add 1 here so the if (*iter) check fails */
9039 *iter = GUINT_TO_POINTER (i + 1);
9048 * mono_class_get_properties:
9049 * @klass: the MonoClass to act on
9051 * This routine is an iterator routine for retrieving the properties in a class.
9053 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9054 * iterate over all of the elements. When no more values are
9055 * available, the return value is NULL.
9057 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9060 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9062 MonoProperty* property;
9066 mono_class_setup_properties (klass);
9067 /* start from the first */
9068 if (klass->ext->property.count) {
9069 return *iter = &klass->ext->properties [0];
9077 if (property < &klass->ext->properties [klass->ext->property.count]) {
9078 return *iter = property;
9084 * mono_class_get_events:
9085 * @klass: the MonoClass to act on
9087 * This routine is an iterator routine for retrieving the properties in a class.
9089 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9090 * iterate over all of the elements. When no more values are
9091 * available, the return value is NULL.
9093 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9096 mono_class_get_events (MonoClass* klass, gpointer *iter)
9102 mono_class_setup_events (klass);
9103 /* start from the first */
9104 if (klass->ext->event.count) {
9105 return *iter = &klass->ext->events [0];
9113 if (event < &klass->ext->events [klass->ext->event.count]) {
9114 return *iter = event;
9120 * mono_class_get_interfaces
9121 * @klass: the MonoClass to act on
9123 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9125 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9126 * iterate over all of the elements. When no more values are
9127 * available, the return value is NULL.
9129 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9132 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9140 mono_class_init (klass);
9141 if (!klass->interfaces_inited) {
9142 mono_class_setup_interfaces (klass, &error);
9143 if (!mono_error_ok (&error)) {
9144 mono_error_cleanup (&error);
9148 /* start from the first */
9149 if (klass->interface_count) {
9150 *iter = &klass->interfaces [0];
9151 return klass->interfaces [0];
9159 if (iface < &klass->interfaces [klass->interface_count]) {
9167 setup_nested_types (MonoClass *klass)
9170 GList *classes, *nested_classes, *l;
9173 if (klass->nested_classes_inited)
9176 if (!klass->type_token)
9177 klass->nested_classes_inited = TRUE;
9179 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9183 guint32 cols [MONO_NESTED_CLASS_SIZE];
9184 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9185 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9186 if (!mono_error_ok (&error)) {
9187 /*FIXME don't swallow the error message*/
9188 mono_error_cleanup (&error);
9190 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9194 classes = g_list_prepend (classes, nclass);
9196 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9199 mono_class_alloc_ext (klass);
9201 nested_classes = NULL;
9202 for (l = classes; l; l = l->next)
9203 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9204 g_list_free (classes);
9206 mono_image_lock (klass->image);
9208 mono_memory_barrier ();
9209 if (!klass->nested_classes_inited) {
9210 klass->ext->nested_classes = nested_classes;
9211 mono_memory_barrier ();
9212 klass->nested_classes_inited = TRUE;
9215 mono_image_unlock (klass->image);
9219 * mono_class_get_nested_types
9220 * @klass: the MonoClass to act on
9222 * This routine is an iterator routine for retrieving the nested types of a class.
9223 * This works only if @klass is non-generic, or a generic type definition.
9225 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9226 * iterate over all of the elements. When no more values are
9227 * available, the return value is NULL.
9229 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9232 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9238 if (!klass->nested_classes_inited)
9239 setup_nested_types (klass);
9242 /* start from the first */
9243 if (klass->ext && klass->ext->nested_classes) {
9244 *iter = klass->ext->nested_classes;
9245 return klass->ext->nested_classes->data;
9247 /* no nested types */
9262 * mono_class_is_delegate
9263 * @klass: the MonoClass to act on
9265 * Returns: true if the MonoClass represents a System.Delegate.
9268 mono_class_is_delegate (MonoClass *klass)
9270 return klass->delegate;
9274 * mono_class_implements_interface
9275 * @klass: The MonoClass to act on
9276 * @interface: The interface to check if @klass implements.
9278 * Returns: true if @klass implements @interface.
9281 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9283 return mono_class_is_assignable_from (iface, klass);
9287 * mono_field_get_name:
9288 * @field: the MonoClassField to act on
9290 * Returns: the name of the field.
9293 mono_field_get_name (MonoClassField *field)
9299 * mono_field_get_type:
9300 * @field: the MonoClassField to act on
9302 * Returns: MonoType of the field.
9305 mono_field_get_type (MonoClassField *field)
9308 MonoType *type = mono_field_get_type_checked (field, &error);
9309 if (!mono_error_ok (&error)) {
9310 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9311 mono_error_cleanup (&error);
9318 * mono_field_get_type_checked:
9319 * @field: the MonoClassField to act on
9320 * @error: used to return any erro found while retrieving @field type
9322 * Returns: MonoType of the field.
9325 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9327 mono_error_init (error);
9329 mono_field_resolve_type (field, error);
9334 * mono_field_get_parent:
9335 * @field: the MonoClassField to act on
9337 * Returns: MonoClass where the field was defined.
9340 mono_field_get_parent (MonoClassField *field)
9342 return field->parent;
9346 * mono_field_get_flags;
9347 * @field: the MonoClassField to act on
9349 * The metadata flags for a field are encoded using the
9350 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9352 * Returns: the flags for the field.
9355 mono_field_get_flags (MonoClassField *field)
9358 return mono_field_resolve_flags (field);
9359 return field->type->attrs;
9363 * mono_field_get_offset;
9364 * @field: the MonoClassField to act on
9366 * Returns: the field offset.
9369 mono_field_get_offset (MonoClassField *field)
9371 return field->offset;
9375 mono_field_get_rva (MonoClassField *field)
9379 MonoClass *klass = field->parent;
9380 MonoFieldDefaultValue *field_def_values;
9382 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9384 if (!klass->ext || !klass->ext->field_def_values) {
9385 mono_class_alloc_ext (klass);
9387 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9389 mono_image_lock (klass->image);
9390 if (!klass->ext->field_def_values)
9391 klass->ext->field_def_values = field_def_values;
9392 mono_image_unlock (klass->image);
9395 field_index = mono_field_get_index (field);
9397 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9398 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9400 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9401 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9404 return klass->ext->field_def_values [field_index].data;
9408 * mono_field_get_data;
9409 * @field: the MonoClassField to act on
9411 * Returns: pointer to the metadata constant value or to the field
9412 * data if it has an RVA flag.
9415 mono_field_get_data (MonoClassField *field)
9417 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9418 MonoTypeEnum def_type;
9420 return mono_class_get_field_default_value (field, &def_type);
9421 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9422 return mono_field_get_rva (field);
9429 * mono_property_get_name:
9430 * @prop: the MonoProperty to act on
9432 * Returns: the name of the property
9435 mono_property_get_name (MonoProperty *prop)
9441 * mono_property_get_set_method
9442 * @prop: the MonoProperty to act on.
9444 * Returns: the setter method of the property (A MonoMethod)
9447 mono_property_get_set_method (MonoProperty *prop)
9453 * mono_property_get_get_method
9454 * @prop: the MonoProperty to act on.
9456 * Returns: the setter method of the property (A MonoMethod)
9459 mono_property_get_get_method (MonoProperty *prop)
9465 * mono_property_get_parent:
9466 * @prop: the MonoProperty to act on.
9468 * Returns: the MonoClass where the property was defined.
9471 mono_property_get_parent (MonoProperty *prop)
9473 return prop->parent;
9477 * mono_property_get_flags:
9478 * @prop: the MonoProperty to act on.
9480 * The metadata flags for a property are encoded using the
9481 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9483 * Returns: the flags for the property.
9486 mono_property_get_flags (MonoProperty *prop)
9492 * mono_event_get_name:
9493 * @event: the MonoEvent to act on
9495 * Returns: the name of the event.
9498 mono_event_get_name (MonoEvent *event)
9504 * mono_event_get_add_method:
9505 * @event: The MonoEvent to act on.
9507 * Returns: the @add' method for the event (a MonoMethod).
9510 mono_event_get_add_method (MonoEvent *event)
9516 * mono_event_get_remove_method:
9517 * @event: The MonoEvent to act on.
9519 * Returns: the @remove method for the event (a MonoMethod).
9522 mono_event_get_remove_method (MonoEvent *event)
9524 return event->remove;
9528 * mono_event_get_raise_method:
9529 * @event: The MonoEvent to act on.
9531 * Returns: the @raise method for the event (a MonoMethod).
9534 mono_event_get_raise_method (MonoEvent *event)
9536 return event->raise;
9540 * mono_event_get_parent:
9541 * @event: the MonoEvent to act on.
9543 * Returns: the MonoClass where the event is defined.
9546 mono_event_get_parent (MonoEvent *event)
9548 return event->parent;
9552 * mono_event_get_flags
9553 * @event: the MonoEvent to act on.
9555 * The metadata flags for an event are encoded using the
9556 * EVENT_* constants. See the tabledefs.h file for details.
9558 * Returns: the flags for the event.
9561 mono_event_get_flags (MonoEvent *event)
9563 return event->attrs;
9567 * mono_class_get_method_from_name:
9568 * @klass: where to look for the method
9569 * @name: name of the method
9570 * @param_count: number of parameters. -1 for any number.
9572 * Obtains a MonoMethod with a given name and number of parameters.
9573 * It only works if there are no multiple signatures for any given method name.
9576 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9578 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9582 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9584 MonoMethod *res = NULL;
9587 /* Search directly in the metadata to avoid calling setup_methods () */
9588 for (i = 0; i < klass->method.count; ++i) {
9590 guint32 cols [MONO_METHOD_SIZE];
9592 MonoMethodSignature *sig;
9594 /* class->method.first points into the methodptr table */
9595 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9597 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9598 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9600 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9603 if (param_count == -1) {
9607 sig = mono_method_signature_checked (method, &error);
9609 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9612 if (sig->param_count == param_count) {
9623 * mono_class_get_method_from_name_flags:
9624 * @klass: where to look for the method
9625 * @name_space: name of the method
9626 * @param_count: number of parameters. -1 for any number.
9627 * @flags: flags which must be set in the method
9629 * Obtains a MonoMethod with a given name and number of parameters.
9630 * It only works if there are no multiple signatures for any given method name.
9633 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9635 MonoMethod *res = NULL;
9638 mono_class_init (klass);
9640 if (klass->generic_class && !klass->methods) {
9641 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9644 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9645 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9650 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9651 mono_class_setup_methods (klass);
9653 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9654 See mono/tests/array_load_exception.il
9655 FIXME we should better report this error to the caller
9657 if (!klass->methods)
9659 for (i = 0; i < klass->method.count; ++i) {
9660 MonoMethod *method = klass->methods [i];
9662 if (method->name[0] == name [0] &&
9663 !strcmp (name, method->name) &&
9664 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9665 ((method->flags & flags) == flags)) {
9672 res = find_method_in_metadata (klass, name, param_count, flags);
9679 * mono_class_set_failure:
9680 * @klass: class in which the failure was detected
9681 * @ex_type: the kind of exception/error to be thrown (later)
9682 * @ex_data: exception data (specific to each type of exception/error)
9684 * Keep a detected failure informations in the class for later processing.
9685 * Note that only the first failure is kept.
9687 * LOCKING: Acquires the loader lock.
9690 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9692 if (klass->exception_type)
9695 mono_loader_lock ();
9696 klass->exception_type = ex_type;
9698 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9699 mono_loader_unlock ();
9705 * mono_class_get_exception_data:
9707 * Return the exception_data property of KLASS.
9709 * LOCKING: Acquires the loader lock.
9712 mono_class_get_exception_data (MonoClass *klass)
9714 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9718 * mono_classes_init:
9720 * Initialize the resources used by this module.
9723 mono_classes_init (void)
9725 mono_mutex_init (&classes_mutex);
9727 mono_counters_register ("Inflated methods size",
9728 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9729 mono_counters_register ("Inflated classes",
9730 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9731 mono_counters_register ("Inflated classes size",
9732 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9733 mono_counters_register ("MonoClass size",
9734 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9735 mono_counters_register ("MonoClassExt size",
9736 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9740 * mono_classes_cleanup:
9742 * Free the resources used by this module.
9745 mono_classes_cleanup (void)
9747 if (global_interface_bitset)
9748 mono_bitset_free (global_interface_bitset);
9749 global_interface_bitset = NULL;
9750 mono_mutex_destroy (&classes_mutex);
9754 * mono_class_get_exception_for_failure:
9755 * @klass: class in which the failure was detected
9757 * Return a constructed MonoException than the caller can then throw
9758 * using mono_raise_exception - or NULL if no failure is present (or
9759 * doesn't result in an exception).
9762 mono_class_get_exception_for_failure (MonoClass *klass)
9764 gpointer exception_data = mono_class_get_exception_data (klass);
9766 switch (klass->exception_type) {
9767 case MONO_EXCEPTION_TYPE_LOAD: {
9770 char *str = mono_type_get_full_name (klass);
9771 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9772 name = mono_string_new (mono_domain_get (), str);
9774 ex = mono_get_exception_type_load (name, astr);
9778 case MONO_EXCEPTION_MISSING_METHOD: {
9779 char *class_name = exception_data;
9780 char *assembly_name = class_name + strlen (class_name) + 1;
9782 return mono_get_exception_missing_method (class_name, assembly_name);
9784 case MONO_EXCEPTION_MISSING_FIELD: {
9785 char *class_name = exception_data;
9786 char *member_name = class_name + strlen (class_name) + 1;
9788 return mono_get_exception_missing_field (class_name, member_name);
9790 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9791 char *msg_format = exception_data;
9792 char *assembly_name = msg_format + strlen (msg_format) + 1;
9793 char *msg = g_strdup_printf (msg_format, assembly_name);
9796 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9802 case MONO_EXCEPTION_BAD_IMAGE: {
9803 return mono_get_exception_bad_image_format (exception_data);
9806 MonoLoaderError *error;
9809 error = mono_loader_get_last_error ();
9811 ex = mono_loader_error_prepare_exception (error);
9815 /* TODO - handle other class related failures */
9822 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9824 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9825 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9827 if (outer_klass == inner_klass)
9829 inner_klass = inner_klass->nested_in;
9830 } while (inner_klass);
9835 mono_class_get_generic_type_definition (MonoClass *klass)
9837 return klass->generic_class ? klass->generic_class->container_class : klass;
9841 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9843 * Generic instantiations are ignored for all super types of @klass.
9845 * Visibility checks ignoring generic instantiations.
9848 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9851 klass = mono_class_get_generic_type_definition (klass);
9852 parent = mono_class_get_generic_type_definition (parent);
9853 mono_class_setup_supertypes (klass);
9855 for (i = 0; i < klass->idepth; ++i) {
9856 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9862 * Subtype can only access parent members with family protection if the site object
9863 * is subclass of Subtype. For example:
9864 * class A { protected int x; }
9866 * void valid_access () {
9870 * void invalid_access () {
9877 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9879 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9882 if (context_klass == NULL)
9884 /*if access_klass is not member_klass context_klass must be type compat*/
9885 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9891 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9894 if (accessing == accessed)
9896 if (!accessed || !accessing)
9899 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9900 * anywhere so untrusted friends are not safe to access platform's code internals */
9901 if (mono_security_core_clr_enabled ()) {
9902 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9906 mono_assembly_load_friends (accessed);
9907 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9908 MonoAssemblyName *friend = tmp->data;
9909 /* Be conservative with checks */
9912 if (strcmp (accessing->aname.name, friend->name))
9914 if (friend->public_key_token [0]) {
9915 if (!accessing->aname.public_key_token [0])
9917 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9926 * If klass is a generic type or if it is derived from a generic type, return the
9927 * MonoClass of the generic definition
9928 * Returns NULL if not found
9931 get_generic_definition_class (MonoClass *klass)
9934 if (klass->generic_class && klass->generic_class->container_class)
9935 return klass->generic_class->container_class;
9936 klass = klass->parent;
9942 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9945 for (i = 0; i < ginst->type_argc; ++i) {
9946 MonoType *type = ginst->type_argv[i];
9947 switch (type->type) {
9948 case MONO_TYPE_SZARRAY:
9949 if (!can_access_type (access_klass, type->data.klass))
9952 case MONO_TYPE_ARRAY:
9953 if (!can_access_type (access_klass, type->data.array->eklass))
9957 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9960 case MONO_TYPE_CLASS:
9961 case MONO_TYPE_VALUETYPE:
9962 case MONO_TYPE_GENERICINST:
9963 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9973 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9977 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9980 if (access_klass->element_class && !access_klass->enumtype)
9981 access_klass = access_klass->element_class;
9983 if (member_klass->element_class && !member_klass->enumtype)
9984 member_klass = member_klass->element_class;
9986 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9988 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9991 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9994 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9997 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10000 /*Non nested type with nested visibility. We just fail it.*/
10001 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10004 switch (access_level) {
10005 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10006 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10008 case TYPE_ATTRIBUTE_PUBLIC:
10011 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10014 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10015 return is_nesting_type (member_klass, access_klass);
10017 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10018 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10020 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10021 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10023 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10024 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10025 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10027 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10028 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10029 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10034 /* FIXME: check visibility of type, too */
10036 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10038 MonoClass *member_generic_def;
10039 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10042 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10043 access_klass->generic_container) &&
10044 (member_generic_def = get_generic_definition_class (member_klass))) {
10045 MonoClass *access_container;
10047 if (access_klass->generic_container)
10048 access_container = access_klass;
10050 access_container = access_klass->generic_class->container_class;
10052 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10056 /* Partition I 8.5.3.2 */
10057 /* the access level values are the same for fields and methods */
10058 switch (access_level) {
10059 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10060 /* same compilation unit */
10061 return access_klass->image == member_klass->image;
10062 case FIELD_ATTRIBUTE_PRIVATE:
10063 return access_klass == member_klass;
10064 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10065 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10066 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10069 case FIELD_ATTRIBUTE_ASSEMBLY:
10070 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10071 case FIELD_ATTRIBUTE_FAMILY:
10072 if (is_valid_family_access (access_klass, member_klass, context_klass))
10075 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10076 if (is_valid_family_access (access_klass, member_klass, context_klass))
10078 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10079 case FIELD_ATTRIBUTE_PUBLIC:
10086 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10088 /* FIXME: check all overlapping fields */
10089 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10091 MonoClass *nested = method->klass->nested_in;
10093 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10096 nested = nested->nested_in;
10103 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10105 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10107 MonoClass *nested = method->klass->nested_in;
10109 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10112 nested = nested->nested_in;
10117 * with generics calls to explicit interface implementations can be expressed
10118 * directly: the method is private, but we must allow it. This may be opening
10119 * a hole or the generics code should handle this differently.
10120 * Maybe just ensure the interface type is public.
10122 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10128 * mono_method_can_access_method_full:
10129 * @method: The caller method
10130 * @called: The called method
10131 * @context_klass: The static type on stack of the owner @called object used
10133 * This function must be used with instance calls, as they have more strict family accessibility.
10134 * It can be used with static methods, but context_klass should be NULL.
10136 * Returns: TRUE if caller have proper visibility and acessibility to @called
10139 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10141 MonoClass *access_class = method->klass;
10142 MonoClass *member_class = called->klass;
10143 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10145 MonoClass *nested = access_class->nested_in;
10147 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10150 nested = nested->nested_in;
10157 can = can_access_type (access_class, member_class);
10159 MonoClass *nested = access_class->nested_in;
10161 can = can_access_type (nested, member_class);
10164 nested = nested->nested_in;
10171 if (called->is_inflated) {
10172 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10173 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10182 * mono_method_can_access_field_full:
10183 * @method: The caller method
10184 * @field: The accessed field
10185 * @context_klass: The static type on stack of the owner @field object used
10187 * This function must be used with instance fields, as they have more strict family accessibility.
10188 * It can be used with static fields, but context_klass should be NULL.
10190 * Returns: TRUE if caller have proper visibility and acessibility to @field
10193 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10195 MonoClass *access_class = method->klass;
10196 MonoClass *member_class = field->parent;
10197 /* FIXME: check all overlapping fields */
10198 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10200 MonoClass *nested = access_class->nested_in;
10202 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10205 nested = nested->nested_in;
10212 can = can_access_type (access_class, member_class);
10214 MonoClass *nested = access_class->nested_in;
10216 can = can_access_type (nested, member_class);
10219 nested = nested->nested_in;
10229 * mono_class_can_access_class:
10230 * @source_class: The source class
10231 * @target_class: The accessed class
10233 * This function returns is @target_class is visible to @source_class
10235 * Returns: TRUE if source have proper visibility and acessibility to target
10238 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10240 return can_access_type (source_class, target_class);
10244 * mono_type_is_valid_enum_basetype:
10245 * @type: The MonoType to check
10247 * Returns: TRUE if the type can be used as the basetype of an enum
10249 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10250 switch (type->type) {
10253 case MONO_TYPE_BOOLEAN:
10256 case MONO_TYPE_CHAR:
10270 * mono_class_is_valid_enum:
10271 * @klass: An enum class to be validated
10273 * This method verify the required properties an enum should have.
10275 * Returns: TRUE if the informed enum class is valid
10277 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10278 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10279 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10281 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10282 MonoClassField * field;
10283 gpointer iter = NULL;
10284 gboolean found_base_field = FALSE;
10286 g_assert (klass->enumtype);
10287 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10288 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10292 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10295 while ((field = mono_class_get_fields (klass, &iter))) {
10296 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10297 if (found_base_field)
10299 found_base_field = TRUE;
10300 if (!mono_type_is_valid_enum_basetype (field->type))
10305 if (!found_base_field)
10308 if (klass->method.count > 0)
10315 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10317 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10321 * mono_class_setup_interface_id:
10323 * Initializes MonoClass::interface_id if required.
10325 * LOCKING: Acquires the loader lock.
10328 mono_class_setup_interface_id (MonoClass *class)
10330 mono_loader_lock ();
10331 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10332 class->interface_id = mono_get_unique_iid (class);
10333 mono_loader_unlock ();
10337 * mono_class_alloc_ext:
10339 * Allocate klass->ext if not already done.
10342 mono_class_alloc_ext (MonoClass *klass)
10349 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10350 mono_image_lock (klass->image);
10351 mono_memory_barrier ();
10354 class_ext_size += sizeof (MonoClassExt);
10355 mono_image_unlock (klass->image);
10359 * mono_class_setup_interfaces:
10361 * Initialize class->interfaces/interfaces_count.
10362 * LOCKING: Acquires the loader lock.
10363 * This function can fail the type.
10366 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10368 int i, interface_count;
10369 MonoClass **interfaces;
10371 mono_error_init (error);
10373 if (klass->interfaces_inited)
10376 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10377 MonoType *args [1];
10379 /* generic IList, ICollection, IEnumerable */
10380 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10381 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10383 args [0] = &klass->element_class->byval_arg;
10384 interfaces [0] = mono_class_bind_generic_parameters (
10385 mono_defaults.generic_ilist_class, 1, args, FALSE);
10386 if (interface_count > 1)
10387 interfaces [1] = mono_class_bind_generic_parameters (
10388 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10389 } else if (klass->generic_class) {
10390 MonoClass *gklass = klass->generic_class->container_class;
10392 mono_class_setup_interfaces (gklass, error);
10393 if (!mono_error_ok (error)) {
10394 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10398 interface_count = gklass->interface_count;
10399 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10400 for (i = 0; i < interface_count; i++) {
10401 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10402 if (!mono_error_ok (error)) {
10403 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10408 interface_count = 0;
10412 mono_image_lock (klass->image);
10414 if (!klass->interfaces_inited) {
10415 klass->interface_count = interface_count;
10416 klass->interfaces = interfaces;
10418 mono_memory_barrier ();
10420 klass->interfaces_inited = TRUE;
10423 mono_image_unlock (klass->image);
10427 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10429 MonoClass *class = field->parent;
10430 MonoImage *image = class->image;
10431 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10432 int field_idx = field - class->fields;
10434 mono_error_init (error);
10437 MonoClassField *gfield = >d->fields [field_idx];
10438 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10439 if (!mono_error_ok (error)) {
10440 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10441 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10445 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10446 if (!mono_error_ok (error)) {
10447 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10448 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10453 guint32 cols [MONO_FIELD_SIZE];
10454 MonoGenericContainer *container = NULL;
10455 int idx = class->field.first + field_idx;
10457 /*FIXME, in theory we do not lazy load SRE fields*/
10458 g_assert (!image_is_dynamic (image));
10460 if (class->generic_container) {
10461 container = class->generic_container;
10463 container = gtd->generic_container;
10464 g_assert (container);
10467 /* class->field.first and idx points into the fieldptr table */
10468 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10470 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10471 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10472 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10476 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10478 mono_metadata_decode_value (sig, &sig);
10479 /* FIELD signature == 0x06 */
10480 g_assert (*sig == 0x06);
10481 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10483 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10488 mono_field_resolve_flags (MonoClassField *field)
10490 MonoClass *class = field->parent;
10491 MonoImage *image = class->image;
10492 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10493 int field_idx = field - class->fields;
10497 MonoClassField *gfield = >d->fields [field_idx];
10498 return mono_field_get_flags (gfield);
10500 int idx = class->field.first + field_idx;
10502 /*FIXME, in theory we do not lazy load SRE fields*/
10503 g_assert (!image_is_dynamic (image));
10505 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10510 * mono_class_setup_basic_field_info:
10511 * @class: The class to initialize
10513 * Initializes the class->fields array of fields.
10514 * Aquires the loader lock.
10517 mono_class_setup_basic_field_info_locking (MonoClass *class)
10519 mono_loader_lock ();
10520 mono_class_setup_basic_field_info (class);
10521 mono_loader_unlock ();
10525 * mono_class_get_fields_lazy:
10526 * @klass: the MonoClass to act on
10528 * This routine is an iterator routine for retrieving the fields in a class.
10529 * Only minimal information about fields are loaded. Accessors must be used
10530 * for all MonoClassField returned.
10532 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10533 * iterate over all of the elements. When no more values are
10534 * available, the return value is NULL.
10536 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10539 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10541 MonoClassField* field;
10545 mono_class_setup_basic_field_info_locking (klass);
10546 if (!klass->fields)
10548 /* start from the first */
10549 if (klass->field.count) {
10550 return *iter = &klass->fields [0];
10558 if (field < &klass->fields [klass->field.count]) {
10559 return *iter = field;
10565 mono_class_full_name (MonoClass *klass)
10567 return mono_type_full_name (&klass->byval_arg);