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 mono_loader_assert_no_error ();
289 mono_image_memdup (MonoImage *image, void *data, guint size)
291 void *res = mono_image_alloc (image, size);
292 memcpy (res, data, size);
296 /* Copy everything mono_metadata_free_array free. */
298 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
301 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
303 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
307 a = g_memdup (a, sizeof (MonoArrayType));
309 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
311 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
316 /* Copy everything mono_metadata_free_method_signature free. */
318 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
322 sig = mono_metadata_signature_dup_full (image, sig);
324 sig->ret = mono_metadata_type_dup (image, sig->ret);
325 for (i = 0; i < sig->param_count; ++i)
326 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
332 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
334 MonoAssembly *ta = klass->image->assembly;
337 name = mono_stringify_assembly_name (&ta->aname);
338 g_string_append_printf (str, ", %s", name);
343 mono_type_name_check_byref (MonoType *type, GString *str)
346 g_string_append_c (str, '&');
350 mono_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 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1100 mono_image_set_lock (set);
1101 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1102 mono_image_set_unlock (set);
1106 return (MonoMethod*)cached;
1109 mono_stats.inflated_method_count++;
1111 inflated_methods_size += sizeof (MonoMethodInflated);
1113 sig = mono_method_signature (method);
1115 char *name = mono_type_get_full_name (method->klass);
1116 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1122 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1124 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1127 result = (MonoMethod *) iresult;
1128 result->is_inflated = TRUE;
1129 result->is_generic = FALSE;
1130 result->sre_method = FALSE;
1131 result->signature = NULL;
1132 result->is_mb_open = is_mb_open;
1134 if (!context->method_inst) {
1135 /* Set the generic_container of the result to the generic_container of method */
1136 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1138 if (generic_container) {
1139 result->is_generic = 1;
1140 mono_method_set_generic_container (result, generic_container);
1144 if (!klass_hint || !klass_hint->generic_class ||
1145 klass_hint->generic_class->container_class != method->klass ||
1146 klass_hint->generic_class->context.class_inst != context->class_inst)
1149 if (method->klass->generic_container)
1150 result->klass = klass_hint;
1152 if (!result->klass) {
1153 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1154 if (!mono_error_ok (error))
1157 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1159 mono_metadata_free_type (inflated);
1163 * FIXME: This should hold, but it doesn't:
1165 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1166 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1167 * g_assert (result->is_generic);
1170 * Fixing this here causes other things to break, hence a very
1171 * ugly hack in mini-trampolines.c - see
1172 * is_generic_method_definition().
1176 mono_image_set_lock (set);
1177 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1179 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1180 iresult->owner = set;
1183 mono_image_set_unlock (set);
1185 return (MonoMethod*)cached;
1193 * mono_get_inflated_method:
1195 * Obsolete. We keep it around since it's mentioned in the public API.
1198 mono_get_inflated_method (MonoMethod *method)
1204 * mono_method_get_context_general:
1206 * @uninflated: handle uninflated methods?
1208 * Returns the generic context of a method or NULL if it doesn't have
1209 * one. For an inflated method that's the context stored in the
1210 * method. Otherwise it's in the method's generic container or in the
1211 * generic container of the method's class.
1214 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1216 if (method->is_inflated) {
1217 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1218 return &imethod->context;
1222 if (method->is_generic)
1223 return &(mono_method_get_generic_container (method)->context);
1224 if (method->klass->generic_container)
1225 return &method->klass->generic_container->context;
1230 * mono_method_get_context:
1233 * Returns the generic context for method if it's inflated, otherwise
1237 mono_method_get_context (MonoMethod *method)
1239 return mono_method_get_context_general (method, FALSE);
1243 * mono_method_get_generic_container:
1245 * Returns the generic container of METHOD, which should be a generic method definition.
1246 * Returns NULL if METHOD is not a generic method definition.
1247 * LOCKING: Acquires the loader lock.
1249 MonoGenericContainer*
1250 mono_method_get_generic_container (MonoMethod *method)
1252 MonoGenericContainer *container;
1254 if (!method->is_generic)
1257 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1258 g_assert (container);
1264 * mono_method_set_generic_container:
1266 * Sets the generic container of METHOD to CONTAINER.
1267 * LOCKING: Acquires the image lock.
1270 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1272 g_assert (method->is_generic);
1274 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1278 * mono_class_find_enum_basetype:
1279 * @class: The enum class
1281 * Determine the basetype of an enum by iterating through its fields. We do this
1282 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1285 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1287 MonoGenericContainer *container = NULL;
1288 MonoImage *m = class->image;
1289 const int top = class->field.count;
1292 g_assert (class->enumtype);
1294 mono_error_init (error);
1296 if (class->generic_container)
1297 container = class->generic_container;
1298 else if (class->generic_class) {
1299 MonoClass *gklass = class->generic_class->container_class;
1301 container = gklass->generic_container;
1302 g_assert (container);
1306 * Fetch all the field information.
1308 for (i = 0; i < top; i++){
1310 guint32 cols [MONO_FIELD_SIZE];
1311 int idx = class->field.first + i;
1314 /* class->field.first and idx points into the fieldptr table */
1315 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1317 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1320 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1321 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1325 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1326 mono_metadata_decode_value (sig, &sig);
1327 /* FIELD signature == 0x06 */
1329 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1333 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1335 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1336 mono_error_set_from_loader_error (error);
1338 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1341 if (class->generic_class) {
1342 //FIXME do we leak here?
1343 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1344 if (!mono_error_ok (error))
1346 ftype->attrs = cols [MONO_FIELD_FLAGS];
1351 mono_error_set_type_load_class (error, class, "Could not find base type");
1354 mono_loader_assert_no_error ();
1359 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1362 mono_type_has_exceptions (MonoType *type)
1364 switch (type->type) {
1365 case MONO_TYPE_CLASS:
1366 case MONO_TYPE_VALUETYPE:
1367 case MONO_TYPE_SZARRAY:
1368 return type->data.klass->exception_type;
1369 case MONO_TYPE_ARRAY:
1370 return type->data.array->eklass->exception_type;
1371 case MONO_TYPE_GENERICINST:
1372 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1381 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1385 mono_class_alloc (MonoClass *class, int size)
1387 if (class->generic_class)
1388 return mono_image_set_alloc (class->generic_class->owner, size);
1390 return mono_image_alloc (class->image, size);
1394 mono_class_alloc0 (MonoClass *class, int size)
1398 res = mono_class_alloc (class, size);
1399 memset (res, 0, size);
1403 #define mono_class_new0(class,struct_type, n_structs) \
1404 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1407 * mono_class_setup_basic_field_info:
1408 * @class: The class to initialize
1410 * Initializes the class->fields.
1411 * LOCKING: Assumes the loader lock is held.
1414 mono_class_setup_basic_field_info (MonoClass *class)
1416 MonoClassField *field;
1424 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1425 image = class->image;
1426 top = class->field.count;
1428 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1430 * This happens when a generic instance of an unfinished generic typebuilder
1431 * is used as an element type for creating an array type. We can't initialize
1432 * the fields of this class using the fields of gklass, since gklass is not
1433 * finished yet, fields could be added to it later.
1439 mono_class_setup_basic_field_info (gtd);
1441 top = gtd->field.count;
1442 class->field.first = gtd->field.first;
1443 class->field.count = gtd->field.count;
1446 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1449 * Fetch all the field information.
1451 for (i = 0; i < top; i++){
1452 field = &class->fields [i];
1453 field->parent = class;
1456 field->name = mono_field_get_name (>d->fields [i]);
1458 int idx = class->field.first + i;
1459 /* class->field.first and idx points into the fieldptr table */
1460 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1461 /* The name is needed for fieldrefs */
1462 field->name = mono_metadata_string_heap (image, name_idx);
1468 * mono_class_setup_fields:
1469 * @class: The class to initialize
1471 * Initializes the class->fields.
1472 * LOCKING: Assumes the loader lock is held.
1475 mono_class_setup_fields (MonoClass *class)
1478 MonoImage *m = class->image;
1480 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1481 int i, blittable = TRUE;
1482 guint32 real_size = 0;
1483 guint32 packing_size = 0;
1484 gboolean explicit_size;
1485 MonoClassField *field;
1486 MonoGenericContainer *container = NULL;
1487 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1490 * FIXME: We have a race condition here. It's possible that this function returns
1491 * to its caller with `instance_size` set to `0` instead of the actual size. This
1492 * is not a problem when the function is called recursively on the same class,
1493 * because the size will be initialized by the outer invocation. What follows is a
1494 * description of how it can occur in other cases, too. There it is a problem,
1495 * because it can lead to the GC being asked to allocate an object of size `0`,
1496 * which SGen chokes on. The race condition is triggered infrequently by
1497 * `tests/sgen-suspend.cs`.
1499 * This function is called for a class whenever one of its subclasses is inited.
1500 * For example, it's called for every subclass of Object. What it does is this:
1502 * if (class->setup_fields_called)
1505 * class->instance_size = 0;
1507 * class->setup_fields_called = 1;
1508 * ... critical point
1509 * class->instance_size = actual_instance_size;
1511 * The last two steps are sometimes reversed, but that only changes the way in which
1512 * the race condition works.
1514 * Assume thread A goes through this function and makes it to the critical point.
1515 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1516 * immediately, but `instance_size` is incorrect.
1518 * The other case looks like this:
1520 * if (class->setup_fields_called)
1522 * ... critical point X
1523 * class->instance_size = 0;
1524 * ... critical point Y
1525 * class->instance_size = actual_instance_size;
1527 * class->setup_fields_called = 1;
1529 * Assume thread A goes through the function and makes it to critical point X. Now
1530 * thread B runs through the whole of the function, returning, assuming
1531 * `instance_size` is set. At that point thread A gets to run and makes it to
1532 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1535 if (class->setup_fields_called)
1538 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1540 * This happens when a generic instance of an unfinished generic typebuilder
1541 * is used as an element type for creating an array type. We can't initialize
1542 * the fields of this class using the fields of gklass, since gklass is not
1543 * finished yet, fields could be added to it later.
1548 mono_class_setup_basic_field_info (class);
1549 top = class->field.count;
1552 mono_class_setup_fields (gtd);
1553 if (gtd->exception_type) {
1554 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1559 class->instance_size = 0;
1561 class->sizes.class_size = 0;
1563 if (class->parent) {
1564 /* For generic instances, class->parent might not have been initialized */
1565 mono_class_init (class->parent);
1566 if (!class->parent->size_inited) {
1567 mono_class_setup_fields (class->parent);
1568 if (class->parent->exception_type) {
1569 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1573 class->instance_size += class->parent->instance_size;
1574 class->min_align = class->parent->min_align;
1575 /* we use |= since it may have been set already */
1576 class->has_references |= class->parent->has_references;
1577 blittable = class->parent->blittable;
1579 class->instance_size = sizeof (MonoObject);
1580 class->min_align = 1;
1583 /* We can't really enable 16 bytes alignment until the GC supports it.
1584 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1585 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1586 Bug #506144 is an example of this issue.
1588 if (class->simd_type)
1589 class->min_align = 16;
1591 /* Get the real size */
1592 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1594 if (explicit_size) {
1595 if ((packing_size & 0xffffff00) != 0) {
1596 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1597 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1600 class->packing_size = packing_size;
1601 real_size += class->instance_size;
1605 if (explicit_size && real_size) {
1606 class->instance_size = MAX (real_size, class->instance_size);
1608 class->blittable = blittable;
1609 mono_memory_barrier ();
1610 class->size_inited = 1;
1611 class->fields_inited = 1;
1612 class->setup_fields_called = 1;
1616 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
1619 /* Prevent infinite loops if the class references itself */
1620 class->setup_fields_called = 1;
1622 if (class->generic_container) {
1623 container = class->generic_container;
1625 container = gtd->generic_container;
1626 g_assert (container);
1630 * Fetch all the field information.
1632 for (i = 0; i < top; i++){
1633 int idx = class->field.first + i;
1634 field = &class->fields [i];
1636 field->parent = class;
1639 mono_field_resolve_type (field, &error);
1640 if (!mono_error_ok (&error)) {
1641 /*mono_field_resolve_type already failed class*/
1642 mono_error_cleanup (&error);
1646 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1647 g_assert (field->type);
1650 if (mono_field_is_deleted (field))
1653 MonoClassField *gfield = >d->fields [i];
1654 field->offset = gfield->offset;
1656 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1658 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1659 field->offset = offset;
1661 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1665 if (field->offset < -1) { /*-1 is used to encode special static fields */
1666 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1669 if (class->generic_container) {
1670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1676 /* Only do these checks if we still think this type is blittable */
1677 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1678 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1681 MonoClass *field_class = mono_class_from_mono_type (field->type);
1683 mono_class_setup_fields (field_class);
1684 if (field_class->exception_type) {
1685 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1689 if (!field_class || !field_class->blittable)
1694 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1695 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1696 blittable = class->element_class->blittable;
1699 if (mono_type_has_exceptions (field->type)) {
1700 char *class_name = mono_type_get_full_name (class);
1701 char *type_name = mono_type_full_name (field->type);
1703 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1704 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1705 g_free (class_name);
1709 /* The def_value of fields is compute lazily during vtable creation */
1712 if (class == mono_defaults.string_class)
1715 class->blittable = blittable;
1717 if (class->enumtype && !mono_class_enum_basetype (class)) {
1718 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1721 if (explicit_size && real_size) {
1722 class->instance_size = MAX (real_size, class->instance_size);
1725 if (class->exception_type)
1727 mono_class_layout_fields (class);
1729 /*valuetypes can't be neither bigger than 1Mb or empty. */
1730 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1731 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1733 mono_memory_barrier ();
1734 class->fields_inited = 1;
1738 * mono_class_setup_fields_locking:
1739 * @class: The class to initialize
1741 * Initializes the class->fields array of fields.
1742 * Aquires the loader lock.
1745 mono_class_setup_fields_locking (MonoClass *class)
1747 /* This can be checked without locks */
1748 if (class->fields_inited)
1750 mono_loader_lock ();
1751 mono_class_setup_fields (class);
1752 mono_loader_unlock ();
1756 * mono_class_has_references:
1758 * Returns whenever @klass->has_references is set, initializing it if needed.
1759 * Aquires the loader lock.
1762 mono_class_has_references (MonoClass *klass)
1764 if (klass->init_pending) {
1765 /* Be conservative */
1768 mono_class_init (klass);
1770 return klass->has_references;
1775 * mono_type_get_basic_type_from_generic:
1778 * Returns a closed type corresponding to the possibly open type
1782 mono_type_get_basic_type_from_generic (MonoType *type)
1784 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1785 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1786 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1787 return &mono_defaults.object_class->byval_arg;
1792 type_has_references (MonoClass *klass, MonoType *ftype)
1794 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1796 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1797 MonoGenericParam *gparam = ftype->data.generic_param;
1799 if (gparam->gshared_constraint)
1800 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1806 * mono_class_layout_fields:
1809 * Compute the placement of fields inside an object or struct, according to
1810 * the layout rules and set the following fields in @class:
1811 * - has_references (if the class contains instance references firled or structs that contain references)
1812 * - has_static_refs (same, but for static fields)
1813 * - instance_size (size of the object in memory)
1814 * - class_size (size needed for the static fields)
1815 * - size_inited (flag set when the instance_size is set)
1817 * LOCKING: this is supposed to be called with the loader lock held.
1820 mono_class_layout_fields (MonoClass *class)
1823 const int top = class->field.count;
1824 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1825 guint32 pass, passes, real_size;
1826 gboolean gc_aware_layout = FALSE;
1827 gboolean has_static_fields = FALSE;
1828 MonoClassField *field;
1831 * When we do generic sharing we need to have layout
1832 * information for open generic classes (either with a generic
1833 * context containing type variables or with a generic
1834 * container), so we don't return in that case anymore.
1838 * Enable GC aware auto layout: in this mode, reference
1839 * fields are grouped together inside objects, increasing collector
1841 * Requires that all classes whose layout is known to native code be annotated
1842 * with [StructLayout (LayoutKind.Sequential)]
1843 * Value types have gc_aware_layout disabled by default, as per
1844 * what the default is for other runtimes.
1846 /* corlib is missing [StructLayout] directives in many places */
1847 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1848 if (!class->valuetype)
1849 gc_aware_layout = TRUE;
1852 /* Compute klass->has_references */
1854 * Process non-static fields first, since static fields might recursively
1855 * refer to the class itself.
1857 for (i = 0; i < top; i++) {
1860 field = &class->fields [i];
1862 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1863 ftype = mono_type_get_underlying_type (field->type);
1864 ftype = mono_type_get_basic_type_from_generic (ftype);
1865 if (type_has_references (class, ftype))
1866 class->has_references = TRUE;
1870 for (i = 0; i < top; i++) {
1873 field = &class->fields [i];
1875 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1876 ftype = mono_type_get_underlying_type (field->type);
1877 ftype = mono_type_get_basic_type_from_generic (ftype);
1878 if (type_has_references (class, ftype))
1879 class->has_static_refs = TRUE;
1883 for (i = 0; i < top; i++) {
1886 field = &class->fields [i];
1888 ftype = mono_type_get_underlying_type (field->type);
1889 ftype = mono_type_get_basic_type_from_generic (ftype);
1890 if (type_has_references (class, ftype)) {
1891 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1892 class->has_static_refs = TRUE;
1894 class->has_references = TRUE;
1899 * Compute field layout and total size (not considering static fields)
1903 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1904 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1906 if (gc_aware_layout)
1911 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1914 if (class->parent) {
1915 mono_class_setup_fields (class->parent);
1916 if (class->parent->exception_type) {
1917 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1920 real_size = class->parent->instance_size;
1922 real_size = sizeof (MonoObject);
1925 for (pass = 0; pass < passes; ++pass) {
1926 for (i = 0; i < top; i++){
1931 field = &class->fields [i];
1933 if (mono_field_is_deleted (field))
1935 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1938 ftype = mono_type_get_underlying_type (field->type);
1939 ftype = mono_type_get_basic_type_from_generic (ftype);
1940 if (gc_aware_layout) {
1941 if (type_has_references (class, ftype)) {
1950 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1951 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1952 /* This field is a hack inserted by MCS to empty structures */
1956 size = mono_type_size (field->type, &align);
1958 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1959 align = class->packing_size ? MIN (class->packing_size, align): align;
1960 /* if the field has managed references, we need to force-align it
1963 if (type_has_references (class, ftype))
1964 align = MAX (align, sizeof (gpointer));
1966 class->min_align = MAX (align, class->min_align);
1967 field->offset = real_size;
1969 field->offset += align - 1;
1970 field->offset &= ~(align - 1);
1972 /*TypeBuilders produce all sort of weird things*/
1973 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1974 real_size = field->offset + size;
1977 class->instance_size = MAX (real_size, class->instance_size);
1979 if (class->instance_size & (class->min_align - 1)) {
1980 class->instance_size += class->min_align - 1;
1981 class->instance_size &= ~(class->min_align - 1);
1985 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1989 for (i = 0; i < top; i++) {
1994 field = &class->fields [i];
1997 * There must be info about all the fields in a type if it
1998 * uses explicit layout.
2000 if (mono_field_is_deleted (field))
2002 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2005 size = mono_type_size (field->type, &align);
2006 align = class->packing_size ? MIN (class->packing_size, align): align;
2007 class->min_align = MAX (align, class->min_align);
2010 * When we get here, field->offset is already set by the
2011 * loader (for either runtime fields or fields loaded from metadata).
2012 * The offset is from the start of the object: this works for both
2013 * classes and valuetypes.
2015 field->offset += sizeof (MonoObject);
2016 ftype = mono_type_get_underlying_type (field->type);
2017 ftype = mono_type_get_basic_type_from_generic (ftype);
2018 if (type_has_references (class, ftype)) {
2019 if (field->offset % sizeof (gpointer)) {
2020 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2027 real_size = MAX (real_size, size + field->offset);
2030 if (class->has_references) {
2031 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2033 /* Check for overlapping reference and non-reference fields */
2034 for (i = 0; i < top; i++) {
2037 field = &class->fields [i];
2039 if (mono_field_is_deleted (field))
2041 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2043 ftype = mono_type_get_underlying_type (field->type);
2044 if (MONO_TYPE_IS_REFERENCE (ftype))
2045 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2047 for (i = 0; i < top; i++) {
2048 field = &class->fields [i];
2050 if (mono_field_is_deleted (field))
2052 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2055 // FIXME: Too much code does this
2057 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2058 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);
2059 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2063 g_free (ref_bitmap);
2066 class->instance_size = MAX (real_size, class->instance_size);
2067 if (class->instance_size & (class->min_align - 1)) {
2068 class->instance_size += class->min_align - 1;
2069 class->instance_size &= ~(class->min_align - 1);
2075 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2077 * This leads to all kinds of problems with nested structs, so only
2078 * enable it when a MONO_DEBUG property is set.
2080 * For small structs, set min_align to at least the struct size to improve
2081 * performance, and since the JIT memset/memcpy code assumes this and generates
2082 * unaligned accesses otherwise. See #78990 for a testcase.
2084 if (mono_align_small_structs) {
2085 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2086 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2090 mono_memory_barrier ();
2091 class->size_inited = 1;
2094 * Compute static field layout and size
2096 for (i = 0; i < top; i++){
2100 field = &class->fields [i];
2102 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2104 if (mono_field_is_deleted (field))
2107 if (mono_type_has_exceptions (field->type)) {
2108 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2112 has_static_fields = TRUE;
2114 size = mono_type_size (field->type, &align);
2115 field->offset = class->sizes.class_size;
2116 /*align is always non-zero here*/
2117 field->offset += align - 1;
2118 field->offset &= ~(align - 1);
2119 class->sizes.class_size = field->offset + size;
2122 if (has_static_fields && class->sizes.class_size == 0)
2123 /* Simplify code which depends on class_size != 0 if the class has static fields */
2124 class->sizes.class_size = 8;
2128 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2132 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2133 method->klass = class;
2134 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2135 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2136 method->signature = sig;
2137 method->name = name;
2140 if (name [0] == '.') {
2141 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2143 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2149 * mono_class_setup_methods:
2152 * Initializes the 'methods' array in CLASS.
2153 * Calling this method should be avoided if possible since it allocates a lot
2154 * of long-living MonoMethod structures.
2155 * Methods belonging to an interface are assigned a sequential slot starting
2158 * On failure this function sets class->exception_type
2161 mono_class_setup_methods (MonoClass *class)
2164 MonoMethod **methods;
2169 if (class->generic_class) {
2171 MonoClass *gklass = class->generic_class->container_class;
2173 mono_class_init (gklass);
2174 if (!gklass->exception_type)
2175 mono_class_setup_methods (gklass);
2176 if (gklass->exception_type) {
2177 /* FIXME make exception_data less opaque so it's possible to dup it here */
2178 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2182 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2183 count = gklass->method.count;
2184 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2186 for (i = 0; i < count; i++) {
2187 methods [i] = mono_class_inflate_generic_method_full_checked (
2188 gklass->methods [i], class, mono_class_get_context (class), &error);
2189 if (!mono_error_ok (&error)) {
2190 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2191 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)));
2194 mono_error_cleanup (&error);
2198 } else if (class->rank) {
2200 MonoMethod *amethod;
2201 MonoMethodSignature *sig;
2202 int count_generic = 0, first_generic = 0;
2204 gboolean jagged_ctor = FALSE;
2206 count = 3 + (class->rank > 1? 2: 1);
2208 mono_class_setup_interfaces (class, &error);
2209 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2211 if (class->rank == 1 && class->element_class->rank) {
2213 class->method.count ++;
2216 if (class->interface_count) {
2217 count_generic = generic_array_methods (class);
2218 first_generic = count;
2219 count += class->interface_count * count_generic;
2222 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2224 sig = mono_metadata_signature_alloc (class->image, class->rank);
2225 sig->ret = &mono_defaults.void_class->byval_arg;
2226 sig->pinvoke = TRUE;
2227 sig->hasthis = TRUE;
2228 for (i = 0; i < class->rank; ++i)
2229 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2231 amethod = create_array_method (class, ".ctor", sig);
2232 methods [method_num++] = amethod;
2233 if (class->rank > 1) {
2234 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2235 sig->ret = &mono_defaults.void_class->byval_arg;
2236 sig->pinvoke = TRUE;
2237 sig->hasthis = TRUE;
2238 for (i = 0; i < class->rank * 2; ++i)
2239 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2241 amethod = create_array_method (class, ".ctor", sig);
2242 methods [method_num++] = amethod;
2246 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2247 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2248 sig->ret = &mono_defaults.void_class->byval_arg;
2249 sig->pinvoke = TRUE;
2250 sig->hasthis = TRUE;
2251 for (i = 0; i < class->rank + 1; ++i)
2252 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2253 amethod = create_array_method (class, ".ctor", sig);
2254 methods [method_num++] = amethod;
2257 /* element Get (idx11, [idx2, ...]) */
2258 sig = mono_metadata_signature_alloc (class->image, class->rank);
2259 sig->ret = &class->element_class->byval_arg;
2260 sig->pinvoke = TRUE;
2261 sig->hasthis = TRUE;
2262 for (i = 0; i < class->rank; ++i)
2263 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2264 amethod = create_array_method (class, "Get", sig);
2265 methods [method_num++] = amethod;
2266 /* element& Address (idx11, [idx2, ...]) */
2267 sig = mono_metadata_signature_alloc (class->image, class->rank);
2268 sig->ret = &class->element_class->this_arg;
2269 sig->pinvoke = TRUE;
2270 sig->hasthis = TRUE;
2271 for (i = 0; i < class->rank; ++i)
2272 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2273 amethod = create_array_method (class, "Address", sig);
2274 methods [method_num++] = amethod;
2275 /* void Set (idx11, [idx2, ...], element) */
2276 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2277 sig->ret = &mono_defaults.void_class->byval_arg;
2278 sig->pinvoke = TRUE;
2279 sig->hasthis = TRUE;
2280 for (i = 0; i < class->rank; ++i)
2281 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2282 sig->params [i] = &class->element_class->byval_arg;
2283 amethod = create_array_method (class, "Set", sig);
2284 methods [method_num++] = amethod;
2286 for (i = 0; i < class->interface_count; i++)
2287 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2291 count = class->method.count;
2292 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2293 for (i = 0; i < count; ++i) {
2294 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2295 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2297 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)));
2298 mono_error_cleanup (&error);
2303 if (MONO_CLASS_IS_INTERFACE (class)) {
2305 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2306 for (i = 0; i < count; ++i) {
2307 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2308 methods [i]->slot = slot++;
2312 mono_image_lock (class->image);
2314 if (!class->methods) {
2315 class->method.count = count;
2317 /* Needed because of the double-checking locking pattern */
2318 mono_memory_barrier ();
2320 class->methods = methods;
2323 mono_image_unlock (class->image);
2327 * mono_class_get_method_by_index:
2329 * Returns class->methods [index], initializing class->methods if neccesary.
2331 * LOCKING: Acquires the loader lock.
2334 mono_class_get_method_by_index (MonoClass *class, int index)
2337 /* Avoid calling setup_methods () if possible */
2338 if (class->generic_class && !class->methods) {
2339 MonoClass *gklass = class->generic_class->container_class;
2342 m = mono_class_inflate_generic_method_full_checked (
2343 gklass->methods [index], class, mono_class_get_context (class), &error);
2344 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2346 * If setup_methods () is called later for this class, no duplicates are created,
2347 * since inflate_generic_method guarantees that only one instance of a method
2348 * is created for each context.
2351 mono_class_setup_methods (class);
2352 g_assert (m == class->methods [index]);
2356 mono_class_setup_methods (class);
2357 if (class->exception_type) /*FIXME do proper error handling*/
2359 g_assert (index >= 0 && index < class->method.count);
2360 return class->methods [index];
2365 * mono_class_get_inflated_method:
2367 * Given an inflated class CLASS and a method METHOD which should be a method of
2368 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2371 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2373 MonoClass *gklass = class->generic_class->container_class;
2376 g_assert (method->klass == gklass);
2378 mono_class_setup_methods (gklass);
2379 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2381 for (i = 0; i < gklass->method.count; ++i) {
2382 if (gklass->methods [i] == method) {
2383 if (class->methods) {
2384 return class->methods [i];
2387 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2388 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2398 * mono_class_get_vtable_entry:
2400 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2401 * LOCKING: Acquires the loader lock.
2404 mono_class_get_vtable_entry (MonoClass *class, int offset)
2408 if (class->rank == 1) {
2410 * szarrays do not overwrite any methods of Array, so we can avoid
2411 * initializing their vtables in some cases.
2413 mono_class_setup_vtable (class->parent);
2414 if (offset < class->parent->vtable_size)
2415 return class->parent->vtable [offset];
2418 if (class->generic_class) {
2420 MonoClass *gklass = class->generic_class->container_class;
2421 mono_class_setup_vtable (gklass);
2422 m = gklass->vtable [offset];
2424 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2425 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2427 mono_class_setup_vtable (class);
2428 if (class->exception_type)
2430 m = class->vtable [offset];
2437 * mono_class_get_vtable_size:
2439 * Return the vtable size for KLASS.
2442 mono_class_get_vtable_size (MonoClass *klass)
2444 mono_class_setup_vtable (klass);
2446 return klass->vtable_size;
2450 * mono_class_setup_properties:
2452 * Initialize class->ext.property and class->ext.properties.
2454 * This method can fail the class.
2457 mono_class_setup_properties (MonoClass *class)
2459 guint startm, endm, i, j;
2460 guint32 cols [MONO_PROPERTY_SIZE];
2461 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2462 MonoProperty *properties;
2466 if (class->ext && class->ext->properties)
2469 if (class->generic_class) {
2470 MonoClass *gklass = class->generic_class->container_class;
2472 mono_class_init (gklass);
2473 mono_class_setup_properties (gklass);
2474 if (gklass->exception_type) {
2475 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2479 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2481 for (i = 0; i < gklass->ext->property.count; i++) {
2483 MonoProperty *prop = &properties [i];
2485 *prop = gklass->ext->properties [i];
2488 prop->get = mono_class_inflate_generic_method_full_checked (
2489 prop->get, class, mono_class_get_context (class), &error);
2491 prop->set = mono_class_inflate_generic_method_full_checked (
2492 prop->set, class, mono_class_get_context (class), &error);
2494 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2495 prop->parent = class;
2498 first = gklass->ext->property.first;
2499 count = gklass->ext->property.count;
2501 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2502 count = last - first;
2505 mono_class_setup_methods (class);
2506 if (class->exception_type)
2510 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2511 for (i = first; i < last; ++i) {
2512 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2513 properties [i - first].parent = class;
2514 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2515 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2517 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2518 for (j = startm; j < endm; ++j) {
2521 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2523 if (class->image->uncompressed_metadata) {
2525 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2526 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2527 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2529 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2532 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2533 case METHOD_SEMANTIC_SETTER:
2534 properties [i - first].set = method;
2536 case METHOD_SEMANTIC_GETTER:
2537 properties [i - first].get = method;
2546 mono_class_alloc_ext (class);
2548 mono_image_lock (class->image);
2550 if (class->ext->properties) {
2551 /* We leak 'properties' which was allocated from the image mempool */
2552 mono_image_unlock (class->image);
2556 class->ext->property.first = first;
2557 class->ext->property.count = count;
2559 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2560 mono_memory_barrier ();
2562 /* Leave this assignment as the last op in the function */
2563 class->ext->properties = properties;
2565 mono_image_unlock (class->image);
2569 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2571 MonoMethod **om, **retval;
2574 for (om = methods, count = 0; *om; ++om, ++count)
2577 retval = g_new0 (MonoMethod*, count + 1);
2579 for (om = methods, count = 0; *om; ++om, ++count) {
2581 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2582 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2588 /*This method can fail the class.*/
2590 mono_class_setup_events (MonoClass *class)
2593 guint startm, endm, i, j;
2594 guint32 cols [MONO_EVENT_SIZE];
2595 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2599 if (class->ext && class->ext->events)
2602 if (class->generic_class) {
2603 MonoClass *gklass = class->generic_class->container_class;
2604 MonoGenericContext *context = NULL;
2606 mono_class_setup_events (gklass);
2607 if (gklass->exception_type) {
2608 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2612 first = gklass->ext->event.first;
2613 count = gklass->ext->event.count;
2615 events = mono_class_new0 (class, MonoEvent, count);
2618 context = mono_class_get_context (class);
2620 for (i = 0; i < count; i++) {
2622 MonoEvent *event = &events [i];
2623 MonoEvent *gevent = &gklass->ext->events [i];
2625 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2627 event->parent = class;
2628 event->name = gevent->name;
2629 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2630 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2631 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2632 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2633 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2634 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2636 #ifndef MONO_SMALL_CONFIG
2637 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2639 event->attrs = gevent->attrs;
2642 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2643 count = last - first;
2646 mono_class_setup_methods (class);
2647 if (class->exception_type) {
2648 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2653 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2654 for (i = first; i < last; ++i) {
2655 MonoEvent *event = &events [i - first];
2657 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2658 event->parent = class;
2659 event->attrs = cols [MONO_EVENT_FLAGS];
2660 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2662 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2663 for (j = startm; j < endm; ++j) {
2666 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2668 if (class->image->uncompressed_metadata) {
2670 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2671 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2672 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2674 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2677 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2678 case METHOD_SEMANTIC_ADD_ON:
2679 event->add = method;
2681 case METHOD_SEMANTIC_REMOVE_ON:
2682 event->remove = method;
2684 case METHOD_SEMANTIC_FIRE:
2685 event->raise = method;
2687 case METHOD_SEMANTIC_OTHER: {
2688 #ifndef MONO_SMALL_CONFIG
2691 if (event->other == NULL) {
2692 event->other = g_new0 (MonoMethod*, 2);
2694 while (event->other [n])
2696 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2698 event->other [n] = method;
2699 /* NULL terminated */
2700 event->other [n + 1] = NULL;
2711 mono_class_alloc_ext (class);
2713 mono_image_lock (class->image);
2715 if (class->ext->events) {
2716 mono_image_unlock (class->image);
2720 class->ext->event.first = first;
2721 class->ext->event.count = count;
2723 /* Flush any pending writes as we do double checked locking on class->ext.events */
2724 mono_memory_barrier ();
2726 /* Leave this assignment as the last op in the function */
2727 class->ext->events = events;
2729 mono_image_unlock (class->image);
2733 * Global pool of interface IDs, represented as a bitset.
2734 * LOCKING: Protected by the classes lock.
2736 static MonoBitSet *global_interface_bitset = NULL;
2739 * mono_unload_interface_ids:
2740 * @bitset: bit set of interface IDs
2742 * When an image is unloaded, the interface IDs associated with
2743 * the image are put back in the global pool of IDs so the numbers
2747 mono_unload_interface_ids (MonoBitSet *bitset)
2750 mono_bitset_sub (global_interface_bitset, bitset);
2755 mono_unload_interface_id (MonoClass *class)
2757 if (global_interface_bitset && class->interface_id) {
2759 mono_bitset_clear (global_interface_bitset, class->interface_id);
2765 * mono_get_unique_iid:
2768 * Assign a unique integer ID to the interface represented by @class.
2769 * The ID will positive and as small as possible.
2770 * LOCKING: Acquires the classes lock.
2771 * Returns: the new ID.
2774 mono_get_unique_iid (MonoClass *class)
2778 g_assert (MONO_CLASS_IS_INTERFACE (class));
2782 if (!global_interface_bitset) {
2783 global_interface_bitset = mono_bitset_new (128, 0);
2786 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2788 int old_size = mono_bitset_size (global_interface_bitset);
2789 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2790 mono_bitset_free (global_interface_bitset);
2791 global_interface_bitset = new_set;
2794 mono_bitset_set (global_interface_bitset, iid);
2795 /* set the bit also in the per-image set */
2796 if (!class->generic_class) {
2797 if (class->image->interface_bitset) {
2798 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2799 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2800 mono_bitset_free (class->image->interface_bitset);
2801 class->image->interface_bitset = new_set;
2804 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2806 mono_bitset_set (class->image->interface_bitset, iid);
2811 #ifndef MONO_SMALL_CONFIG
2812 if (mono_print_vtable) {
2814 char *type_name = mono_type_full_name (&class->byval_arg);
2815 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2816 generic_id = class->generic_class->context.class_inst->id;
2817 g_assert (generic_id != 0);
2821 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2826 g_assert (iid <= 65535);
2831 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2836 mono_class_setup_interfaces (klass, error);
2837 if (!mono_error_ok (error))
2840 for (i = 0; i < klass->interface_count; i++) {
2841 ic = klass->interfaces [i];
2844 *res = g_ptr_array_new ();
2845 g_ptr_array_add (*res, ic);
2846 mono_class_init (ic);
2847 if (ic->exception_type) {
2848 mono_error_set_type_load_class (error, ic, "Error Loading class");
2852 collect_implemented_interfaces_aux (ic, res, error);
2853 if (!mono_error_ok (error))
2859 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2861 GPtrArray *res = NULL;
2863 collect_implemented_interfaces_aux (klass, &res, error);
2864 if (!mono_error_ok (error)) {
2866 g_ptr_array_free (res, TRUE);
2873 compare_interface_ids (const void *p_key, const void *p_element) {
2874 const MonoClass *key = p_key;
2875 const MonoClass *element = *(MonoClass**) p_element;
2877 return (key->interface_id - element->interface_id);
2880 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2882 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2883 MonoClass **result = mono_binary_search (
2885 klass->interfaces_packed,
2886 klass->interface_offsets_count,
2887 sizeof (MonoClass *),
2888 compare_interface_ids);
2890 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2897 * mono_class_interface_offset_with_variance:
2899 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2900 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2902 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2904 * FIXME figure out MS disambiguation rules and fix this function.
2907 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2908 int i = mono_class_interface_offset (klass, itf);
2909 *non_exact_match = FALSE;
2913 if (!mono_class_has_variant_generic_params (itf))
2916 for (i = 0; i < klass->interface_offsets_count; i++) {
2917 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2918 *non_exact_match = TRUE;
2919 return klass->interface_offsets_packed [i];
2927 print_implemented_interfaces (MonoClass *klass) {
2930 GPtrArray *ifaces = NULL;
2932 int ancestor_level = 0;
2934 name = mono_type_get_full_name (klass);
2935 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2938 for (i = 0; i < klass->interface_offsets_count; i++)
2939 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2940 klass->interfaces_packed [i]->interface_id,
2941 klass->interface_offsets_packed [i],
2942 klass->interfaces_packed [i]->method.count,
2943 klass->interfaces_packed [i]->name_space,
2944 klass->interfaces_packed [i]->name );
2945 printf ("Interface flags: ");
2946 for (i = 0; i <= klass->max_interface_id; i++)
2947 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2948 printf ("(%d,T)", i);
2950 printf ("(%d,F)", i);
2952 printf ("Dump interface flags:");
2953 #ifdef COMPRESSED_INTERFACE_BITMAP
2955 const uint8_t* p = klass->interface_bitmap;
2956 i = klass->max_interface_id;
2958 printf (" %d x 00 %02X", p [0], p [1]);
2964 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2965 printf (" %02X", klass->interface_bitmap [i]);
2968 while (klass != NULL) {
2969 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2970 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2971 if (!mono_error_ok (&error)) {
2972 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2973 mono_error_cleanup (&error);
2974 } else if (ifaces) {
2975 for (i = 0; i < ifaces->len; i++) {
2976 MonoClass *ic = g_ptr_array_index (ifaces, i);
2977 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2978 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2980 mono_class_interface_offset (klass, ic),
2985 g_ptr_array_free (ifaces, TRUE);
2988 klass = klass->parent;
2993 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2996 args [0] = &arg0->byval_arg;
2998 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3002 array_class_get_if_rank (MonoClass *class, guint rank)
3004 return rank ? mono_array_class_get (class, rank) : class;
3008 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3010 valuetype_types [0] = eclass;
3011 if (eclass == mono_defaults.int16_class)
3012 valuetype_types [1] = mono_defaults.uint16_class;
3013 else if (eclass == mono_defaults.uint16_class)
3014 valuetype_types [1] = mono_defaults.int16_class;
3015 else if (eclass == mono_defaults.int32_class)
3016 valuetype_types [1] = mono_defaults.uint32_class;
3017 else if (eclass == mono_defaults.uint32_class)
3018 valuetype_types [1] = mono_defaults.int32_class;
3019 else if (eclass == mono_defaults.int64_class)
3020 valuetype_types [1] = mono_defaults.uint64_class;
3021 else if (eclass == mono_defaults.uint64_class)
3022 valuetype_types [1] = mono_defaults.int64_class;
3023 else if (eclass == mono_defaults.byte_class)
3024 valuetype_types [1] = mono_defaults.sbyte_class;
3025 else if (eclass == mono_defaults.sbyte_class)
3026 valuetype_types [1] = mono_defaults.byte_class;
3027 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3028 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3031 /* this won't be needed once bug #325495 is completely fixed
3032 * though we'll need something similar to know which interfaces to allow
3033 * in arrays when they'll be lazyly created
3035 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3036 * MS returns diferrent types based on which instance is called. For example:
3037 * object obj = new byte[10][];
3038 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3039 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3042 * Fixing this should kill quite some code, save some bits and improve compatibility.
3045 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3047 MonoClass *eclass = class->element_class;
3048 static MonoClass* generic_icollection_class = NULL;
3049 static MonoClass* generic_ienumerable_class = NULL;
3050 static MonoClass* generic_ienumerator_class = NULL;
3051 static MonoClass* generic_ireadonlylist_class = NULL;
3052 static MonoClass* generic_ireadonlycollection_class = NULL;
3053 MonoClass *valuetype_types[2] = { NULL, NULL };
3054 MonoClass **interfaces = NULL;
3055 int i, nifaces, interface_count, real_count, original_rank;
3057 gboolean internal_enumerator;
3058 gboolean eclass_is_valuetype;
3060 if (!mono_defaults.generic_ilist_class) {
3064 internal_enumerator = FALSE;
3065 eclass_is_valuetype = FALSE;
3066 original_rank = eclass->rank;
3067 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3068 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3070 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3072 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3073 original_rank = eclass->rank;
3075 eclass = eclass->element_class;
3076 internal_enumerator = TRUE;
3077 *is_enumerator = TRUE;
3085 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3086 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3088 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3090 if (!generic_icollection_class) {
3091 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3092 "System.Collections.Generic", "ICollection`1");
3093 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3094 "System.Collections.Generic", "IEnumerable`1");
3095 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3096 "System.Collections.Generic", "IEnumerator`1");
3097 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3098 "System.Collections.Generic", "IReadOnlyList`1");
3099 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3100 "System.Collections.Generic", "IReadOnlyCollection`1");
3103 mono_class_init (eclass);
3106 * Arrays in 2.0 need to implement a number of generic interfaces
3107 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3108 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3109 * We collect the types needed to build the
3110 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3111 * the generic interfaces needed to implement.
3113 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3114 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3116 if (eclass->valuetype) {
3117 nifaces = generic_ireadonlylist_class ? 5 : 3;
3118 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3120 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3121 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3122 if (internal_enumerator) {
3124 if (valuetype_types [1])
3128 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3129 interfaces [0] = valuetype_types [0];
3130 if (valuetype_types [1])
3131 interfaces [nifaces] = valuetype_types [1];
3133 eclass_is_valuetype = TRUE;
3136 int idepth = eclass->idepth;
3137 if (!internal_enumerator)
3139 nifaces = generic_ireadonlylist_class ? 2 : 3;
3141 // FIXME: This doesn't seem to work/required for generic params
3142 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3143 mono_class_setup_interface_offsets (eclass);
3145 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3146 /* we add object for interfaces and the supertypes for the other
3147 * types. The last of the supertypes is the element class itself which we
3148 * already created the explicit interfaces for (so we include it for IEnumerator
3149 * and exclude it for arrays).
3151 if (MONO_CLASS_IS_INTERFACE (eclass))
3154 interface_count += idepth;
3155 if (eclass->rank && eclass->element_class->valuetype) {
3156 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3157 if (valuetype_types [1])
3160 /* IList, ICollection, IEnumerable, IReadOnlyList */
3161 interface_count *= nifaces;
3162 real_count = interface_count;
3163 if (internal_enumerator) {
3164 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3165 if (valuetype_types [1])
3168 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3169 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3170 interfaces [0] = mono_defaults.object_class;
3174 for (i = 0; i < idepth; i++) {
3175 mono_class_init (eclass->supertypes [i]);
3176 interfaces [j] = eclass->supertypes [i];
3180 if (all_interfaces) {
3181 for (i = 0; i < eclass->interface_offsets_count; i++) {
3182 interfaces [j] = eclass->interfaces_packed [i];
3186 for (i = 0; i < eclass->interface_count; i++) {
3187 interfaces [j] = eclass->interfaces [i];
3191 if (valuetype_types [1]) {
3192 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3197 /* instantiate the generic interfaces */
3198 for (i = 0; i < interface_count; i += nifaces) {
3199 MonoClass *iface = interfaces [i];
3201 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3202 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3204 if (eclass->valuetype) {
3205 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3206 if (generic_ireadonlylist_class) {
3207 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3208 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3211 if (!generic_ireadonlylist_class)
3212 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3215 if (internal_enumerator) {
3217 /* instantiate IEnumerator<iface> */
3218 for (i = 0; i < interface_count; i++) {
3219 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3221 j = interface_count;
3222 if (!eclass_is_valuetype) {
3223 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3224 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3227 for (i = 0; i < eclass->idepth; i++) {
3228 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3232 for (i = 0; i < eclass->interface_offsets_count; i++) {
3233 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3237 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3239 if (valuetype_types [1])
3240 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3244 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3245 for (i = 0; i < real_count; ++i) {
3246 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3247 g_print ("%s implements %s\n", type_name, name);
3258 find_array_interface (MonoClass *klass, const char *name)
3261 for (i = 0; i < klass->interface_count; ++i) {
3262 if (strcmp (klass->interfaces [i]->name, name) == 0)
3269 * Return the number of virtual methods.
3270 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3271 * Return -1 on failure.
3272 * FIXME It would be nice if this information could be cached somewhere.
3275 count_virtual_methods (MonoClass *class)
3279 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3281 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3282 mono_class_setup_methods (class);
3283 if (class->exception_type)
3286 for (i = 0; i < class->method.count; ++i) {
3287 flags = class->methods [i]->flags;
3288 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3292 for (i = 0; i < class->method.count; ++i) {
3293 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3295 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3303 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3311 m = (l + num_ifaces) / 2;
3312 if (interfaces_full [m] == ic)
3314 if (l == num_ifaces)
3316 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3325 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3327 int i = find_interface (num_ifaces, interfaces_full, ic);
3329 return interface_offsets_full [i];
3334 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3336 int i = find_interface (num_ifaces, interfaces_full, ic);
3340 interface_offsets_full [i] = offset;
3343 for (i = 0; i < num_ifaces; ++i) {
3344 if (interfaces_full [i]) {
3346 if (interfaces_full [i]->interface_id < ic->interface_id)
3349 while (end < num_ifaces && interfaces_full [end]) end++;
3350 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3351 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3353 interfaces_full [i] = ic;
3354 interface_offsets_full [i] = offset;
3360 #ifdef COMPRESSED_INTERFACE_BITMAP
3363 * Compressed interface bitmap design.
3365 * Interface bitmaps take a large amount of memory, because their size is
3366 * linear with the maximum interface id assigned in the process (each interface
3367 * is assigned a unique id as it is loaded). The number of interface classes
3368 * is high because of the many implicit interfaces implemented by arrays (we'll
3369 * need to lazy-load them in the future).
3370 * Most classes implement a very small number of interfaces, so the bitmap is
3371 * sparse. This bitmap needs to be checked by interface casts, so access to the
3372 * needed bit must be fast and doable with few jit instructions.
3374 * The current compression format is as follows:
3375 * *) it is a sequence of one or more two-byte elements
3376 * *) the first byte in the element is the count of empty bitmap bytes
3377 * at the current bitmap position
3378 * *) the second byte in the element is an actual bitmap byte at the current
3381 * As an example, the following compressed bitmap bytes:
3382 * 0x07 0x01 0x00 0x7
3383 * correspond to the following bitmap:
3384 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3386 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3387 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3388 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3392 * mono_compress_bitmap:
3393 * @dest: destination buffer
3394 * @bitmap: bitmap buffer
3395 * @size: size of @bitmap in bytes
3397 * This is a mono internal function.
3398 * The @bitmap data is compressed into a format that is small but
3399 * still searchable in few instructions by the JIT and runtime.
3400 * The compressed data is stored in the buffer pointed to by the
3401 * @dest array. Passing a #NULL value for @dest allows to just compute
3402 * the size of the buffer.
3403 * This compression algorithm assumes the bits set in the bitmap are
3404 * few and far between, like in interface bitmaps.
3405 * Returns: the size of the compressed bitmap in bytes.
3408 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3412 const uint8_t *end = bitmap + size;
3413 while (bitmap < end) {
3414 if (*bitmap || numz == 255) {
3438 * mono_class_interface_match:
3439 * @bitmap: a compressed bitmap buffer
3440 * @id: the index to check in the bitmap
3442 * This is a mono internal function.
3443 * Checks if a bit is set in a compressed interface bitmap. @id must
3444 * be already checked for being smaller than the maximum id encoded in the
3447 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3451 mono_class_interface_match (const uint8_t *bitmap, int id)
3454 id -= bitmap [0] * 8;
3458 return bitmap [1] & (1 << id);
3467 * LOCKING: this is supposed to be called with the loader lock held.
3468 * Return -1 on failure and set exception_type
3471 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3475 int i, j, max_iid, num_ifaces;
3476 MonoClass **interfaces_full = NULL;
3477 int *interface_offsets_full = NULL;
3479 GPtrArray **ifaces_array = NULL;
3480 int interface_offsets_count;
3481 MonoClass **array_interfaces = NULL;
3482 int num_array_interfaces;
3483 int is_enumerator = FALSE;
3485 mono_class_setup_supertypes (class);
3487 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3488 * implicit interfaces have the property that they are assigned the same slot in the
3489 * vtables for compatible interfaces
3491 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3493 /* compute maximum number of slots and maximum interface id */
3495 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3496 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3497 for (j = 0; j < class->idepth; j++) {
3498 k = class->supertypes [j];
3499 num_ifaces += k->interface_count;
3500 for (i = 0; i < k->interface_count; i++) {
3501 ic = k->interfaces [i];
3504 mono_class_init (ic);
3506 if (max_iid < ic->interface_id)
3507 max_iid = ic->interface_id;
3509 ifaces = mono_class_get_implemented_interfaces (k, &error);
3510 if (!mono_error_ok (&error)) {
3511 char *name = mono_type_get_full_name (k);
3512 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)));
3514 mono_error_cleanup (&error);
3519 num_ifaces += ifaces->len;
3520 for (i = 0; i < ifaces->len; ++i) {
3521 ic = g_ptr_array_index (ifaces, i);
3522 if (max_iid < ic->interface_id)
3523 max_iid = ic->interface_id;
3525 ifaces_array [j] = ifaces;
3529 for (i = 0; i < num_array_interfaces; ++i) {
3530 ic = array_interfaces [i];
3531 mono_class_init (ic);
3532 if (max_iid < ic->interface_id)
3533 max_iid = ic->interface_id;
3536 if (MONO_CLASS_IS_INTERFACE (class)) {
3538 if (max_iid < class->interface_id)
3539 max_iid = class->interface_id;
3541 class->max_interface_id = max_iid;
3542 /* compute vtable offset for interfaces */
3543 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3544 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3546 for (i = 0; i < num_ifaces; i++) {
3547 interface_offsets_full [i] = -1;
3550 /* skip the current class */
3551 for (j = 0; j < class->idepth - 1; j++) {
3552 k = class->supertypes [j];
3553 ifaces = ifaces_array [j];
3556 for (i = 0; i < ifaces->len; ++i) {
3558 ic = g_ptr_array_index (ifaces, i);
3560 /*Force the sharing of interface offsets between parent and subtypes.*/
3561 io = mono_class_interface_offset (k, ic);
3563 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3568 g_assert (class == class->supertypes [class->idepth - 1]);
3569 ifaces = ifaces_array [class->idepth - 1];
3571 for (i = 0; i < ifaces->len; ++i) {
3573 ic = g_ptr_array_index (ifaces, i);
3574 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3576 count = count_virtual_methods (ic);
3578 char *name = mono_type_get_full_name (ic);
3579 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3588 if (MONO_CLASS_IS_INTERFACE (class))
3589 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3591 if (num_array_interfaces) {
3592 if (is_enumerator) {
3593 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3594 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3595 g_assert (ienumerator_offset >= 0);
3596 for (i = 0; i < num_array_interfaces; ++i) {
3597 ic = array_interfaces [i];
3598 if (strcmp (ic->name, "IEnumerator`1") == 0)
3599 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3601 g_assert_not_reached ();
3602 /*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);*/
3605 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3606 int ilist_iface_idx = find_array_interface (class, "IList`1");
3607 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3608 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3609 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3610 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3611 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3612 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3613 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3614 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3615 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3616 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3617 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3618 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3619 for (i = 0; i < num_array_interfaces; ++i) {
3621 ic = array_interfaces [i];
3622 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3623 offset = ilist_offset;
3624 else if (strcmp (ic->name, "ICollection`1") == 0)
3625 offset = icollection_offset;
3626 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3627 offset = ienumerable_offset;
3628 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3629 offset = ireadonlylist_offset;
3630 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3631 offset = ireadonlycollection_offset;
3633 g_assert_not_reached ();
3634 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3635 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3640 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3641 if (interface_offsets_full [i] != -1) {
3642 interface_offsets_count ++;
3647 * We might get called multiple times:
3648 * - mono_class_init ()
3649 * - mono_class_setup_vtable ().
3650 * - mono_class_setup_interface_offsets ().
3651 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3652 * means we have to overwrite those when called from other places (#4440).
3654 if (class->interfaces_packed) {
3656 g_assert (class->interface_offsets_count == interface_offsets_count);
3660 class->interface_offsets_count = interface_offsets_count;
3661 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3662 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3663 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3664 #ifdef COMPRESSED_INTERFACE_BITMAP
3665 bitmap = g_malloc0 (bsize);
3667 bitmap = mono_class_alloc0 (class, bsize);
3669 for (i = 0; i < interface_offsets_count; i++) {
3670 int id = interfaces_full [i]->interface_id;
3671 bitmap [id >> 3] |= (1 << (id & 7));
3672 class->interfaces_packed [i] = interfaces_full [i];
3673 class->interface_offsets_packed [i] = interface_offsets_full [i];
3674 /*if (num_array_interfaces)
3675 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]);*/
3677 #ifdef COMPRESSED_INTERFACE_BITMAP
3678 i = mono_compress_bitmap (NULL, bitmap, bsize);
3679 class->interface_bitmap = mono_class_alloc0 (class, i);
3680 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3683 class->interface_bitmap = bitmap;
3688 g_free (interfaces_full);
3689 g_free (interface_offsets_full);
3690 g_free (array_interfaces);
3691 for (i = 0; i < class->idepth; i++) {
3692 ifaces = ifaces_array [i];
3694 g_ptr_array_free (ifaces, TRUE);
3696 g_free (ifaces_array);
3698 //printf ("JUST DONE: ");
3699 //print_implemented_interfaces (class);
3705 * Setup interface offsets for interfaces.
3707 * - class->max_interface_id
3708 * - class->interface_offsets_count
3709 * - class->interfaces_packed
3710 * - class->interface_offsets_packed
3711 * - class->interface_bitmap
3713 * This function can fail @class.
3716 mono_class_setup_interface_offsets (MonoClass *class)
3718 mono_loader_lock ();
3720 setup_interface_offsets (class, 0, FALSE);
3722 mono_loader_unlock ();
3725 /*Checks if @klass has @parent as one of it's parents type gtd
3729 * Bar<T> : Foo<Bar<Bar<T>>>
3733 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3735 klass = mono_class_get_generic_type_definition (klass);
3736 parent = mono_class_get_generic_type_definition (parent);
3737 mono_class_setup_supertypes (klass);
3738 mono_class_setup_supertypes (parent);
3740 return klass->idepth >= parent->idepth &&
3741 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3745 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3747 MonoGenericInst *ginst;
3749 if (!class->generic_class) {
3750 mono_class_setup_vtable_full (class, in_setup);
3751 return class->exception_type == 0;
3754 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3755 if (class->generic_class->container_class->exception_type) {
3756 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3760 ginst = class->generic_class->context.class_inst;
3761 for (i = 0; i < ginst->type_argc; ++i) {
3763 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3765 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3766 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3767 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3769 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3770 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3778 * mono_class_setup_vtable:
3780 * Creates the generic vtable of CLASS.
3781 * Initializes the following fields in MonoClass:
3784 * Plus all the fields initialized by setup_interface_offsets ().
3785 * If there is an error during vtable construction, class->exception_type is set.
3787 * LOCKING: Acquires the loader lock.
3790 mono_class_setup_vtable (MonoClass *class)
3792 mono_class_setup_vtable_full (class, NULL);
3796 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3798 MonoMethod **overrides;
3799 MonoGenericContext *context;
3807 if (MONO_CLASS_IS_INTERFACE (class)) {
3808 /* This sets method->slot for all methods if this is an interface */
3809 mono_class_setup_methods (class);
3813 if (class->exception_type)
3816 if (g_list_find (in_setup, class))
3819 mono_loader_lock ();
3821 if (class->vtable) {
3822 mono_loader_unlock ();
3826 mono_stats.generic_vtable_count ++;
3827 in_setup = g_list_prepend (in_setup, class);
3829 if (class->generic_class) {
3830 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3831 mono_loader_unlock ();
3832 g_list_remove (in_setup, class);
3836 context = mono_class_get_context (class);
3837 type_token = class->generic_class->container_class->type_token;
3839 context = (MonoGenericContext *) class->generic_container;
3840 type_token = class->type_token;
3843 if (image_is_dynamic (class->image)) {
3844 /* Generic instances can have zero method overrides without causing any harm.
3845 * This is true since we don't do layout all over again for them, we simply inflate
3846 * the layout of the parent.
3848 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3850 /* The following call fails if there are missing methods in the type */
3851 /* FIXME it's probably a good idea to avoid this for generic instances. */
3852 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3856 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3858 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3862 mono_loader_unlock ();
3863 g_list_remove (in_setup, class);
3868 #define DEBUG_INTERFACE_VTABLE_CODE 0
3869 #define TRACE_INTERFACE_VTABLE_CODE 0
3870 #define VERIFY_INTERFACE_VTABLE_CODE 0
3871 #define VTABLE_SELECTOR (1)
3873 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3874 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3875 if (!(VTABLE_SELECTOR)) break; \
3879 #define DEBUG_INTERFACE_VTABLE(stmt)
3882 #if TRACE_INTERFACE_VTABLE_CODE
3883 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3884 if (!(VTABLE_SELECTOR)) break; \
3888 #define TRACE_INTERFACE_VTABLE(stmt)
3891 #if VERIFY_INTERFACE_VTABLE_CODE
3892 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3893 if (!(VTABLE_SELECTOR)) break; \
3897 #define VERIFY_INTERFACE_VTABLE(stmt)
3901 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3903 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3907 GString *res = g_string_new ("");
3909 g_string_append_c (res, '(');
3910 for (i = 0; i < sig->param_count; ++i) {
3912 g_string_append_c (res, ',');
3913 mono_type_get_desc (res, sig->params [i], include_namespace);
3915 g_string_append (res, ")=>");
3916 if (sig->ret != NULL) {
3917 mono_type_get_desc (res, sig->ret, include_namespace);
3919 g_string_append (res, "NULL");
3922 g_string_free (res, FALSE);
3926 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3927 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3928 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3929 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3937 is_wcf_hack_disabled (void)
3939 static gboolean disabled;
3940 static gboolean inited = FALSE;
3942 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3949 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3951 MonoMethodSignature *cmsig, *imsig;
3952 if (strcmp (im->name, cm->name) == 0) {
3953 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3954 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3957 if (! slot_is_empty) {
3958 if (require_newslot) {
3959 if (! interface_is_explicitly_implemented_by_class) {
3960 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3963 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3964 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3968 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3971 cmsig = mono_method_signature (cm);
3972 imsig = mono_method_signature (im);
3973 if (!cmsig || !imsig) {
3974 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3978 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3979 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3980 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3981 TRACE_INTERFACE_VTABLE (printf ("]"));
3984 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3985 if (mono_security_core_clr_enabled ())
3986 mono_security_core_clr_check_override (class, cm, im);
3988 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3989 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3990 char *body_name = mono_method_full_name (cm, TRUE);
3991 char *decl_name = mono_method_full_name (im, TRUE);
3992 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));
4000 MonoClass *ic = im->klass;
4001 const char *ic_name_space = ic->name_space;
4002 const char *ic_name = ic->name;
4005 if (! require_newslot) {
4006 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4009 if (cm->klass->rank == 0) {
4010 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4013 cmsig = mono_method_signature (cm);
4014 imsig = mono_method_signature (im);
4015 if (!cmsig || !imsig) {
4016 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4020 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4021 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4022 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4023 TRACE_INTERFACE_VTABLE (printf ("]"));
4026 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4027 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4030 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4031 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4034 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))) {
4035 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4039 subname = strstr (cm->name, ic_name_space);
4040 if (subname != cm->name) {
4041 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4044 subname += strlen (ic_name_space);
4045 if (subname [0] != '.') {
4046 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4050 if (strstr (subname, ic_name) != subname) {
4051 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4054 subname += strlen (ic_name);
4055 if (subname [0] != '.') {
4056 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4060 if (strcmp (subname, im->name) != 0) {
4061 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4065 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4066 if (mono_security_core_clr_enabled ())
4067 mono_security_core_clr_check_override (class, cm, im);
4069 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4070 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4071 char *body_name = mono_method_full_name (cm, TRUE);
4072 char *decl_name = mono_method_full_name (im, TRUE);
4073 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));
4083 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4085 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4086 MonoMethod *method = key;
4087 MonoMethod *override = value;
4088 MonoClass *method_class = mono_method_get_class (method);
4089 MonoClass *override_class = mono_method_get_class (override);
4091 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4092 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4093 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4096 print_overrides (GHashTable *override_map, const char *message) {
4098 printf ("Override map \"%s\" START:\n", message);
4099 g_hash_table_foreach (override_map, foreach_override, NULL);
4100 printf ("Override map \"%s\" END.\n", message);
4102 printf ("Override map \"%s\" EMPTY.\n", message);
4106 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4107 char *full_name = mono_type_full_name (&class->byval_arg);
4111 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4113 if (print_interfaces) {
4114 print_implemented_interfaces (class);
4115 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4118 if (class->parent) {
4119 parent_size = class->parent->vtable_size;
4123 for (i = 0; i < size; ++i) {
4124 MonoMethod *cm = vtable [i];
4125 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4126 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4128 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4136 #if VERIFY_INTERFACE_VTABLE_CODE
4138 mono_method_try_get_vtable_index (MonoMethod *method)
4140 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4141 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4142 if (imethod->declaring->is_generic)
4143 return imethod->declaring->slot;
4145 return method->slot;
4149 mono_class_verify_vtable (MonoClass *class)
4152 char *full_name = mono_type_full_name (&class->byval_arg);
4154 printf ("*** Verifying VTable of class '%s' \n", full_name);
4158 if (!class->methods)
4161 for (i = 0; i < class->method.count; ++i) {
4162 MonoMethod *cm = class->methods [i];
4165 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4169 full_name = mono_method_full_name (cm, TRUE);
4171 slot = mono_method_try_get_vtable_index (cm);
4173 if (slot >= class->vtable_size) {
4174 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4178 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4179 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4180 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4181 g_free (other_name);
4184 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4191 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4193 char *method_signature;
4196 for (index = 0; index < onum; ++index) {
4197 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4198 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4200 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4201 type_name = mono_type_full_name (&class->byval_arg);
4202 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4203 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4204 g_free (method_signature);
4206 mono_class_setup_methods (class);
4207 if (class->exception_type) {
4208 char *name = mono_type_get_full_name (class);
4209 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4213 for (index = 0; index < class->method.count; ++index) {
4214 MonoMethod *cm = class->methods [index];
4215 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4217 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4218 g_free (method_signature);
4223 mono_method_get_method_definition (MonoMethod *method)
4225 while (method->is_inflated)
4226 method = ((MonoMethodInflated*)method)->declaring;
4231 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4235 for (i = 0; i < onum; ++i) {
4236 MonoMethod *decl = overrides [i * 2];
4237 MonoMethod *body = overrides [i * 2 + 1];
4239 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4240 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4244 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4245 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4246 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4248 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4252 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4253 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4254 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4256 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4260 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4261 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4265 body = mono_method_get_method_definition (body);
4266 decl = mono_method_get_method_definition (decl);
4268 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4269 char *body_name = mono_method_full_name (body, TRUE);
4270 char *decl_name = mono_method_full_name (decl, TRUE);
4271 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));
4281 mono_class_need_stelemref_method (MonoClass *class)
4283 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4287 * LOCKING: this is supposed to be called with the loader lock held.
4290 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4294 MonoMethod **vtable;
4295 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4296 GPtrArray *ifaces = NULL;
4297 GHashTable *override_map = NULL;
4299 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4300 int first_non_interface_slot;
4302 GSList *virt_methods = NULL, *l;
4303 int stelemref_slot = 0;
4308 if (overrides && !verify_class_overrides (class, overrides, onum))
4311 ifaces = mono_class_get_implemented_interfaces (class, &error);
4312 if (!mono_error_ok (&error)) {
4313 char *name = mono_type_get_full_name (class);
4314 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)));
4316 mono_error_cleanup (&error);
4318 } else if (ifaces) {
4319 for (i = 0; i < ifaces->len; i++) {
4320 MonoClass *ic = g_ptr_array_index (ifaces, i);
4321 max_vtsize += ic->method.count;
4323 g_ptr_array_free (ifaces, TRUE);
4327 if (class->parent) {
4328 mono_class_init (class->parent);
4329 mono_class_setup_vtable_full (class->parent, in_setup);
4331 if (class->parent->exception_type) {
4332 char *name = mono_type_get_full_name (class->parent);
4333 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4338 max_vtsize += class->parent->vtable_size;
4339 cur_slot = class->parent->vtable_size;
4342 max_vtsize += class->method.count;
4344 /*Array have a slot for stelemref*/
4345 if (mono_class_need_stelemref_method (class)) {
4346 stelemref_slot = cur_slot;
4351 vtable = alloca (sizeof (gpointer) * max_vtsize);
4352 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4354 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4356 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4357 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4360 max_iid = class->max_interface_id;
4361 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4363 /* Optimized version for generic instances */
4364 if (class->generic_class) {
4366 MonoClass *gklass = class->generic_class->container_class;
4369 mono_class_setup_vtable_full (gklass, in_setup);
4370 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4371 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4375 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4376 class->vtable_size = gklass->vtable_size;
4377 for (i = 0; i < gklass->vtable_size; ++i)
4378 if (gklass->vtable [i]) {
4379 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4380 if (!mono_error_ok (&error)) {
4381 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4382 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4384 mono_error_cleanup (&error);
4388 tmp [i]->slot = gklass->vtable [i]->slot;
4390 mono_memory_barrier ();
4391 class->vtable = tmp;
4393 /* Have to set method->slot for abstract virtual methods */
4394 if (class->methods && gklass->methods) {
4395 for (i = 0; i < class->method.count; ++i)
4396 if (class->methods [i]->slot == -1)
4397 class->methods [i]->slot = gklass->methods [i]->slot;
4403 if (class->parent && class->parent->vtable_size) {
4404 MonoClass *parent = class->parent;
4407 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4409 // Also inherit parent interface vtables, just as a starting point.
4410 // This is needed otherwise bug-77127.exe fails when the property methods
4411 // have different names in the iterface and the class, because for child
4412 // classes the ".override" information is not used anymore.
4413 for (i = 0; i < parent->interface_offsets_count; i++) {
4414 MonoClass *parent_interface = parent->interfaces_packed [i];
4415 int interface_offset = mono_class_interface_offset (class, parent_interface);
4416 /*FIXME this is now dead code as this condition will never hold true.
4417 Since interface offsets are inherited then the offset of an interface implemented
4418 by a parent will never be the out of it's vtable boundary.
4420 if (interface_offset >= parent->vtable_size) {
4421 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4424 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4425 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4426 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4427 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4428 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4429 parent_interface_offset + j, parent_interface_offset, j,
4430 interface_offset + j, interface_offset, j));
4437 /*Array have a slot for stelemref*/
4438 if (mono_class_need_stelemref_method (class)) {
4439 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4441 method->slot = stelemref_slot;
4443 g_assert (method->slot == stelemref_slot);
4445 vtable [stelemref_slot] = method;
4448 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4449 /* override interface methods */
4450 for (i = 0; i < onum; i++) {
4451 MonoMethod *decl = overrides [i*2];
4452 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4454 dslot = mono_method_get_vtable_slot (decl);
4456 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4460 dslot += mono_class_interface_offset (class, decl->klass);
4461 vtable [dslot] = overrides [i*2 + 1];
4462 vtable [dslot]->slot = dslot;
4464 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4466 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4468 if (mono_security_core_clr_enabled ())
4469 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4472 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4473 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4476 * Create a list of virtual methods to avoid calling
4477 * mono_class_get_virtual_methods () which is slow because of the metadata
4481 gpointer iter = NULL;
4484 virt_methods = NULL;
4485 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4486 virt_methods = g_slist_prepend (virt_methods, cm);
4488 if (class->exception_type)
4492 // Loop on all implemented interfaces...
4493 for (i = 0; i < class->interface_offsets_count; i++) {
4494 MonoClass *parent = class->parent;
4496 gboolean interface_is_explicitly_implemented_by_class;
4499 ic = class->interfaces_packed [i];
4500 ic_offset = mono_class_interface_offset (class, ic);
4502 mono_class_setup_methods (ic);
4503 if (ic->exception_type)
4506 // Check if this interface is explicitly implemented (instead of just inherited)
4507 if (parent != NULL) {
4508 int implemented_interfaces_index;
4509 interface_is_explicitly_implemented_by_class = FALSE;
4510 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4511 if (ic == class->interfaces [implemented_interfaces_index]) {
4512 interface_is_explicitly_implemented_by_class = TRUE;
4517 interface_is_explicitly_implemented_by_class = TRUE;
4520 // Loop on all interface methods...
4521 for (im_index = 0; im_index < ic->method.count; im_index++) {
4522 MonoMethod *im = ic->methods [im_index];
4523 int im_slot = ic_offset + im->slot;
4524 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4526 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4529 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4531 // If there is an explicit implementation, just use it right away,
4532 // otherwise look for a matching method
4533 if (override_im == NULL) {
4537 // First look for a suitable method among the class methods
4538 for (l = virt_methods; l; l = l->next) {
4540 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)));
4541 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4542 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4543 vtable [im_slot] = cm;
4544 /* Why do we need this? */
4549 TRACE_INTERFACE_VTABLE (printf ("\n"));
4550 if (class->exception_type) /*Might be set by check_interface_method_override*/
4554 // If the slot is still empty, look in all the inherited virtual methods...
4555 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4556 MonoClass *parent = class->parent;
4557 // Reverse order, so that last added methods are preferred
4558 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4559 MonoMethod *cm = parent->vtable [cm_index];
4561 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));
4562 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
4563 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4564 vtable [im_slot] = cm;
4565 /* Why do we need this? */
4571 if (class->exception_type) /*Might be set by check_interface_method_override*/
4573 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4577 g_assert (vtable [im_slot] == override_im);
4582 // If the class is not abstract, check that all its interface slots are full.
4583 // The check is done here and not directly at the end of the loop above because
4584 // it can happen (for injected generic array interfaces) that the same slot is
4585 // processed multiple times (those interfaces have overlapping slots), and it
4586 // will not always be the first pass the one that fills the slot.
4587 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4588 for (i = 0; i < class->interface_offsets_count; i++) {
4592 ic = class->interfaces_packed [i];
4593 ic_offset = mono_class_interface_offset (class, ic);
4595 for (im_index = 0; im_index < ic->method.count; im_index++) {
4596 MonoMethod *im = ic->methods [im_index];
4597 int im_slot = ic_offset + im->slot;
4599 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4602 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4603 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4604 if (vtable [im_slot] == NULL) {
4605 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4612 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4613 for (l = virt_methods; l; l = l->next) {
4616 * If the method is REUSE_SLOT, we must check in the
4617 * base class for a method to override.
4619 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4621 for (k = class->parent; k ; k = k->parent) {
4626 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4627 MonoMethodSignature *cmsig, *m1sig;
4629 cmsig = mono_method_signature (cm);
4630 m1sig = mono_method_signature (m1);
4632 if (!cmsig || !m1sig) {
4633 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4637 if (!strcmp(cm->name, m1->name) &&
4638 mono_metadata_signature_equal (cmsig, m1sig)) {
4640 if (mono_security_core_clr_enabled ())
4641 mono_security_core_clr_check_override (class, cm, m1);
4643 slot = mono_method_get_vtable_slot (m1);
4647 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4648 char *body_name = mono_method_full_name (cm, TRUE);
4649 char *decl_name = mono_method_full_name (m1, TRUE);
4650 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));
4656 g_assert (cm->slot < max_vtsize);
4658 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4659 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4660 mono_method_full_name (m1, 1), m1,
4661 mono_method_full_name (cm, 1), cm));
4662 g_hash_table_insert (override_map, m1, cm);
4666 if (k->exception_type)
4676 /*Non final newslot methods must be given a non-interface vtable slot*/
4677 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4681 cm->slot = cur_slot++;
4683 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4684 vtable [cm->slot] = cm;
4687 /* override non interface methods */
4688 for (i = 0; i < onum; i++) {
4689 MonoMethod *decl = overrides [i*2];
4690 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4691 g_assert (decl->slot != -1);
4692 vtable [decl->slot] = overrides [i*2 + 1];
4693 overrides [i * 2 + 1]->slot = decl->slot;
4695 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4696 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4697 mono_method_full_name (decl, 1), decl,
4698 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4699 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4701 if (mono_security_core_clr_enabled ())
4702 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4707 * If a method occupies more than one place in the vtable, and it is
4708 * overriden, then change the other occurances too.
4713 for (i = 0; i < max_vtsize; ++i)
4715 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4717 cm = g_hash_table_lookup (override_map, vtable [i]);
4722 g_hash_table_destroy (override_map);
4723 override_map = NULL;
4726 g_slist_free (virt_methods);
4727 virt_methods = NULL;
4729 /* Ensure that all vtable slots are filled with concrete instance methods */
4730 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4731 for (i = 0; i < cur_slot; ++i) {
4732 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4733 char *type_name = mono_type_get_full_name (class);
4734 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4735 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));
4737 g_free (method_name);
4743 if (class->generic_class) {
4744 MonoClass *gklass = class->generic_class->container_class;
4746 mono_class_init (gklass);
4748 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4750 /* Check that the vtable_size value computed in mono_class_init () is correct */
4751 if (class->vtable_size)
4752 g_assert (cur_slot == class->vtable_size);
4753 class->vtable_size = cur_slot;
4756 /* Try to share the vtable with our parent. */
4757 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4758 mono_memory_barrier ();
4759 class->vtable = class->parent->vtable;
4761 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4762 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4763 mono_memory_barrier ();
4764 class->vtable = tmp;
4767 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4768 if (mono_print_vtable) {
4771 print_implemented_interfaces (class);
4773 for (i = 0; i <= max_iid; i++)
4774 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4777 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4778 class->vtable_size, icount);
4780 for (i = 0; i < cur_slot; ++i) {
4785 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4786 mono_method_full_name (cm, TRUE));
4792 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4793 class->name, max_iid);
4795 for (i = 0; i < class->interface_count; i++) {
4796 ic = class->interfaces [i];
4797 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4798 mono_class_interface_offset (class, ic),
4799 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4802 for (k = class->parent; k ; k = k->parent) {
4803 for (i = 0; i < k->interface_count; i++) {
4804 ic = k->interfaces [i];
4805 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4806 mono_class_interface_offset (class, ic),
4807 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4813 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4818 char *name = mono_type_get_full_name (class);
4819 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4822 g_hash_table_destroy (override_map);
4824 g_slist_free (virt_methods);
4829 * mono_method_get_vtable_slot:
4831 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4832 * LOCKING: Acquires the loader lock.
4834 * FIXME Use proper MonoError machinery here.
4837 mono_method_get_vtable_slot (MonoMethod *method)
4839 if (method->slot == -1) {
4840 mono_class_setup_vtable (method->klass);
4841 if (method->klass->exception_type)
4843 if (method->slot == -1) {
4847 if (!method->klass->generic_class) {
4848 g_assert (method->is_inflated);
4849 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4852 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4853 g_assert (method->klass->generic_class);
4854 gklass = method->klass->generic_class->container_class;
4855 mono_class_setup_methods (method->klass);
4856 g_assert (method->klass->methods);
4857 for (i = 0; i < method->klass->method.count; ++i) {
4858 if (method->klass->methods [i] == method)
4861 g_assert (i < method->klass->method.count);
4862 g_assert (gklass->methods);
4863 method->slot = gklass->methods [i]->slot;
4865 g_assert (method->slot != -1);
4867 return method->slot;
4871 * mono_method_get_vtable_index:
4874 * Returns the index into the runtime vtable to access the method or,
4875 * in the case of a virtual generic method, the virtual generic method
4876 * thunk. Returns -1 on failure.
4878 * FIXME Use proper MonoError machinery here.
4881 mono_method_get_vtable_index (MonoMethod *method)
4883 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4884 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4885 if (imethod->declaring->is_generic)
4886 return mono_method_get_vtable_slot (imethod->declaring);
4888 return mono_method_get_vtable_slot (method);
4891 static MonoMethod *default_ghc = NULL;
4892 static MonoMethod *default_finalize = NULL;
4893 static int finalize_slot = -1;
4894 static int ghc_slot = -1;
4897 initialize_object_slots (MonoClass *class)
4902 if (class == mono_defaults.object_class) {
4903 mono_class_setup_vtable (class);
4904 for (i = 0; i < class->vtable_size; ++i) {
4905 MonoMethod *cm = class->vtable [i];
4907 if (!strcmp (cm->name, "GetHashCode"))
4909 else if (!strcmp (cm->name, "Finalize"))
4913 g_assert (ghc_slot > 0);
4914 default_ghc = class->vtable [ghc_slot];
4916 g_assert (finalize_slot > 0);
4917 default_finalize = class->vtable [finalize_slot];
4922 MonoMethod *array_method;
4924 } GenericArrayMethodInfo;
4926 static int generic_array_method_num = 0;
4927 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4930 generic_array_methods (MonoClass *class)
4932 int i, count_generic = 0;
4933 GList *list = NULL, *tmp;
4934 if (generic_array_method_num)
4935 return generic_array_method_num;
4936 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4937 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4938 for (i = 0; i < class->parent->method.count; i++) {
4939 MonoMethod *m = class->parent->methods [i];
4940 if (!strncmp (m->name, "InternalArray__", 15)) {
4942 list = g_list_prepend (list, m);
4945 list = g_list_reverse (list);
4946 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4948 for (tmp = list; tmp; tmp = tmp->next) {
4949 const char *mname, *iname;
4951 MonoMethod *m = tmp->data;
4952 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4953 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4955 generic_array_method_info [i].array_method = m;
4956 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4957 iname = "System.Collections.Generic.ICollection`1.";
4958 mname = m->name + 27;
4959 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4960 iname = "System.Collections.Generic.IEnumerable`1.";
4961 mname = m->name + 27;
4962 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4963 iname = "System.Collections.Generic.IReadOnlyList`1.";
4964 mname = m->name + strlen (ireadonlylist_prefix);
4965 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4966 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4967 mname = m->name + strlen (ireadonlycollection_prefix);
4968 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4969 iname = "System.Collections.Generic.IList`1.";
4970 mname = m->name + 15;
4972 g_assert_not_reached ();
4975 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4976 strcpy (name, iname);
4977 strcpy (name + strlen (iname), mname);
4978 generic_array_method_info [i].name = name;
4981 /*g_print ("array generic methods: %d\n", count_generic);*/
4983 generic_array_method_num = count_generic;
4985 return generic_array_method_num;
4989 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4991 MonoGenericContext tmp_context;
4994 tmp_context.class_inst = NULL;
4995 tmp_context.method_inst = iface->generic_class->context.class_inst;
4996 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4998 for (i = 0; i < generic_array_method_num; i++) {
5000 MonoMethod *m = generic_array_method_info [i].array_method;
5001 MonoMethod *inflated;
5003 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5004 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5005 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
5010 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5012 int null_length = strlen ("(null)");
5013 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5014 char *s = mono_image_alloc (image, len);
5017 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5018 g_assert (result == len - 1);
5024 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
5026 gpointer exception_data = NULL;
5028 switch (error->exception_type) {
5029 case MONO_EXCEPTION_TYPE_LOAD:
5030 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5033 case MONO_EXCEPTION_MISSING_METHOD:
5034 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5037 case MONO_EXCEPTION_MISSING_FIELD: {
5038 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5039 const char *class_name;
5042 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5044 class_name = error->klass->name;
5046 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5049 g_free ((void*)class_name);
5053 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5056 if (error->ref_only)
5057 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.";
5059 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5061 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5065 case MONO_EXCEPTION_BAD_IMAGE:
5066 exception_data = error->msg;
5070 g_assert_not_reached ();
5073 mono_class_set_failure (class, error->exception_type, exception_data);
5078 * @class: the class to initialize
5080 * Compute the instance_size, class_size and other infos that cannot be
5081 * computed at mono_class_get() time. Also compute vtable_size if possible.
5082 * Returns TRUE on success or FALSE if there was a problem in loading
5083 * the type (incorrect assemblies, missing assemblies, methods, etc).
5085 * LOCKING: Acquires the loader lock.
5088 mono_class_init (MonoClass *class)
5091 MonoCachedClassInfo cached_info;
5092 gboolean has_cached_info;
5096 /* Double-checking locking pattern */
5097 if (class->inited || class->exception_type)
5098 return class->exception_type == MONO_EXCEPTION_NONE;
5100 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5102 /* We do everything inside the lock to prevent races */
5103 mono_loader_lock ();
5105 if (class->inited || class->exception_type) {
5106 mono_loader_unlock ();
5107 /* Somebody might have gotten in before us */
5108 return class->exception_type == MONO_EXCEPTION_NONE;
5111 if (class->init_pending) {
5112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5116 class->init_pending = 1;
5118 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5119 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5124 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5125 MonoClass *element_class = class->element_class;
5126 if (!element_class->inited)
5127 mono_class_init (element_class);
5128 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5129 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5134 mono_stats.initialized_class_count++;
5136 if (class->generic_class && !class->generic_class->is_dynamic) {
5137 MonoClass *gklass = class->generic_class->container_class;
5139 mono_stats.generic_class_count++;
5141 class->method = gklass->method;
5142 class->field = gklass->field;
5144 mono_class_init (gklass);
5145 // FIXME: Why is this needed ?
5146 if (!gklass->exception_type)
5147 mono_class_setup_methods (gklass);
5148 if (gklass->exception_type) {
5149 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5153 if (MONO_CLASS_IS_INTERFACE (class))
5154 class->interface_id = mono_get_unique_iid (class);
5157 if (class->parent && !class->parent->inited)
5158 mono_class_init (class->parent);
5160 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5162 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5163 class->nested_classes_inited = TRUE;
5166 * Computes the size used by the fields, and their locations
5168 if (has_cached_info) {
5169 class->instance_size = cached_info.instance_size;
5170 class->sizes.class_size = cached_info.class_size;
5171 class->packing_size = cached_info.packing_size;
5172 class->min_align = cached_info.min_align;
5173 class->blittable = cached_info.blittable;
5174 class->has_references = cached_info.has_references;
5175 class->has_static_refs = cached_info.has_static_refs;
5176 class->no_special_static_fields = cached_info.no_special_static_fields;
5179 if (!class->size_inited){
5180 mono_class_setup_fields (class);
5181 if (class->exception_type || mono_loader_get_last_error ())
5185 /* Initialize arrays */
5187 class->method.count = 3 + (class->rank > 1? 2: 1);
5189 if (class->interface_count) {
5190 int count_generic = generic_array_methods (class);
5191 class->method.count += class->interface_count * count_generic;
5195 mono_class_setup_supertypes (class);
5198 initialize_object_slots (class);
5201 * Initialize the rest of the data without creating a generic vtable if possible.
5202 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5203 * also avoid computing a generic vtable.
5205 if (has_cached_info) {
5207 class->vtable_size = cached_info.vtable_size;
5208 class->has_finalize = cached_info.has_finalize;
5209 class->has_finalize_inited = TRUE;
5210 class->ghcimpl = cached_info.ghcimpl;
5211 class->has_cctor = cached_info.has_cctor;
5212 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5213 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5214 * The first slot if for array with.
5216 static int szarray_vtable_size[2] = { 0 };
5218 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5221 if (!szarray_vtable_size [slot]) {
5222 mono_class_setup_vtable (class);
5223 szarray_vtable_size [slot] = class->vtable_size;
5225 class->vtable_size = szarray_vtable_size[slot];
5227 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5228 MonoClass *gklass = class->generic_class->container_class;
5230 /* Generic instance case */
5231 class->ghcimpl = gklass->ghcimpl;
5232 class->has_cctor = gklass->has_cctor;
5234 mono_class_setup_vtable (gklass);
5235 if (gklass->exception_type) {
5236 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5240 class->vtable_size = gklass->vtable_size;
5244 /* ghcimpl is not currently used
5246 if (class->parent) {
5247 MonoMethod *cmethod = class->vtable [ghc_slot];
5248 if (cmethod->is_inflated)
5249 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5250 if (cmethod == default_ghc) {
5256 /* C# doesn't allow interfaces to have cctors */
5257 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5258 MonoMethod *cmethod = NULL;
5260 if (class->type_token) {
5261 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5262 /* The find_method function ignores the 'flags' argument */
5263 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5264 class->has_cctor = 1;
5266 mono_class_setup_methods (class);
5267 if (class->exception_type)
5270 for (i = 0; i < class->method.count; ++i) {
5271 MonoMethod *method = class->methods [i];
5272 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5273 (strcmp (".cctor", method->name) == 0)) {
5274 class->has_cctor = 1;
5282 if (class->parent) {
5283 int first_iface_slot;
5284 /* This will compute class->parent->vtable_size for some classes */
5285 mono_class_init (class->parent);
5286 if (class->parent->exception_type) {
5287 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5290 if (mono_loader_get_last_error ())
5292 if (!class->parent->vtable_size) {
5293 /* FIXME: Get rid of this somehow */
5294 mono_class_setup_vtable (class->parent);
5295 if (class->parent->exception_type) {
5296 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5299 if (mono_loader_get_last_error ())
5302 first_iface_slot = class->parent->vtable_size;
5303 if (mono_class_need_stelemref_method (class))
5305 setup_interface_offsets (class, first_iface_slot, TRUE);
5307 setup_interface_offsets (class, 0, TRUE);
5310 if (mono_security_core_clr_enabled ())
5311 mono_security_core_clr_check_inheritance (class);
5313 if (mono_loader_get_last_error ()) {
5314 if (class->exception_type == MONO_EXCEPTION_NONE) {
5315 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5317 mono_loader_clear_error ();
5320 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5321 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5326 /* Because of the double-checking locking pattern */
5327 mono_memory_barrier ();
5329 class->init_pending = 0;
5331 mono_loader_unlock ();
5333 return class->exception_type == MONO_EXCEPTION_NONE;
5337 * mono_class_has_finalizer:
5339 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5343 mono_class_has_finalizer (MonoClass *klass)
5345 MonoClass *class = klass;
5346 gboolean has_finalize = FALSE;
5348 if (klass->has_finalize_inited)
5349 return klass->has_finalize;
5351 /* Interfaces and valuetypes are not supposed to have finalizers */
5352 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5353 MonoMethod *cmethod = NULL;
5355 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5356 } else if (class->generic_class) {
5357 MonoClass *gklass = class->generic_class->container_class;
5359 has_finalize = mono_class_has_finalizer (gklass);
5360 } else if (class->parent && class->parent->has_finalize) {
5361 has_finalize = TRUE;
5363 if (class->parent) {
5365 * Can't search in metadata for a method named Finalize, because that
5366 * ignores overrides.
5368 mono_class_setup_vtable (class);
5369 if (class->exception_type || mono_loader_get_last_error ())
5372 cmethod = class->vtable [finalize_slot];
5376 g_assert (class->vtable_size > finalize_slot);
5378 if (class->parent) {
5379 if (cmethod->is_inflated)
5380 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5381 if (cmethod != default_finalize)
5382 has_finalize = TRUE;
5388 mono_image_lock (klass->image);
5390 if (!klass->has_finalize_inited) {
5391 klass->has_finalize = has_finalize ? 1 : 0;
5393 mono_memory_barrier ();
5394 klass->has_finalize_inited = TRUE;
5397 mono_image_unlock (klass->image);
5399 return klass->has_finalize;
5403 mono_is_corlib_image (MonoImage *image)
5405 /* FIXME: allow the dynamic case for our compilers and with full trust */
5406 if (image_is_dynamic (image))
5407 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5409 return image == mono_defaults.corlib;
5413 * LOCKING: this assumes the loader lock is held
5416 mono_class_setup_mono_type (MonoClass *class)
5418 const char *name = class->name;
5419 const char *nspace = class->name_space;
5420 gboolean is_corlib = mono_is_corlib_image (class->image);
5422 class->this_arg.byref = 1;
5423 class->this_arg.data.klass = class;
5424 class->this_arg.type = MONO_TYPE_CLASS;
5425 class->byval_arg.data.klass = class;
5426 class->byval_arg.type = MONO_TYPE_CLASS;
5428 if (is_corlib && !strcmp (nspace, "System")) {
5429 if (!strcmp (name, "ValueType")) {
5431 * do not set the valuetype bit for System.ValueType.
5432 * class->valuetype = 1;
5434 class->blittable = TRUE;
5435 } else if (!strcmp (name, "Enum")) {
5437 * do not set the valuetype bit for System.Enum.
5438 * class->valuetype = 1;
5440 class->valuetype = 0;
5441 class->enumtype = 0;
5442 } else if (!strcmp (name, "Object")) {
5443 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5444 } else if (!strcmp (name, "String")) {
5445 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5446 } else if (!strcmp (name, "TypedReference")) {
5447 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5451 if (class->valuetype) {
5452 int t = MONO_TYPE_VALUETYPE;
5454 if (is_corlib && !strcmp (nspace, "System")) {
5457 if (!strcmp (name, "Boolean")) {
5458 t = MONO_TYPE_BOOLEAN;
5459 } else if (!strcmp(name, "Byte")) {
5461 class->blittable = TRUE;
5465 if (!strcmp (name, "Char")) {
5470 if (!strcmp (name, "Double")) {
5472 class->blittable = TRUE;
5476 if (!strcmp (name, "Int32")) {
5478 class->blittable = TRUE;
5479 } else if (!strcmp(name, "Int16")) {
5481 class->blittable = TRUE;
5482 } else if (!strcmp(name, "Int64")) {
5484 class->blittable = TRUE;
5485 } else if (!strcmp(name, "IntPtr")) {
5487 class->blittable = TRUE;
5491 if (!strcmp (name, "Single")) {
5493 class->blittable = TRUE;
5494 } else if (!strcmp(name, "SByte")) {
5496 class->blittable = TRUE;
5500 if (!strcmp (name, "UInt32")) {
5502 class->blittable = TRUE;
5503 } else if (!strcmp(name, "UInt16")) {
5505 class->blittable = TRUE;
5506 } else if (!strcmp(name, "UInt64")) {
5508 class->blittable = TRUE;
5509 } else if (!strcmp(name, "UIntPtr")) {
5511 class->blittable = TRUE;
5515 if (!strcmp (name, "TypedReference")) {
5516 t = MONO_TYPE_TYPEDBYREF;
5517 class->blittable = TRUE;
5521 if (!strcmp (name, "Void")) {
5529 class->this_arg.type = class->byval_arg.type = t;
5532 if (MONO_CLASS_IS_INTERFACE (class))
5533 class->interface_id = mono_get_unique_iid (class);
5539 * COM initialization is delayed until needed.
5540 * However when a [ComImport] attribute is present on a type it will trigger
5541 * the initialization. This is not a problem unless the BCL being executed
5542 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5545 init_com_from_comimport (MonoClass *class)
5547 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5548 if (mono_security_core_clr_enabled ()) {
5549 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5550 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5551 /* but it can not be made available for application (i.e. user code) since all COM calls
5552 * are considered native calls. In this case we fail with a TypeLoadException (just like
5553 * Silverlight 2 does */
5554 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5559 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5561 #endif /*DISABLE_COM*/
5564 * LOCKING: this assumes the loader lock is held
5567 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5569 gboolean system_namespace;
5570 gboolean is_corlib = mono_is_corlib_image (class->image);
5572 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5574 /* if root of the hierarchy */
5575 if (system_namespace && !strcmp (class->name, "Object")) {
5576 class->parent = NULL;
5577 class->instance_size = sizeof (MonoObject);
5580 if (!strcmp (class->name, "<Module>")) {
5581 class->parent = NULL;
5582 class->instance_size = 0;
5586 if (!MONO_CLASS_IS_INTERFACE (class)) {
5587 /* Imported COM Objects always derive from __ComObject. */
5589 if (MONO_CLASS_IS_IMPORT (class)) {
5590 init_com_from_comimport (class);
5591 if (parent == mono_defaults.object_class)
5592 parent = mono_class_get_com_object_class ();
5596 /* set the parent to something useful and safe, but mark the type as broken */
5597 parent = mono_defaults.object_class;
5598 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5601 class->parent = parent;
5603 if (parent->generic_class && !parent->name) {
5605 * If the parent is a generic instance, we may get
5606 * called before it is fully initialized, especially
5607 * before it has its name.
5612 #ifndef DISABLE_REMOTING
5613 class->marshalbyref = parent->marshalbyref;
5614 class->contextbound = parent->contextbound;
5617 class->delegate = parent->delegate;
5619 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5620 mono_class_set_is_com_object (class);
5622 if (system_namespace) {
5623 #ifndef DISABLE_REMOTING
5624 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5625 class->marshalbyref = 1;
5627 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5628 class->contextbound = 1;
5630 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5631 class->delegate = 1;
5634 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5635 (strcmp (class->parent->name_space, "System") == 0)))
5636 class->valuetype = 1;
5637 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5638 class->valuetype = class->enumtype = 1;
5640 /*class->enumtype = class->parent->enumtype; */
5642 /* initialize com types if COM interfaces are present */
5644 if (MONO_CLASS_IS_IMPORT (class))
5645 init_com_from_comimport (class);
5647 class->parent = NULL;
5653 * mono_class_setup_supertypes:
5656 * Build the data structure needed to make fast type checks work.
5657 * This currently sets two fields in @class:
5658 * - idepth: distance between @class and System.Object in the type
5660 * - supertypes: array of classes: each element has a class in the hierarchy
5661 * starting from @class up to System.Object
5663 * LOCKING: This function is atomic, in case of contention we waste memory.
5666 mono_class_setup_supertypes (MonoClass *class)
5669 MonoClass **supertypes;
5671 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5675 if (class->parent && !class->parent->supertypes)
5676 mono_class_setup_supertypes (class->parent);
5678 class->idepth = class->parent->idepth + 1;
5682 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5683 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5685 if (class->parent) {
5686 supertypes [class->idepth - 1] = class;
5687 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5689 supertypes [0] = class;
5692 mono_atomic_store_release (&class->supertypes, supertypes);
5696 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5698 MonoClass *gtd = (MonoClass*)user_data;
5699 /* Only try to fix generic instances of @gtd */
5700 if (gclass->generic_class->container_class != gtd)
5703 /* Check if the generic instance has no parent. */
5704 if (gtd->parent && !gclass->parent)
5705 mono_generic_class_setup_parent (gclass, gtd);
5711 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5713 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5714 mono_error_set_type_load_class (error, class, msg);
5718 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5720 MonoLoaderError *lerror = mono_loader_get_last_error ();
5723 set_failure_from_loader_error (class, lerror);
5724 mono_error_set_from_loader_error (error);
5728 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5729 mono_error_set_type_load_class (error, class, msg);
5734 * mono_class_create_from_typedef:
5735 * @image: image where the token is valid
5736 * @type_token: typedef token
5737 * @error: used to return any error found while creating the type
5739 * Create the MonoClass* representing the specified type token.
5740 * @type_token must be a TypeDef token.
5742 * FIXME: don't return NULL on failure, just the the caller figure it out.
5745 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5747 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5748 MonoClass *class, *parent = NULL;
5749 guint32 cols [MONO_TYPEDEF_SIZE];
5750 guint32 cols_next [MONO_TYPEDEF_SIZE];
5751 guint tidx = mono_metadata_token_index (type_token);
5752 MonoGenericContext *context = NULL;
5753 const char *name, *nspace;
5755 MonoClass **interfaces;
5756 guint32 field_last, method_last;
5757 guint32 nesting_tokeen;
5759 mono_error_init (error);
5761 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5762 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5763 mono_loader_assert_no_error ();
5767 mono_loader_lock ();
5769 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5770 mono_loader_unlock ();
5771 mono_loader_assert_no_error ();
5775 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5777 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5778 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5780 class = mono_image_alloc0 (image, sizeof (MonoClass));
5783 class->name_space = nspace;
5785 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5787 class->image = image;
5788 class->type_token = type_token;
5789 class->flags = cols [MONO_TYPEDEF_FLAGS];
5791 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5793 classes_size += sizeof (MonoClass);
5796 * Check whether we're a generic type definition.
5798 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5799 if (class->generic_container) {
5800 class->is_generic = 1;
5801 class->generic_container->owner.klass = class;
5802 context = &class->generic_container->context;
5805 if (class->generic_container)
5806 enable_gclass_recording ();
5808 if (cols [MONO_TYPEDEF_EXTENDS]) {
5810 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5812 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5813 /*WARNING: this must satisfy mono_metadata_type_hash*/
5814 class->this_arg.byref = 1;
5815 class->this_arg.data.klass = class;
5816 class->this_arg.type = MONO_TYPE_CLASS;
5817 class->byval_arg.data.klass = class;
5818 class->byval_arg.type = MONO_TYPE_CLASS;
5820 parent = mono_class_get_checked (image, parent_token, error);
5821 if (parent && context) /* Always inflate */
5822 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5824 if (parent == NULL) {
5825 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5826 goto parent_failure;
5829 for (tmp = parent; tmp; tmp = tmp->parent) {
5831 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5832 goto parent_failure;
5834 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5835 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5836 goto parent_failure;
5841 mono_class_setup_parent (class, parent);
5843 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5844 mono_class_setup_mono_type (class);
5846 if (class->generic_container)
5847 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5850 * This might access class->byval_arg for recursion generated by generic constraints,
5851 * so it has to come after setup_mono_type ().
5853 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5854 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5855 if (!mono_error_ok (error)) {
5856 /*FIXME implement a mono_class_set_failure_from_mono_error */
5857 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5858 mono_loader_unlock ();
5859 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5860 mono_loader_assert_no_error ();
5865 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5869 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5873 class->cast_class = class->element_class = class;
5875 if (!class->enumtype) {
5876 if (!mono_metadata_interfaces_from_typedef_full (
5877 image, type_token, &interfaces, &icount, FALSE, context, error)){
5879 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5880 mono_loader_unlock ();
5881 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5885 class->interfaces = interfaces;
5886 class->interface_count = icount;
5887 class->interfaces_inited = 1;
5890 /*g_print ("Load class %s\n", name);*/
5893 * Compute the field and method lists
5895 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5896 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5898 if (tt->rows > tidx){
5899 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5900 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5901 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5903 field_last = image->tables [MONO_TABLE_FIELD].rows;
5904 method_last = image->tables [MONO_TABLE_METHOD].rows;
5907 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5908 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5909 class->field.count = field_last - class->field.first;
5911 class->field.count = 0;
5913 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5914 class->method.count = method_last - class->method.first;
5916 class->method.count = 0;
5918 /* reserve space to store vector pointer in arrays */
5919 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5920 class->instance_size += 2 * sizeof (gpointer);
5921 g_assert (class->field.count == 0);
5924 if (class->enumtype) {
5925 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5926 if (!enum_basetype) {
5927 /*set it to a default value as the whole runtime can't handle this to be null*/
5928 class->cast_class = class->element_class = mono_defaults.int32_class;
5929 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5930 mono_loader_unlock ();
5931 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5932 mono_loader_assert_no_error ();
5935 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5939 * If we're a generic type definition, load the constraints.
5940 * We must do this after the class has been constructed to make certain recursive scenarios
5943 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5944 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)));
5945 mono_loader_unlock ();
5946 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5947 mono_loader_assert_no_error ();
5951 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5952 if (!strncmp (name, "Vector", 6))
5953 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");
5956 mono_loader_unlock ();
5958 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5959 mono_loader_assert_no_error ();
5964 mono_class_setup_mono_type (class);
5965 mono_loader_unlock ();
5966 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5967 mono_loader_assert_no_error ();
5971 /** is klass Nullable<T>? */
5973 mono_class_is_nullable (MonoClass *klass)
5975 return klass->generic_class != NULL &&
5976 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5980 /** if klass is T? return T */
5982 mono_class_get_nullable_param (MonoClass *klass)
5984 g_assert (mono_class_is_nullable (klass));
5985 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5989 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5993 MonoGenericClass *gclass = klass->generic_class;
5995 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5996 if (!mono_error_ok (&error)) {
5997 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5998 klass->parent = mono_defaults.object_class;
5999 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6000 mono_error_cleanup (&error);
6004 mono_class_setup_parent (klass, klass->parent);
6006 if (klass->enumtype) {
6007 klass->cast_class = gtd->cast_class;
6008 klass->element_class = gtd->element_class;
6014 * Create the `MonoClass' for an instantiation of a generic type.
6015 * We only do this if we actually need it.
6018 mono_generic_class_get_class (MonoGenericClass *gclass)
6020 MonoClass *klass, *gklass;
6022 if (gclass->cached_class)
6023 return gclass->cached_class;
6025 mono_loader_lock ();
6026 if (gclass->cached_class) {
6027 mono_loader_unlock ();
6028 return gclass->cached_class;
6031 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6033 gklass = gclass->container_class;
6035 if (record_gclass_instantiation > 0)
6036 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6038 if (gklass->nested_in) {
6039 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6040 klass->nested_in = gklass->nested_in;
6043 klass->name = gklass->name;
6044 klass->name_space = gklass->name_space;
6046 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6048 klass->image = gklass->image;
6049 klass->flags = gklass->flags;
6050 klass->type_token = gklass->type_token;
6051 klass->field.count = gklass->field.count;
6053 klass->is_inflated = 1;
6054 klass->generic_class = gclass;
6056 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6057 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6058 klass->this_arg.byref = TRUE;
6059 klass->enumtype = gklass->enumtype;
6060 klass->valuetype = gklass->valuetype;
6062 klass->cast_class = klass->element_class = klass;
6064 if (mono_class_is_nullable (klass))
6065 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6068 * We're not interested in the nested classes of a generic instance.
6069 * We use the generic type definition to look for nested classes.
6072 mono_generic_class_setup_parent (klass, gklass);
6074 if (gclass->is_dynamic) {
6076 * 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.
6077 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6078 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6080 if (!gklass->wastypebuilder)
6083 mono_class_setup_supertypes (klass);
6085 if (klass->enumtype) {
6087 * For enums, gklass->fields might not been set, but instance_size etc. is
6088 * already set in mono_reflection_create_internal_class (). For non-enums,
6089 * these will be computed normally in mono_class_layout_fields ().
6091 klass->instance_size = gklass->instance_size;
6092 klass->sizes.class_size = gklass->sizes.class_size;
6093 mono_memory_barrier ();
6094 klass->size_inited = 1;
6098 mono_memory_barrier ();
6099 gclass->cached_class = klass;
6101 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6103 inflated_classes ++;
6104 inflated_classes_size += sizeof (MonoClass);
6106 mono_loader_unlock ();
6112 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6114 MonoClass *klass, **ptr;
6116 MonoGenericContainer *container = mono_generic_param_owner (param);
6120 image = mono_defaults.corlib;
6122 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6123 classes_size += sizeof (MonoClass);
6126 klass->name = pinfo->name;
6128 int n = mono_generic_param_num (param);
6129 klass->name = mono_image_alloc0 (image, 16);
6130 sprintf ((char*)klass->name, "%d", n);
6135 MonoMethod *omethod = container->owner.method;
6136 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6138 MonoClass *oklass = container->owner.klass;
6139 klass->name_space = oklass ? oklass->name_space : "";
6142 klass->name_space = "";
6145 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6149 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6153 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6154 klass->parent = pinfo->constraints [0];
6156 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6157 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6159 klass->parent = mono_defaults.object_class;
6162 if (count - pos > 0) {
6163 klass->interface_count = count - pos;
6164 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6165 klass->interfaces_inited = TRUE;
6166 for (i = pos; i < count; i++)
6167 klass->interfaces [i - pos] = pinfo->constraints [i];
6170 klass->image = image;
6172 klass->inited = TRUE;
6173 klass->cast_class = klass->element_class = klass;
6174 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6176 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6177 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6178 klass->this_arg.byref = TRUE;
6180 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6181 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6183 /*Init these fields to sane values*/
6184 klass->min_align = 1;
6186 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6187 * constrained to, the JIT depends on this.
6189 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6190 mono_memory_barrier ();
6191 klass->size_inited = 1;
6192 klass->setup_fields_called = 1;
6194 mono_class_setup_supertypes (klass);
6196 if (count - pos > 0) {
6197 mono_class_setup_vtable (klass->parent);
6198 if (klass->parent->exception_type)
6199 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6201 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6207 #define FAST_CACHE_SIZE 16
6210 * LOCKING: Takes the image lock depending on @take_lock.
6213 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6215 int n = mono_generic_param_num (param);
6216 MonoImage *image = param->image;
6217 MonoClass *klass = NULL;
6222 if (param->gshared_constraint) {
6223 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6226 mono_image_lock (image);
6227 klass = g_hash_table_lookup (ht, param);
6229 mono_image_unlock (image);
6234 if (n < FAST_CACHE_SIZE) {
6236 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6238 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6240 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6243 mono_image_lock (image);
6244 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6246 mono_image_unlock (image);
6253 * LOCKING: Image lock (param->image) must be held
6256 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6258 int n = mono_generic_param_num (param);
6259 MonoImage *image = param->image;
6263 if (param->gshared_constraint) {
6264 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6266 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6267 mono_memory_barrier ();
6269 image->mvar_cache_constrained = ht;
6271 image->var_cache_constrained = ht;
6273 g_hash_table_insert (ht, param, klass);
6274 } else if (n < FAST_CACHE_SIZE) {
6276 /* Requires locking to avoid droping an already published class */
6277 if (!image->mvar_cache_fast)
6278 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6279 image->mvar_cache_fast [n] = klass;
6281 if (!image->var_cache_fast)
6282 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6283 image->var_cache_fast [n] = klass;
6286 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6288 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6290 ht = g_hash_table_new (NULL, NULL);
6291 mono_memory_barrier ();
6293 image->mvar_cache_slow = ht;
6295 image->var_cache_slow = ht;
6298 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6303 * LOCKING: Acquires the image lock (@image).
6306 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6308 MonoGenericContainer *container = mono_generic_param_owner (param);
6309 MonoGenericParamInfo *pinfo = NULL;
6310 MonoClass *klass, *klass2;
6313 pinfo = mono_generic_param_info (param);
6314 klass = pinfo->pklass;
6317 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6322 if (!image && container) {
6324 MonoMethod *method = container->owner.method;
6325 image = (method && method->klass) ? method->klass->image : NULL;
6327 MonoClass *klass = container->owner.klass;
6328 // FIXME: 'klass' should not be null
6329 // But, monodis creates GenericContainers without associating a owner to it
6330 image = klass ? klass->image : NULL;
6334 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6336 mono_memory_barrier ();
6338 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6339 image = mono_defaults.corlib;
6341 mono_image_lock (image);
6343 klass2 = pinfo->pklass;
6345 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6351 pinfo->pklass = klass;
6353 set_anon_gparam_class (param, is_mvar, klass);
6355 mono_image_unlock (image);
6357 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6359 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6361 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6367 mono_ptr_class_get (MonoType *type)
6370 MonoClass *el_class;
6374 el_class = mono_class_from_mono_type (type);
6375 image = el_class->image;
6377 mono_image_lock (image);
6378 if (image->ptr_cache) {
6379 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6380 mono_image_unlock (image);
6384 mono_image_unlock (image);
6386 result = mono_image_alloc0 (image, sizeof (MonoClass));
6388 classes_size += sizeof (MonoClass);
6390 result->parent = NULL; /* no parent for PTR types */
6391 result->name_space = el_class->name_space;
6392 name = g_strdup_printf ("%s*", el_class->name);
6393 result->name = mono_image_strdup (image, name);
6396 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6398 result->image = el_class->image;
6399 result->inited = TRUE;
6400 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6401 /* Can pointers get boxed? */
6402 result->instance_size = sizeof (gpointer);
6403 result->cast_class = result->element_class = el_class;
6404 result->blittable = TRUE;
6406 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6407 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6408 result->this_arg.byref = TRUE;
6410 mono_class_setup_supertypes (result);
6412 mono_image_lock (image);
6413 if (image->ptr_cache) {
6415 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6416 mono_image_unlock (image);
6417 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6421 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6423 g_hash_table_insert (image->ptr_cache, el_class, result);
6424 mono_image_unlock (image);
6426 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6432 mono_fnptr_class_get (MonoMethodSignature *sig)
6435 static GHashTable *ptr_hash = NULL;
6437 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6439 mono_loader_lock ();
6442 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6444 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6445 mono_loader_unlock ();
6448 result = g_new0 (MonoClass, 1);
6450 result->parent = NULL; /* no parent for PTR types */
6451 result->name_space = "System";
6452 result->name = "MonoFNPtrFakeClass";
6454 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6456 result->image = mono_defaults.corlib; /* need to fix... */
6457 result->inited = TRUE;
6458 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6459 /* Can pointers get boxed? */
6460 result->instance_size = sizeof (gpointer);
6461 result->cast_class = result->element_class = result;
6462 result->blittable = TRUE;
6464 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6465 result->this_arg.data.method = result->byval_arg.data.method = sig;
6466 result->this_arg.byref = TRUE;
6467 result->blittable = TRUE;
6469 mono_class_setup_supertypes (result);
6471 g_hash_table_insert (ptr_hash, sig, result);
6473 mono_loader_unlock ();
6475 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6481 mono_class_from_mono_type (MonoType *type)
6483 switch (type->type) {
6484 case MONO_TYPE_OBJECT:
6485 return type->data.klass? type->data.klass: mono_defaults.object_class;
6486 case MONO_TYPE_VOID:
6487 return type->data.klass? type->data.klass: mono_defaults.void_class;
6488 case MONO_TYPE_BOOLEAN:
6489 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6490 case MONO_TYPE_CHAR:
6491 return type->data.klass? type->data.klass: mono_defaults.char_class;
6493 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6495 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6497 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6499 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6501 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6503 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6505 return type->data.klass? type->data.klass: mono_defaults.int_class;
6507 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6509 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6511 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6513 return type->data.klass? type->data.klass: mono_defaults.single_class;
6515 return type->data.klass? type->data.klass: mono_defaults.double_class;
6516 case MONO_TYPE_STRING:
6517 return type->data.klass? type->data.klass: mono_defaults.string_class;
6518 case MONO_TYPE_TYPEDBYREF:
6519 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6520 case MONO_TYPE_ARRAY:
6521 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6523 return mono_ptr_class_get (type->data.type);
6524 case MONO_TYPE_FNPTR:
6525 return mono_fnptr_class_get (type->data.method);
6526 case MONO_TYPE_SZARRAY:
6527 return mono_array_class_get (type->data.klass, 1);
6528 case MONO_TYPE_CLASS:
6529 case MONO_TYPE_VALUETYPE:
6530 return type->data.klass;
6531 case MONO_TYPE_GENERICINST:
6532 return mono_generic_class_get_class (type->data.generic_class);
6534 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6535 case MONO_TYPE_MVAR:
6536 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6538 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6539 g_assert_not_reached ();
6546 * mono_type_retrieve_from_typespec
6547 * @image: context where the image is created
6548 * @type_spec: typespec token
6549 * @context: the generic context used to evaluate generic instantiations in
6552 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6554 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6556 *did_inflate = FALSE;
6561 if (context && (context->class_inst || context->method_inst)) {
6562 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6564 if (!mono_error_ok (error)) {
6565 mono_loader_assert_no_error ();
6571 *did_inflate = TRUE;
6578 * mono_class_create_from_typespec
6579 * @image: context where the image is created
6580 * @type_spec: typespec token
6581 * @context: the generic context used to evaluate generic instantiations in
6584 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6587 gboolean inflated = FALSE;
6588 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6589 if (!mono_error_ok (error))
6591 ret = mono_class_from_mono_type (t);
6593 mono_metadata_free_type (t);
6598 * mono_bounded_array_class_get:
6599 * @element_class: element class
6600 * @rank: the dimension of the array class
6601 * @bounded: whenever the array has non-zero bounds
6603 * Returns: a class object describing the array with element type @element_type and
6607 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6611 MonoClass *parent = NULL;
6612 GSList *list, *rootlist = NULL;
6615 gboolean corlib_type = FALSE;
6617 g_assert (rank <= 255);
6620 /* bounded only matters for one-dimensional arrays */
6623 image = eclass->image;
6625 if (rank == 1 && !bounded) {
6627 * This case is very frequent not just during compilation because of calls
6628 * from mono_class_from_mono_type (), mono_array_new (),
6629 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6631 mono_mutex_lock (&image->szarray_cache_lock);
6632 if (!image->szarray_cache)
6633 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6634 class = g_hash_table_lookup (image->szarray_cache, eclass);
6635 mono_mutex_unlock (&image->szarray_cache_lock);
6639 mono_loader_lock ();
6641 mono_loader_lock ();
6643 if (!image->array_cache)
6644 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6646 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6647 for (; list; list = list->next) {
6649 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6650 mono_loader_unlock ();
6657 /* for the building corlib use System.Array from it */
6658 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6659 parent = mono_class_from_name (image, "System", "Array");
6662 parent = mono_defaults.array_class;
6663 if (!parent->inited)
6664 mono_class_init (parent);
6667 class = mono_image_alloc0 (image, sizeof (MonoClass));
6669 class->image = image;
6670 class->name_space = eclass->name_space;
6671 nsize = strlen (eclass->name);
6672 name = g_malloc (nsize + 2 + rank + 1);
6673 memcpy (name, eclass->name, nsize);
6676 memset (name + nsize + 1, ',', rank - 1);
6678 name [nsize + rank] = '*';
6679 name [nsize + rank + bounded] = ']';
6680 name [nsize + rank + bounded + 1] = 0;
6681 class->name = mono_image_strdup (image, name);
6684 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6686 classes_size += sizeof (MonoClass);
6688 class->type_token = 0;
6689 /* all arrays are marked serializable and sealed, bug #42779 */
6690 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6691 class->parent = parent;
6692 class->instance_size = mono_class_instance_size (class->parent);
6694 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6695 /*Arrays of those two types are invalid.*/
6696 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6697 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6698 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6699 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6700 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6702 /* element_size -1 is ok as this is not an instantitable type*/
6703 class->sizes.element_size = -1;
6705 class->sizes.element_size = mono_class_array_element_size (eclass);
6707 mono_class_setup_supertypes (class);
6709 if (eclass->generic_class)
6710 mono_class_init (eclass);
6711 if (!eclass->size_inited)
6712 mono_class_setup_fields (eclass);
6713 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6714 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6716 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6720 if (eclass->enumtype)
6721 class->cast_class = eclass->element_class;
6723 class->cast_class = eclass;
6725 switch (class->cast_class->byval_arg.type) {
6727 class->cast_class = mono_defaults.byte_class;
6730 class->cast_class = mono_defaults.int16_class;
6733 #if SIZEOF_VOID_P == 4
6737 class->cast_class = mono_defaults.int32_class;
6740 #if SIZEOF_VOID_P == 8
6744 class->cast_class = mono_defaults.int64_class;
6750 class->element_class = eclass;
6752 if ((rank > 1) || bounded) {
6753 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6754 class->byval_arg.type = MONO_TYPE_ARRAY;
6755 class->byval_arg.data.array = at;
6756 at->eklass = eclass;
6758 /* FIXME: complete.... */
6760 class->byval_arg.type = MONO_TYPE_SZARRAY;
6761 class->byval_arg.data.klass = eclass;
6763 class->this_arg = class->byval_arg;
6764 class->this_arg.byref = 1;
6769 class->generic_container = eclass->generic_container;
6771 if (rank == 1 && !bounded) {
6772 MonoClass *prev_class;
6774 mono_mutex_lock (&image->szarray_cache_lock);
6775 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6777 /* Someone got in before us */
6780 g_hash_table_insert (image->szarray_cache, eclass, class);
6781 mono_mutex_unlock (&image->szarray_cache_lock);
6783 list = g_slist_append (rootlist, class);
6784 g_hash_table_insert (image->array_cache, eclass, list);
6787 mono_loader_unlock ();
6789 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6795 * mono_array_class_get:
6796 * @element_class: element class
6797 * @rank: the dimension of the array class
6799 * Returns: a class object describing the array with element type @element_type and
6803 mono_array_class_get (MonoClass *eclass, guint32 rank)
6805 return mono_bounded_array_class_get (eclass, rank, FALSE);
6809 * mono_class_instance_size:
6812 * Returns: the size of an object instance
6815 mono_class_instance_size (MonoClass *klass)
6817 if (!klass->size_inited)
6818 mono_class_init (klass);
6820 return klass->instance_size;
6824 * mono_class_min_align:
6827 * Returns: minimm alignment requirements
6830 mono_class_min_align (MonoClass *klass)
6832 if (!klass->size_inited)
6833 mono_class_init (klass);
6835 return klass->min_align;
6839 * mono_class_value_size:
6842 * This function is used for value types, and return the
6843 * space and the alignment to store that kind of value object.
6845 * Returns: the size of a value of kind @klass
6848 mono_class_value_size (MonoClass *klass, guint32 *align)
6852 /* fixme: check disable, because we still have external revereces to
6853 * mscorlib and Dummy Objects
6855 /*g_assert (klass->valuetype);*/
6857 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6860 *align = klass->min_align;
6866 * mono_class_data_size:
6869 * Returns: the size of the static class data
6872 mono_class_data_size (MonoClass *klass)
6875 mono_class_init (klass);
6876 /* This can happen with dynamically created types */
6877 if (!klass->fields_inited)
6878 mono_class_setup_fields_locking (klass);
6880 /* in arrays, sizes.class_size is unioned with element_size
6881 * and arrays have no static fields
6885 return klass->sizes.class_size;
6889 * Auxiliary routine to mono_class_get_field
6891 * Takes a field index instead of a field token.
6893 static MonoClassField *
6894 mono_class_get_field_idx (MonoClass *class, int idx)
6896 mono_class_setup_fields_locking (class);
6897 if (class->exception_type)
6901 if (class->image->uncompressed_metadata) {
6903 * class->field.first points to the FieldPtr table, while idx points into the
6904 * Field table, so we have to do a search.
6906 /*FIXME this is broken for types with multiple fields with the same name.*/
6907 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6910 for (i = 0; i < class->field.count; ++i)
6911 if (mono_field_get_name (&class->fields [i]) == name)
6912 return &class->fields [i];
6913 g_assert_not_reached ();
6915 if (class->field.count) {
6916 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6917 return &class->fields [idx - class->field.first];
6921 class = class->parent;
6927 * mono_class_get_field:
6928 * @class: the class to lookup the field.
6929 * @field_token: the field token
6931 * Returns: A MonoClassField representing the type and offset of
6932 * the field, or a NULL value if the field does not belong to this
6936 mono_class_get_field (MonoClass *class, guint32 field_token)
6938 int idx = mono_metadata_token_index (field_token);
6940 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6942 return mono_class_get_field_idx (class, idx - 1);
6946 * mono_class_get_field_from_name:
6947 * @klass: the class to lookup the field.
6948 * @name: the field name
6950 * Search the class @klass and it's parents for a field with the name @name.
6952 * Returns: the MonoClassField pointer of the named field or NULL
6955 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6957 return mono_class_get_field_from_name_full (klass, name, NULL);
6961 * mono_class_get_field_from_name_full:
6962 * @klass: the class to lookup the field.
6963 * @name: the field name
6964 * @type: the type of the fields. This optional.
6966 * Search the class @klass and it's parents for a field with the name @name and type @type.
6968 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6969 * of its generic type definition.
6971 * Returns: the MonoClassField pointer of the named field or NULL
6974 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6978 mono_class_setup_fields_locking (klass);
6979 if (klass->exception_type)
6983 for (i = 0; i < klass->field.count; ++i) {
6984 MonoClassField *field = &klass->fields [i];
6986 if (strcmp (name, mono_field_get_name (field)) != 0)
6990 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6991 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6996 klass = klass->parent;
7002 * mono_class_get_field_token:
7003 * @field: the field we need the token of
7005 * Get the token of a field. Note that the tokesn is only valid for the image
7006 * the field was loaded from. Don't use this function for fields in dynamic types.
7008 * Returns: the token representing the field in the image it was loaded from.
7011 mono_class_get_field_token (MonoClassField *field)
7013 MonoClass *klass = field->parent;
7016 mono_class_setup_fields_locking (klass);
7021 for (i = 0; i < klass->field.count; ++i) {
7022 if (&klass->fields [i] == field) {
7023 int idx = klass->field.first + i + 1;
7025 if (klass->image->uncompressed_metadata)
7026 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7027 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7030 klass = klass->parent;
7033 g_assert_not_reached ();
7038 mono_field_get_index (MonoClassField *field)
7040 int index = field - field->parent->fields;
7042 g_assert (index >= 0 && index < field->parent->field.count);
7048 * mono_class_get_field_default_value:
7050 * Return the default value of the field as a pointer into the metadata blob.
7053 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7056 guint32 constant_cols [MONO_CONSTANT_SIZE];
7058 MonoClass *klass = field->parent;
7060 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7062 if (!klass->ext || !klass->ext->field_def_values) {
7063 MonoFieldDefaultValue *def_values;
7065 mono_class_alloc_ext (klass);
7067 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7069 mono_image_lock (klass->image);
7070 mono_memory_barrier ();
7071 if (!klass->ext->field_def_values)
7072 klass->ext->field_def_values = def_values;
7073 mono_image_unlock (klass->image);
7076 field_index = mono_field_get_index (field);
7078 if (!klass->ext->field_def_values [field_index].data) {
7079 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7083 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7085 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7086 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7087 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7090 *def_type = klass->ext->field_def_values [field_index].def_type;
7091 return klass->ext->field_def_values [field_index].data;
7095 mono_property_get_index (MonoProperty *prop)
7097 int index = prop - prop->parent->ext->properties;
7099 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7105 * mono_class_get_property_default_value:
7107 * Return the default value of the field as a pointer into the metadata blob.
7110 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7113 guint32 constant_cols [MONO_CONSTANT_SIZE];
7114 MonoClass *klass = property->parent;
7116 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7118 * We don't cache here because it is not used by C# so it's quite rare, but
7119 * we still do the lookup in klass->ext because that is where the data
7120 * is stored for dynamic assemblies.
7123 if (image_is_dynamic (klass->image)) {
7124 int prop_index = mono_property_get_index (property);
7125 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7126 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7127 return klass->ext->prop_def_values [prop_index].data;
7131 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7135 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7136 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7137 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7141 mono_class_get_event_token (MonoEvent *event)
7143 MonoClass *klass = event->parent;
7148 for (i = 0; i < klass->ext->event.count; ++i) {
7149 if (&klass->ext->events [i] == event)
7150 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7153 klass = klass->parent;
7156 g_assert_not_reached ();
7161 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7165 gpointer iter = NULL;
7166 while ((p = mono_class_get_properties (klass, &iter))) {
7167 if (! strcmp (name, p->name))
7170 klass = klass->parent;
7176 mono_class_get_property_token (MonoProperty *prop)
7178 MonoClass *klass = prop->parent;
7182 gpointer iter = NULL;
7183 while ((p = mono_class_get_properties (klass, &iter))) {
7184 if (&klass->ext->properties [i] == prop)
7185 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7189 klass = klass->parent;
7192 g_assert_not_reached ();
7197 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7199 const char *name, *nspace;
7200 if (image_is_dynamic (image))
7201 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7203 switch (type_token & 0xff000000){
7204 case MONO_TOKEN_TYPE_DEF: {
7205 guint32 cols [MONO_TYPEDEF_SIZE];
7206 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7207 guint tidx = mono_metadata_token_index (type_token);
7209 if (tidx > tt->rows)
7210 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7212 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7213 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7214 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7215 if (strlen (nspace) == 0)
7216 return g_strdup_printf ("%s", name);
7218 return g_strdup_printf ("%s.%s", nspace, name);
7221 case MONO_TOKEN_TYPE_REF: {
7223 guint32 cols [MONO_TYPEREF_SIZE];
7224 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7225 guint tidx = mono_metadata_token_index (type_token);
7228 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7230 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7231 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7232 mono_error_cleanup (&error);
7236 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7237 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7238 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7239 if (strlen (nspace) == 0)
7240 return g_strdup_printf ("%s", name);
7242 return g_strdup_printf ("%s.%s", nspace, name);
7245 case MONO_TOKEN_TYPE_SPEC:
7246 return g_strdup_printf ("Typespec 0x%08x", type_token);
7248 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7253 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7255 if (image_is_dynamic (image))
7256 return g_strdup_printf ("DynamicAssembly %s", image->name);
7258 switch (type_token & 0xff000000){
7259 case MONO_TOKEN_TYPE_DEF:
7260 if (image->assembly)
7261 return mono_stringify_assembly_name (&image->assembly->aname);
7262 else if (image->assembly_name)
7263 return g_strdup (image->assembly_name);
7264 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7265 case MONO_TOKEN_TYPE_REF: {
7267 MonoAssemblyName aname;
7268 guint32 cols [MONO_TYPEREF_SIZE];
7269 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7270 guint32 idx = mono_metadata_token_index (type_token);
7273 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7275 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7276 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7277 mono_error_cleanup (&error);
7280 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7282 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7283 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7284 case MONO_RESOLUTION_SCOPE_MODULE:
7286 return g_strdup ("");
7287 case MONO_RESOLUTION_SCOPE_MODULEREF:
7289 return g_strdup ("");
7290 case MONO_RESOLUTION_SCOPE_TYPEREF:
7292 return g_strdup ("");
7293 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7294 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7295 return mono_stringify_assembly_name (&aname);
7297 g_assert_not_reached ();
7301 case MONO_TOKEN_TYPE_SPEC:
7303 return g_strdup ("");
7305 g_assert_not_reached ();
7312 * mono_class_get_full:
7313 * @image: the image where the class resides
7314 * @type_token: the token for the class
7315 * @context: the generic context used to evaluate generic instantiations in
7316 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7318 * Returns: the MonoClass that represents @type_token in @image
7321 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7325 class = mono_class_get_checked (image, type_token, &error);
7327 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7328 class = mono_class_inflate_generic_class_checked (class, context, &error);
7330 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7336 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7340 mono_error_init (error);
7341 class = mono_class_get_checked (image, type_token, error);
7343 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7344 class = mono_class_inflate_generic_class_checked (class, context, error);
7349 * mono_class_get_checked:
7350 * @image: the image where the class resides
7351 * @type_token: the token for the class
7352 * @error: error object to return any error
7354 * Returns: the MonoClass that represents @type_token in @image
7357 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7359 MonoClass *class = NULL;
7361 mono_error_init (error);
7363 if (image_is_dynamic (image)) {
7364 int table = mono_metadata_token_table (type_token);
7366 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7367 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7370 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7374 switch (type_token & 0xff000000){
7375 case MONO_TOKEN_TYPE_DEF:
7376 class = mono_class_create_from_typedef (image, type_token, error);
7378 case MONO_TOKEN_TYPE_REF:
7379 class = mono_class_from_typeref_checked (image, type_token, error);
7381 case MONO_TOKEN_TYPE_SPEC:
7382 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7385 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7389 /* Generic case, should be avoided for when a better error is possible. */
7390 if (!class && mono_error_ok (error)) {
7391 char *name = mono_class_name_from_token (image, type_token);
7392 char *assembly = mono_assembly_name_from_token (image, type_token);
7393 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7401 * mono_type_get_checked:
7402 * @image: the image where the type resides
7403 * @type_token: the token for the type
7404 * @context: the generic context used to evaluate generic instantiations in
7405 * @error: Error handling context
7407 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7409 * Returns: the MonoType that represents @type_token in @image
7412 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7414 MonoType *type = NULL;
7415 gboolean inflated = FALSE;
7417 mono_error_init (error);
7419 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7420 if (image_is_dynamic (image))
7421 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7423 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7424 MonoClass *class = mono_class_get_checked (image, type_token, error);
7427 mono_loader_assert_no_error ();
7432 return mono_class_get_type (class);
7435 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7438 mono_loader_assert_no_error ();
7443 MonoType *tmp = type;
7444 type = mono_class_get_type (mono_class_from_mono_type (type));
7445 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7446 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7447 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7449 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7451 if (type->type != tmp->type)
7454 mono_metadata_free_type (tmp);
7461 mono_class_get (MonoImage *image, guint32 type_token)
7463 return mono_class_get_full (image, type_token, NULL);
7467 * mono_image_init_name_cache:
7469 * Initializes the class name cache stored in image->name_cache.
7471 * LOCKING: Acquires the corresponding image lock.
7474 mono_image_init_name_cache (MonoImage *image)
7476 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7477 guint32 cols [MONO_TYPEDEF_SIZE];
7480 guint32 i, visib, nspace_index;
7481 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7483 if (image->name_cache)
7486 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7488 if (image_is_dynamic (image)) {
7489 mono_image_lock (image);
7490 if (image->name_cache) {
7491 /* Somebody initialized it before us */
7492 g_hash_table_destroy (the_name_cache);
7494 mono_atomic_store_release (&image->name_cache, the_name_cache);
7496 mono_image_unlock (image);
7500 /* Temporary hash table to avoid lookups in the nspace_table */
7501 name_cache2 = g_hash_table_new (NULL, NULL);
7503 for (i = 1; i <= t->rows; ++i) {
7504 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7505 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7507 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7508 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7510 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7512 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7513 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7515 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7516 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7517 if (!nspace_table) {
7518 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7519 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7520 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7523 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7526 /* Load type names from EXPORTEDTYPES table */
7528 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7529 guint32 cols [MONO_EXP_TYPE_SIZE];
7532 for (i = 0; i < t->rows; ++i) {
7533 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7534 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7535 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7537 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7538 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7539 if (!nspace_table) {
7540 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7541 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7542 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7545 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7549 g_hash_table_destroy (name_cache2);
7550 if (image->name_cache) {
7551 /* Somebody initialized it before us */
7552 g_hash_table_destroy (the_name_cache);
7554 mono_atomic_store_release (&image->name_cache, the_name_cache);
7556 mono_image_unlock (image);
7559 /*FIXME Only dynamic assemblies should allow this operation.*/
7561 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7562 const char *name, guint32 index)
7564 GHashTable *nspace_table;
7565 GHashTable *name_cache;
7568 mono_image_init_name_cache (image);
7569 mono_image_lock (image);
7571 name_cache = image->name_cache;
7572 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7573 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7574 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7577 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7578 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7580 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7582 mono_image_unlock (image);
7591 find_nocase (gpointer key, gpointer value, gpointer user_data)
7593 char *name = (char*)key;
7594 FindUserData *data = (FindUserData*)user_data;
7596 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7597 data->value = value;
7601 * mono_class_from_name_case:
7602 * @image: The MonoImage where the type is looked up in
7603 * @name_space: the type namespace
7604 * @name: the type short name.
7605 * @deprecated: use the _checked variant
7607 * Obtains a MonoClass with a given namespace and a given name which
7608 * is located in the given MonoImage. The namespace and name
7609 * lookups are case insensitive.
7612 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7615 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7616 g_assert (!mono_error_ok (&error));
7621 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7623 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7624 guint32 cols [MONO_TYPEDEF_SIZE];
7629 mono_error_init (error);
7631 if (image_is_dynamic (image)) {
7633 FindUserData user_data;
7635 mono_image_init_name_cache (image);
7636 mono_image_lock (image);
7638 user_data.key = name_space;
7639 user_data.value = NULL;
7640 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7642 if (user_data.value) {
7643 GHashTable *nspace_table = (GHashTable*)user_data.value;
7645 user_data.key = name;
7646 user_data.value = NULL;
7648 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7650 if (user_data.value)
7651 token = GPOINTER_TO_UINT (user_data.value);
7654 mono_image_unlock (image);
7657 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7663 /* add a cache if needed */
7664 for (i = 1; i <= t->rows; ++i) {
7665 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7666 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7668 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7669 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7671 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7673 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7674 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7675 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7676 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7682 return_nested_in (MonoClass *class, char *nested)
7685 char *s = strchr (nested, '/');
7686 gpointer iter = NULL;
7693 while ((found = mono_class_get_nested_types (class, &iter))) {
7694 if (strcmp (found->name, nested) == 0) {
7696 return return_nested_in (found, s);
7704 search_modules (MonoImage *image, const char *name_space, const char *name)
7706 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7707 MonoImage *file_image;
7712 * The EXPORTEDTYPES table only contains public types, so have to search the
7714 * Note: image->modules contains the contents of the MODULEREF table, while
7715 * the real module list is in the FILE table.
7717 for (i = 0; i < file_table->rows; i++) {
7718 guint32 cols [MONO_FILE_SIZE];
7719 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7720 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7723 file_image = mono_image_load_file_for_image (image, i + 1);
7725 class = mono_class_from_name (file_image, name_space, name);
7735 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7737 GHashTable *nspace_table;
7738 MonoImage *loaded_image;
7745 mono_error_init (error);
7747 // Checking visited images avoids stack overflows when cyclic references exist.
7748 if (g_hash_table_lookup (visited_images, image))
7751 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7753 if ((nested = strchr (name, '/'))) {
7754 int pos = nested - name;
7755 int len = strlen (name);
7758 memcpy (buf, name, len + 1);
7760 nested = buf + pos + 1;
7764 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7765 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7766 gboolean res = get_class_from_name (image, name_space, name, &class);
7769 class = search_modules (image, name_space, name);
7771 return class ? return_nested_in (class, nested) : NULL;
7777 mono_image_init_name_cache (image);
7778 mono_image_lock (image);
7780 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7783 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7785 mono_image_unlock (image);
7787 if (!token && image_is_dynamic (image) && image->modules) {
7788 /* Search modules as well */
7789 for (i = 0; i < image->module_count; ++i) {
7790 MonoImage *module = image->modules [i];
7792 class = mono_class_from_name (module, name_space, name);
7799 class = search_modules (image, name_space, name);
7807 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7808 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7809 guint32 cols [MONO_EXP_TYPE_SIZE];
7812 idx = mono_metadata_token_index (token);
7814 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7816 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7817 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7818 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7821 class = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7823 return return_nested_in (class, nested);
7825 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7826 guint32 assembly_idx;
7828 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7830 mono_assembly_load_reference (image, assembly_idx - 1);
7831 g_assert (image->references [assembly_idx - 1]);
7832 if (image->references [assembly_idx - 1] == (gpointer)-1)
7835 return mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7837 g_error ("not yet implemented");
7841 token = MONO_TOKEN_TYPE_DEF | token;
7843 class = mono_class_get_checked (image, token, error);
7845 return return_nested_in (class, nested);
7850 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7853 GHashTable *visited_images;
7855 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7857 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
7859 g_hash_table_destroy (visited_images);
7865 * mono_class_from_name:
7866 * @image: The MonoImage where the type is looked up in
7867 * @name_space: the type namespace
7868 * @name: the type short name.
7870 * Obtains a MonoClass with a given namespace and a given name which
7871 * is located in the given MonoImage.
7873 * To reference nested classes, use the "/" character as a separator.
7874 * For example use "Foo/Bar" to reference the class Bar that is nested
7875 * inside Foo, like this: "class Foo { class Bar {} }".
7878 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7883 klass = mono_class_from_name_checked (image, name_space, name, &error);
7884 if (!mono_error_ok (&error)) {
7885 mono_loader_set_error_from_mono_error (&error);
7886 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7892 * mono_class_is_subclass_of:
7893 * @klass: class to probe if it is a subclass of another one
7894 * @klassc: the class we suspect is the base class
7895 * @check_interfaces: whether we should perform interface checks
7897 * This method determines whether @klass is a subclass of @klassc.
7899 * If the @check_interfaces flag is set, then if @klassc is an interface
7900 * this method return true if the @klass implements the interface or
7901 * if @klass is an interface, if one of its base classes is @klass.
7903 * If @check_interfaces is false then, then if @klass is not an interface
7904 * then it returns true if the @klass is a subclass of @klassc.
7906 * if @klass is an interface and @klassc is System.Object, then this function
7911 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7912 gboolean check_interfaces)
7914 /*FIXME test for interfaces with variant generic arguments*/
7916 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7917 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7919 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7922 for (i = 0; i < klass->interface_count; i ++) {
7923 MonoClass *ic = klass->interfaces [i];
7928 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7933 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7936 if (klassc == mono_defaults.object_class)
7943 mono_type_is_generic_argument (MonoType *type)
7945 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7949 mono_class_has_variant_generic_params (MonoClass *klass)
7952 MonoGenericContainer *container;
7954 if (!klass->generic_class)
7957 container = klass->generic_class->container_class->generic_container;
7959 for (i = 0; i < container->type_argc; ++i)
7960 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7967 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7969 if (target == candidate)
7972 if (check_for_reference_conv &&
7973 mono_type_is_generic_argument (&target->byval_arg) &&
7974 mono_type_is_generic_argument (&candidate->byval_arg)) {
7975 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7976 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7978 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7981 if (!mono_class_is_assignable_from (target, candidate))
7987 * @container the generic container from the GTD
7988 * @klass: the class to be assigned to
7989 * @oklass: the source class
7991 * Both klass and oklass must be instances of the same generic interface.
7992 * Return true if @klass can be assigned to a @klass variable
7995 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7998 MonoType **klass_argv, **oklass_argv;
7999 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8000 MonoGenericContainer *container = klass_gtd->generic_container;
8002 if (klass == oklass)
8005 /*Viable candidates are instances of the same generic interface*/
8006 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8009 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8010 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8012 for (j = 0; j < container->type_argc; ++j) {
8013 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8014 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8016 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8020 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8021 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8023 if (param1_class != param2_class) {
8024 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8025 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8027 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8028 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8038 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8040 MonoGenericParam *gparam, *ogparam;
8041 MonoGenericParamInfo *tinfo, *cinfo;
8042 MonoClass **candidate_class;
8043 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8046 if (target == candidate)
8048 if (target->byval_arg.type != candidate->byval_arg.type)
8051 gparam = target->byval_arg.data.generic_param;
8052 ogparam = candidate->byval_arg.data.generic_param;
8053 tinfo = mono_generic_param_info (gparam);
8054 cinfo = mono_generic_param_info (ogparam);
8056 class_constraint_satisfied = FALSE;
8057 valuetype_constraint_satisfied = FALSE;
8059 /*candidate must have a super set of target's special constraints*/
8060 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8061 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8063 if (cinfo->constraints) {
8064 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8065 MonoClass *cc = *candidate_class;
8067 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8068 class_constraint_satisfied = TRUE;
8069 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8070 valuetype_constraint_satisfied = TRUE;
8073 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8074 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8076 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8078 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8080 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8081 valuetype_constraint_satisfied)) {
8086 /*candidate type constraints must be a superset of target's*/
8087 if (tinfo->constraints) {
8088 MonoClass **target_class;
8089 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8090 MonoClass *tc = *target_class;
8093 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8094 * check it's constraints since it satisfy the constraint by itself.
8096 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8099 if (!cinfo->constraints)
8102 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8103 MonoClass *cc = *candidate_class;
8105 if (mono_class_is_assignable_from (tc, cc))
8109 * This happens when we have the following:
8111 * Bar<K> where K : IFace
8112 * Foo<T, U> where T : U where U : IFace
8114 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8117 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8118 if (mono_gparam_is_assignable_from (target, cc))
8122 if (!*candidate_class)
8127 /*candidate itself must have a constraint that satisfy target*/
8128 if (cinfo->constraints) {
8129 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8130 MonoClass *cc = *candidate_class;
8131 if (mono_class_is_assignable_from (target, cc))
8139 * mono_class_is_assignable_from:
8140 * @klass: the class to be assigned to
8141 * @oklass: the source class
8143 * Return: true if an instance of object oklass can be assigned to an
8144 * instance of object @klass
8147 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8149 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8151 mono_class_init (klass);
8153 if (!oklass->inited)
8154 mono_class_init (oklass);
8156 if (klass->exception_type || oklass->exception_type)
8159 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8160 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8162 return mono_gparam_is_assignable_from (klass, oklass);
8165 if (MONO_CLASS_IS_INTERFACE (klass)) {
8166 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8167 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8168 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8172 for (i = 0; constraints [i]; ++i) {
8173 if (mono_class_is_assignable_from (klass, constraints [i]))
8181 /* interface_offsets might not be set for dynamic classes */
8182 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8184 * oklass might be a generic type parameter but they have
8185 * interface_offsets set.
8187 return mono_reflection_call_is_assignable_to (oklass, klass);
8188 if (!oklass->interface_bitmap)
8189 /* Happens with generic instances of not-yet created dynamic types */
8191 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8194 if (mono_class_has_variant_generic_params (klass)) {
8197 mono_class_setup_interfaces (oklass, &error);
8198 if (!mono_error_ok (&error)) {
8199 mono_error_cleanup (&error);
8203 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8204 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8205 MonoClass *iface = oklass->interfaces_packed [i];
8207 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8212 } else if (klass->delegate) {
8213 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8215 }else if (klass->rank) {
8216 MonoClass *eclass, *eoclass;
8218 if (oklass->rank != klass->rank)
8221 /* vectors vs. one dimensional arrays */
8222 if (oklass->byval_arg.type != klass->byval_arg.type)
8225 eclass = klass->cast_class;
8226 eoclass = oklass->cast_class;
8229 * a is b does not imply a[] is b[] when a is a valuetype, and
8230 * b is a reference type.
8233 if (eoclass->valuetype) {
8234 if ((eclass == mono_defaults.enum_class) ||
8235 (eclass == mono_defaults.enum_class->parent) ||
8236 (eclass == mono_defaults.object_class))
8240 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8241 } else if (mono_class_is_nullable (klass)) {
8242 if (mono_class_is_nullable (oklass))
8243 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8245 return mono_class_is_assignable_from (klass->cast_class, oklass);
8246 } else if (klass == mono_defaults.object_class)
8249 return mono_class_has_parent (oklass, klass);
8252 /*Check if @oklass is variant compatible with @klass.*/
8254 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8257 MonoType **klass_argv, **oklass_argv;
8258 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8259 MonoGenericContainer *container = klass_gtd->generic_container;
8261 /*Viable candidates are instances of the same generic interface*/
8262 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8265 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8266 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8268 for (j = 0; j < container->type_argc; ++j) {
8269 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8270 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8272 if (param1_class->valuetype != param2_class->valuetype)
8276 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8277 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8279 if (param1_class != param2_class) {
8280 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8281 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8283 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8284 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8292 /*Check if @candidate implements the interface @target*/
8294 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8298 gboolean is_variant = mono_class_has_variant_generic_params (target);
8300 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8301 if (mono_class_is_variant_compatible_slow (target, candidate))
8306 if (candidate == target)
8309 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8310 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8311 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8313 if (tb && tb->interfaces) {
8314 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8315 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8316 MonoClass *iface_class;
8318 /* we can't realize the type here since it can do pretty much anything. */
8321 iface_class = mono_class_from_mono_type (iface->type);
8322 if (iface_class == target)
8324 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8326 if (mono_class_implement_interface_slow (target, iface_class))
8331 /*setup_interfaces don't mono_class_init anything*/
8332 /*FIXME this doesn't handle primitive type arrays.
8333 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8334 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8336 mono_class_setup_interfaces (candidate, &error);
8337 if (!mono_error_ok (&error)) {
8338 mono_error_cleanup (&error);
8342 for (i = 0; i < candidate->interface_count; ++i) {
8343 if (candidate->interfaces [i] == target)
8346 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8349 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8353 candidate = candidate->parent;
8354 } while (candidate);
8360 * Check if @oklass can be assigned to @klass.
8361 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8364 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8366 if (candidate == target)
8368 if (target == mono_defaults.object_class)
8371 if (mono_class_has_parent (candidate, target))
8374 /*If target is not an interface there is no need to check them.*/
8375 if (MONO_CLASS_IS_INTERFACE (target))
8376 return mono_class_implement_interface_slow (target, candidate);
8378 if (target->delegate && mono_class_has_variant_generic_params (target))
8379 return mono_class_is_variant_compatible (target, candidate, FALSE);
8382 MonoClass *eclass, *eoclass;
8384 if (target->rank != candidate->rank)
8387 /* vectors vs. one dimensional arrays */
8388 if (target->byval_arg.type != candidate->byval_arg.type)
8391 eclass = target->cast_class;
8392 eoclass = candidate->cast_class;
8395 * a is b does not imply a[] is b[] when a is a valuetype, and
8396 * b is a reference type.
8399 if (eoclass->valuetype) {
8400 if ((eclass == mono_defaults.enum_class) ||
8401 (eclass == mono_defaults.enum_class->parent) ||
8402 (eclass == mono_defaults.object_class))
8406 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8408 /*FIXME properly handle nullables */
8409 /*FIXME properly handle (M)VAR */
8414 * mono_class_get_cctor:
8415 * @klass: A MonoClass pointer
8417 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8420 mono_class_get_cctor (MonoClass *klass)
8422 MonoCachedClassInfo cached_info;
8424 if (image_is_dynamic (klass->image)) {
8426 * has_cctor is not set for these classes because mono_class_init () is
8429 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8432 if (!klass->has_cctor)
8435 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8437 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8438 if (!mono_error_ok (&error))
8439 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8443 if (klass->generic_class && !klass->methods)
8444 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8446 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8450 * mono_class_get_finalizer:
8451 * @klass: The MonoClass pointer
8453 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8456 mono_class_get_finalizer (MonoClass *klass)
8458 MonoCachedClassInfo cached_info;
8461 mono_class_init (klass);
8462 if (!mono_class_has_finalizer (klass))
8465 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8467 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8468 if (!mono_error_ok (&error))
8469 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8472 mono_class_setup_vtable (klass);
8473 return klass->vtable [finalize_slot];
8478 * mono_class_needs_cctor_run:
8479 * @klass: the MonoClass pointer
8480 * @caller: a MonoMethod describing the caller
8482 * Determines whenever the class has a static constructor and whenever it
8483 * needs to be called when executing CALLER.
8486 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8490 method = mono_class_get_cctor (klass);
8492 return (method == caller) ? FALSE : TRUE;
8498 * mono_class_array_element_size:
8501 * Returns: the number of bytes an element of type @klass
8502 * uses when stored into an array.
8505 mono_class_array_element_size (MonoClass *klass)
8507 MonoType *type = &klass->byval_arg;
8510 switch (type->type) {
8513 case MONO_TYPE_BOOLEAN:
8517 case MONO_TYPE_CHAR:
8526 case MONO_TYPE_CLASS:
8527 case MONO_TYPE_STRING:
8528 case MONO_TYPE_OBJECT:
8529 case MONO_TYPE_SZARRAY:
8530 case MONO_TYPE_ARRAY:
8531 return sizeof (gpointer);
8536 case MONO_TYPE_VALUETYPE:
8537 if (type->data.klass->enumtype) {
8538 type = mono_class_enum_basetype (type->data.klass);
8539 klass = klass->element_class;
8542 return mono_class_instance_size (klass) - sizeof (MonoObject);
8543 case MONO_TYPE_GENERICINST:
8544 type = &type->data.generic_class->container_class->byval_arg;
8547 case MONO_TYPE_MVAR: {
8550 return mono_type_size (type, &align);
8552 case MONO_TYPE_VOID:
8556 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8562 * mono_array_element_size:
8563 * @ac: pointer to a #MonoArrayClass
8565 * Returns: the size of single array element.
8568 mono_array_element_size (MonoClass *ac)
8570 g_assert (ac->rank);
8571 return ac->sizes.element_size;
8575 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8576 MonoGenericContext *context)
8579 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8580 g_assert (mono_error_ok (&error));
8585 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8586 MonoGenericContext *context, MonoError *error)
8588 mono_error_init (error);
8590 if (image_is_dynamic (image)) {
8591 MonoClass *tmp_handle_class;
8592 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8594 g_assert (tmp_handle_class);
8596 *handle_class = tmp_handle_class;
8598 if (tmp_handle_class == mono_defaults.typehandle_class)
8599 return &((MonoClass*)obj)->byval_arg;
8604 switch (token & 0xff000000) {
8605 case MONO_TOKEN_TYPE_DEF:
8606 case MONO_TOKEN_TYPE_REF:
8607 case MONO_TOKEN_TYPE_SPEC: {
8610 *handle_class = mono_defaults.typehandle_class;
8611 type = mono_type_get_checked (image, token, context, error);
8615 mono_class_init (mono_class_from_mono_type (type));
8616 /* We return a MonoType* as handle */
8619 case MONO_TOKEN_FIELD_DEF: {
8621 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8623 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8627 *handle_class = mono_defaults.fieldhandle_class;
8628 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8632 mono_class_init (class);
8633 return mono_class_get_field (class, token);
8635 case MONO_TOKEN_METHOD_DEF:
8636 case MONO_TOKEN_METHOD_SPEC: {
8638 meth = mono_get_method_checked (image, token, NULL, context, error);
8640 *handle_class = mono_defaults.methodhandle_class;
8646 case MONO_TOKEN_MEMBER_REF: {
8647 guint32 cols [MONO_MEMBERREF_SIZE];
8649 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8650 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8651 mono_metadata_decode_blob_size (sig, &sig);
8652 if (*sig == 0x6) { /* it's a field */
8654 MonoClassField *field;
8655 field = mono_field_from_token_checked (image, token, &klass, context, error);
8657 *handle_class = mono_defaults.fieldhandle_class;
8661 meth = mono_get_method_checked (image, token, NULL, context, error);
8663 *handle_class = mono_defaults.methodhandle_class;
8668 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8674 * This function might need to call runtime functions so it can't be part
8675 * of the metadata library.
8677 static MonoLookupDynamicToken lookup_dynamic = NULL;
8680 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8682 lookup_dynamic = func;
8686 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8688 MonoClass *handle_class;
8690 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8694 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8696 return lookup_dynamic (image, token, valid_token, handle_class, context);
8699 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8702 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8704 get_cached_class_info = func;
8708 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8710 if (!get_cached_class_info)
8713 return get_cached_class_info (klass, res);
8717 mono_install_get_class_from_name (MonoGetClassFromName func)
8719 get_class_from_name = func;
8723 mono_class_get_image (MonoClass *klass)
8725 return klass->image;
8729 * mono_class_get_element_class:
8730 * @klass: the MonoClass to act on
8732 * Returns: the element class of an array or an enumeration.
8735 mono_class_get_element_class (MonoClass *klass)
8737 return klass->element_class;
8741 * mono_class_is_valuetype:
8742 * @klass: the MonoClass to act on
8744 * Returns: true if the MonoClass represents a ValueType.
8747 mono_class_is_valuetype (MonoClass *klass)
8749 return klass->valuetype;
8753 * mono_class_is_enum:
8754 * @klass: the MonoClass to act on
8756 * Returns: true if the MonoClass represents an enumeration.
8759 mono_class_is_enum (MonoClass *klass)
8761 return klass->enumtype;
8765 * mono_class_enum_basetype:
8766 * @klass: the MonoClass to act on
8768 * Returns: the underlying type representation for an enumeration.
8771 mono_class_enum_basetype (MonoClass *klass)
8773 if (klass->element_class == klass)
8774 /* SRE or broken types */
8777 return &klass->element_class->byval_arg;
8781 * mono_class_get_parent
8782 * @klass: the MonoClass to act on
8784 * Returns: the parent class for this class.
8787 mono_class_get_parent (MonoClass *klass)
8789 return klass->parent;
8793 * mono_class_get_nesting_type;
8794 * @klass: the MonoClass to act on
8796 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8799 mono_class_get_nesting_type (MonoClass *klass)
8801 return klass->nested_in;
8805 * mono_class_get_rank:
8806 * @klass: the MonoClass to act on
8808 * Returns: the rank for the array (the number of dimensions).
8811 mono_class_get_rank (MonoClass *klass)
8817 * mono_class_get_flags:
8818 * @klass: the MonoClass to act on
8820 * The type flags from the TypeDef table from the metadata.
8821 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8824 * Returns: the flags from the TypeDef table.
8827 mono_class_get_flags (MonoClass *klass)
8829 return klass->flags;
8833 * mono_class_get_name
8834 * @klass: the MonoClass to act on
8836 * Returns: the name of the class.
8839 mono_class_get_name (MonoClass *klass)
8845 * mono_class_get_namespace:
8846 * @klass: the MonoClass to act on
8848 * Returns: the namespace of the class.
8851 mono_class_get_namespace (MonoClass *klass)
8853 return klass->name_space;
8857 * mono_class_get_type:
8858 * @klass: the MonoClass to act on
8860 * This method returns the internal Type representation for the class.
8862 * Returns: the MonoType from the class.
8865 mono_class_get_type (MonoClass *klass)
8867 return &klass->byval_arg;
8871 * mono_class_get_type_token
8872 * @klass: the MonoClass to act on
8874 * This method returns type token for the class.
8876 * Returns: the type token for the class.
8879 mono_class_get_type_token (MonoClass *klass)
8881 return klass->type_token;
8885 * mono_class_get_byref_type:
8886 * @klass: the MonoClass to act on
8891 mono_class_get_byref_type (MonoClass *klass)
8893 return &klass->this_arg;
8897 * mono_class_num_fields:
8898 * @klass: the MonoClass to act on
8900 * Returns: the number of static and instance fields in the class.
8903 mono_class_num_fields (MonoClass *klass)
8905 return klass->field.count;
8909 * mono_class_num_methods:
8910 * @klass: the MonoClass to act on
8912 * Returns: the number of methods in the class.
8915 mono_class_num_methods (MonoClass *klass)
8917 return klass->method.count;
8921 * mono_class_num_properties
8922 * @klass: the MonoClass to act on
8924 * Returns: the number of properties in the class.
8927 mono_class_num_properties (MonoClass *klass)
8929 mono_class_setup_properties (klass);
8931 return klass->ext->property.count;
8935 * mono_class_num_events:
8936 * @klass: the MonoClass to act on
8938 * Returns: the number of events in the class.
8941 mono_class_num_events (MonoClass *klass)
8943 mono_class_setup_events (klass);
8945 return klass->ext->event.count;
8949 * mono_class_get_fields:
8950 * @klass: the MonoClass to act on
8952 * This routine is an iterator routine for retrieving the fields in a class.
8954 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8955 * iterate over all of the elements. When no more values are
8956 * available, the return value is NULL.
8958 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8961 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8963 MonoClassField* field;
8967 mono_class_setup_fields_locking (klass);
8968 if (klass->exception_type)
8970 /* start from the first */
8971 if (klass->field.count) {
8972 return *iter = &klass->fields [0];
8980 if (field < &klass->fields [klass->field.count]) {
8981 return *iter = field;
8987 * mono_class_get_methods
8988 * @klass: the MonoClass to act on
8990 * This routine is an iterator routine for retrieving the fields in a class.
8992 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8993 * iterate over all of the elements. When no more values are
8994 * available, the return value is NULL.
8996 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8999 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9001 MonoMethod** method;
9005 mono_class_setup_methods (klass);
9008 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9009 * FIXME we should better report this error to the caller
9011 if (!klass->methods)
9013 /* start from the first */
9014 if (klass->method.count) {
9015 *iter = &klass->methods [0];
9016 return klass->methods [0];
9024 if (method < &klass->methods [klass->method.count]) {
9032 * mono_class_get_virtual_methods:
9034 * Iterate over the virtual methods of KLASS.
9036 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9039 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9041 MonoMethod** method;
9044 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9046 mono_class_setup_methods (klass);
9048 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9049 * FIXME we should better report this error to the caller
9051 if (!klass->methods)
9053 /* start from the first */
9054 method = &klass->methods [0];
9059 while (method < &klass->methods [klass->method.count]) {
9060 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9064 if (method < &klass->methods [klass->method.count]) {
9071 /* Search directly in metadata to avoid calling setup_methods () */
9072 MonoMethod *res = NULL;
9078 start_index = GPOINTER_TO_UINT (*iter);
9081 for (i = start_index; i < klass->method.count; ++i) {
9084 /* class->method.first points into the methodptr table */
9085 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9087 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9091 if (i < klass->method.count) {
9093 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9094 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9096 /* Add 1 here so the if (*iter) check fails */
9097 *iter = GUINT_TO_POINTER (i + 1);
9106 * mono_class_get_properties:
9107 * @klass: the MonoClass to act on
9109 * This routine is an iterator routine for retrieving the properties in a class.
9111 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9112 * iterate over all of the elements. When no more values are
9113 * available, the return value is NULL.
9115 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9118 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9120 MonoProperty* property;
9124 mono_class_setup_properties (klass);
9125 /* start from the first */
9126 if (klass->ext->property.count) {
9127 return *iter = &klass->ext->properties [0];
9135 if (property < &klass->ext->properties [klass->ext->property.count]) {
9136 return *iter = property;
9142 * mono_class_get_events:
9143 * @klass: the MonoClass to act on
9145 * This routine is an iterator routine for retrieving the properties in a class.
9147 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9148 * iterate over all of the elements. When no more values are
9149 * available, the return value is NULL.
9151 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9154 mono_class_get_events (MonoClass* klass, gpointer *iter)
9160 mono_class_setup_events (klass);
9161 /* start from the first */
9162 if (klass->ext->event.count) {
9163 return *iter = &klass->ext->events [0];
9171 if (event < &klass->ext->events [klass->ext->event.count]) {
9172 return *iter = event;
9178 * mono_class_get_interfaces
9179 * @klass: the MonoClass to act on
9181 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9183 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9184 * iterate over all of the elements. When no more values are
9185 * available, the return value is NULL.
9187 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9190 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9198 mono_class_init (klass);
9199 if (!klass->interfaces_inited) {
9200 mono_class_setup_interfaces (klass, &error);
9201 if (!mono_error_ok (&error)) {
9202 mono_error_cleanup (&error);
9206 /* start from the first */
9207 if (klass->interface_count) {
9208 *iter = &klass->interfaces [0];
9209 return klass->interfaces [0];
9217 if (iface < &klass->interfaces [klass->interface_count]) {
9225 setup_nested_types (MonoClass *klass)
9228 GList *classes, *nested_classes, *l;
9231 if (klass->nested_classes_inited)
9234 if (!klass->type_token)
9235 klass->nested_classes_inited = TRUE;
9237 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9241 guint32 cols [MONO_NESTED_CLASS_SIZE];
9242 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9243 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9244 if (!mono_error_ok (&error)) {
9245 /*FIXME don't swallow the error message*/
9246 mono_error_cleanup (&error);
9248 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9252 classes = g_list_prepend (classes, nclass);
9254 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9257 mono_class_alloc_ext (klass);
9259 nested_classes = NULL;
9260 for (l = classes; l; l = l->next)
9261 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9262 g_list_free (classes);
9264 mono_image_lock (klass->image);
9266 mono_memory_barrier ();
9267 if (!klass->nested_classes_inited) {
9268 klass->ext->nested_classes = nested_classes;
9269 mono_memory_barrier ();
9270 klass->nested_classes_inited = TRUE;
9273 mono_image_unlock (klass->image);
9277 * mono_class_get_nested_types
9278 * @klass: the MonoClass to act on
9280 * This routine is an iterator routine for retrieving the nested types of a class.
9281 * This works only if @klass is non-generic, or a generic type definition.
9283 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9284 * iterate over all of the elements. When no more values are
9285 * available, the return value is NULL.
9287 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9290 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9296 if (!klass->nested_classes_inited)
9297 setup_nested_types (klass);
9300 /* start from the first */
9301 if (klass->ext && klass->ext->nested_classes) {
9302 *iter = klass->ext->nested_classes;
9303 return klass->ext->nested_classes->data;
9305 /* no nested types */
9320 * mono_class_is_delegate
9321 * @klass: the MonoClass to act on
9323 * Returns: true if the MonoClass represents a System.Delegate.
9326 mono_class_is_delegate (MonoClass *klass)
9328 return klass->delegate;
9332 * mono_class_implements_interface
9333 * @klass: The MonoClass to act on
9334 * @interface: The interface to check if @klass implements.
9336 * Returns: true if @klass implements @interface.
9339 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9341 return mono_class_is_assignable_from (iface, klass);
9345 * mono_field_get_name:
9346 * @field: the MonoClassField to act on
9348 * Returns: the name of the field.
9351 mono_field_get_name (MonoClassField *field)
9357 * mono_field_get_type:
9358 * @field: the MonoClassField to act on
9360 * Returns: MonoType of the field.
9363 mono_field_get_type (MonoClassField *field)
9366 MonoType *type = mono_field_get_type_checked (field, &error);
9367 if (!mono_error_ok (&error)) {
9368 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9369 mono_error_cleanup (&error);
9376 * mono_field_get_type_checked:
9377 * @field: the MonoClassField to act on
9378 * @error: used to return any erro found while retrieving @field type
9380 * Returns: MonoType of the field.
9383 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9385 mono_error_init (error);
9387 mono_field_resolve_type (field, error);
9392 * mono_field_get_parent:
9393 * @field: the MonoClassField to act on
9395 * Returns: MonoClass where the field was defined.
9398 mono_field_get_parent (MonoClassField *field)
9400 return field->parent;
9404 * mono_field_get_flags;
9405 * @field: the MonoClassField to act on
9407 * The metadata flags for a field are encoded using the
9408 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9410 * Returns: the flags for the field.
9413 mono_field_get_flags (MonoClassField *field)
9416 return mono_field_resolve_flags (field);
9417 return field->type->attrs;
9421 * mono_field_get_offset;
9422 * @field: the MonoClassField to act on
9424 * Returns: the field offset.
9427 mono_field_get_offset (MonoClassField *field)
9429 return field->offset;
9433 mono_field_get_rva (MonoClassField *field)
9437 MonoClass *klass = field->parent;
9438 MonoFieldDefaultValue *field_def_values;
9440 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9442 if (!klass->ext || !klass->ext->field_def_values) {
9443 mono_class_alloc_ext (klass);
9445 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9447 mono_image_lock (klass->image);
9448 if (!klass->ext->field_def_values)
9449 klass->ext->field_def_values = field_def_values;
9450 mono_image_unlock (klass->image);
9453 field_index = mono_field_get_index (field);
9455 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9456 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9458 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9459 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9462 return klass->ext->field_def_values [field_index].data;
9466 * mono_field_get_data;
9467 * @field: the MonoClassField to act on
9469 * Returns: pointer to the metadata constant value or to the field
9470 * data if it has an RVA flag.
9473 mono_field_get_data (MonoClassField *field)
9475 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9476 MonoTypeEnum def_type;
9478 return mono_class_get_field_default_value (field, &def_type);
9479 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9480 return mono_field_get_rva (field);
9487 * mono_property_get_name:
9488 * @prop: the MonoProperty to act on
9490 * Returns: the name of the property
9493 mono_property_get_name (MonoProperty *prop)
9499 * mono_property_get_set_method
9500 * @prop: the MonoProperty to act on.
9502 * Returns: the setter method of the property (A MonoMethod)
9505 mono_property_get_set_method (MonoProperty *prop)
9511 * mono_property_get_get_method
9512 * @prop: the MonoProperty to act on.
9514 * Returns: the setter method of the property (A MonoMethod)
9517 mono_property_get_get_method (MonoProperty *prop)
9523 * mono_property_get_parent:
9524 * @prop: the MonoProperty to act on.
9526 * Returns: the MonoClass where the property was defined.
9529 mono_property_get_parent (MonoProperty *prop)
9531 return prop->parent;
9535 * mono_property_get_flags:
9536 * @prop: the MonoProperty to act on.
9538 * The metadata flags for a property are encoded using the
9539 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9541 * Returns: the flags for the property.
9544 mono_property_get_flags (MonoProperty *prop)
9550 * mono_event_get_name:
9551 * @event: the MonoEvent to act on
9553 * Returns: the name of the event.
9556 mono_event_get_name (MonoEvent *event)
9562 * mono_event_get_add_method:
9563 * @event: The MonoEvent to act on.
9565 * Returns: the @add' method for the event (a MonoMethod).
9568 mono_event_get_add_method (MonoEvent *event)
9574 * mono_event_get_remove_method:
9575 * @event: The MonoEvent to act on.
9577 * Returns: the @remove method for the event (a MonoMethod).
9580 mono_event_get_remove_method (MonoEvent *event)
9582 return event->remove;
9586 * mono_event_get_raise_method:
9587 * @event: The MonoEvent to act on.
9589 * Returns: the @raise method for the event (a MonoMethod).
9592 mono_event_get_raise_method (MonoEvent *event)
9594 return event->raise;
9598 * mono_event_get_parent:
9599 * @event: the MonoEvent to act on.
9601 * Returns: the MonoClass where the event is defined.
9604 mono_event_get_parent (MonoEvent *event)
9606 return event->parent;
9610 * mono_event_get_flags
9611 * @event: the MonoEvent to act on.
9613 * The metadata flags for an event are encoded using the
9614 * EVENT_* constants. See the tabledefs.h file for details.
9616 * Returns: the flags for the event.
9619 mono_event_get_flags (MonoEvent *event)
9621 return event->attrs;
9625 * mono_class_get_method_from_name:
9626 * @klass: where to look for the method
9627 * @name: name of the method
9628 * @param_count: number of parameters. -1 for any number.
9630 * Obtains a MonoMethod with a given name and number of parameters.
9631 * It only works if there are no multiple signatures for any given method name.
9634 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9636 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9640 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9642 MonoMethod *res = NULL;
9645 /* Search directly in the metadata to avoid calling setup_methods () */
9646 for (i = 0; i < klass->method.count; ++i) {
9648 guint32 cols [MONO_METHOD_SIZE];
9650 MonoMethodSignature *sig;
9652 /* class->method.first points into the methodptr table */
9653 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9655 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9656 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9658 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9661 if (param_count == -1) {
9665 sig = mono_method_signature_checked (method, &error);
9667 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9670 if (sig->param_count == param_count) {
9681 * mono_class_get_method_from_name_flags:
9682 * @klass: where to look for the method
9683 * @name_space: name of the method
9684 * @param_count: number of parameters. -1 for any number.
9685 * @flags: flags which must be set in the method
9687 * Obtains a MonoMethod with a given name and number of parameters.
9688 * It only works if there are no multiple signatures for any given method name.
9691 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9693 MonoMethod *res = NULL;
9696 mono_class_init (klass);
9698 if (klass->generic_class && !klass->methods) {
9699 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9702 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9703 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9708 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9709 mono_class_setup_methods (klass);
9711 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9712 See mono/tests/array_load_exception.il
9713 FIXME we should better report this error to the caller
9715 if (!klass->methods)
9717 for (i = 0; i < klass->method.count; ++i) {
9718 MonoMethod *method = klass->methods [i];
9720 if (method->name[0] == name [0] &&
9721 !strcmp (name, method->name) &&
9722 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9723 ((method->flags & flags) == flags)) {
9730 res = find_method_in_metadata (klass, name, param_count, flags);
9737 * mono_class_set_failure:
9738 * @klass: class in which the failure was detected
9739 * @ex_type: the kind of exception/error to be thrown (later)
9740 * @ex_data: exception data (specific to each type of exception/error)
9742 * Keep a detected failure informations in the class for later processing.
9743 * Note that only the first failure is kept.
9745 * LOCKING: Acquires the loader lock.
9748 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9750 if (klass->exception_type)
9753 mono_loader_lock ();
9754 klass->exception_type = ex_type;
9756 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9757 mono_loader_unlock ();
9763 * mono_class_get_exception_data:
9765 * Return the exception_data property of KLASS.
9767 * LOCKING: Acquires the loader lock.
9770 mono_class_get_exception_data (MonoClass *klass)
9772 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9776 * mono_classes_init:
9778 * Initialize the resources used by this module.
9781 mono_classes_init (void)
9783 mono_mutex_init (&classes_mutex);
9785 mono_counters_register ("Inflated methods size",
9786 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9787 mono_counters_register ("Inflated classes",
9788 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9789 mono_counters_register ("Inflated classes size",
9790 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9791 mono_counters_register ("MonoClass size",
9792 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9793 mono_counters_register ("MonoClassExt size",
9794 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9798 * mono_classes_cleanup:
9800 * Free the resources used by this module.
9803 mono_classes_cleanup (void)
9805 if (global_interface_bitset)
9806 mono_bitset_free (global_interface_bitset);
9807 global_interface_bitset = NULL;
9808 mono_mutex_destroy (&classes_mutex);
9812 * mono_class_get_exception_for_failure:
9813 * @klass: class in which the failure was detected
9815 * Return a constructed MonoException than the caller can then throw
9816 * using mono_raise_exception - or NULL if no failure is present (or
9817 * doesn't result in an exception).
9820 mono_class_get_exception_for_failure (MonoClass *klass)
9822 gpointer exception_data = mono_class_get_exception_data (klass);
9824 switch (klass->exception_type) {
9825 case MONO_EXCEPTION_TYPE_LOAD: {
9828 char *str = mono_type_get_full_name (klass);
9829 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9830 name = mono_string_new (mono_domain_get (), str);
9832 ex = mono_get_exception_type_load (name, astr);
9836 case MONO_EXCEPTION_MISSING_METHOD: {
9837 char *class_name = exception_data;
9838 char *assembly_name = class_name + strlen (class_name) + 1;
9840 return mono_get_exception_missing_method (class_name, assembly_name);
9842 case MONO_EXCEPTION_MISSING_FIELD: {
9843 char *class_name = exception_data;
9844 char *member_name = class_name + strlen (class_name) + 1;
9846 return mono_get_exception_missing_field (class_name, member_name);
9848 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9849 char *msg_format = exception_data;
9850 char *assembly_name = msg_format + strlen (msg_format) + 1;
9851 char *msg = g_strdup_printf (msg_format, assembly_name);
9854 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9860 case MONO_EXCEPTION_BAD_IMAGE: {
9861 return mono_get_exception_bad_image_format (exception_data);
9864 MonoLoaderError *error;
9867 error = mono_loader_get_last_error ();
9869 ex = mono_loader_error_prepare_exception (error);
9873 /* TODO - handle other class related failures */
9880 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9882 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9883 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9885 if (outer_klass == inner_klass)
9887 inner_klass = inner_klass->nested_in;
9888 } while (inner_klass);
9893 mono_class_get_generic_type_definition (MonoClass *klass)
9895 return klass->generic_class ? klass->generic_class->container_class : klass;
9899 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9901 * Generic instantiations are ignored for all super types of @klass.
9903 * Visibility checks ignoring generic instantiations.
9906 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9909 klass = mono_class_get_generic_type_definition (klass);
9910 parent = mono_class_get_generic_type_definition (parent);
9911 mono_class_setup_supertypes (klass);
9913 for (i = 0; i < klass->idepth; ++i) {
9914 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9920 * Subtype can only access parent members with family protection if the site object
9921 * is subclass of Subtype. For example:
9922 * class A { protected int x; }
9924 * void valid_access () {
9928 * void invalid_access () {
9935 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9937 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9940 if (context_klass == NULL)
9942 /*if access_klass is not member_klass context_klass must be type compat*/
9943 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9949 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9952 if (accessing == accessed)
9954 if (!accessed || !accessing)
9957 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9958 * anywhere so untrusted friends are not safe to access platform's code internals */
9959 if (mono_security_core_clr_enabled ()) {
9960 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9964 mono_assembly_load_friends (accessed);
9965 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9966 MonoAssemblyName *friend = tmp->data;
9967 /* Be conservative with checks */
9970 if (strcmp (accessing->aname.name, friend->name))
9972 if (friend->public_key_token [0]) {
9973 if (!accessing->aname.public_key_token [0])
9975 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9984 * If klass is a generic type or if it is derived from a generic type, return the
9985 * MonoClass of the generic definition
9986 * Returns NULL if not found
9989 get_generic_definition_class (MonoClass *klass)
9992 if (klass->generic_class && klass->generic_class->container_class)
9993 return klass->generic_class->container_class;
9994 klass = klass->parent;
10000 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10003 for (i = 0; i < ginst->type_argc; ++i) {
10004 MonoType *type = ginst->type_argv[i];
10005 switch (type->type) {
10006 case MONO_TYPE_SZARRAY:
10007 if (!can_access_type (access_klass, type->data.klass))
10010 case MONO_TYPE_ARRAY:
10011 if (!can_access_type (access_klass, type->data.array->eklass))
10014 case MONO_TYPE_PTR:
10015 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10018 case MONO_TYPE_CLASS:
10019 case MONO_TYPE_VALUETYPE:
10020 case MONO_TYPE_GENERICINST:
10021 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10031 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10035 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10038 if (access_klass->element_class && !access_klass->enumtype)
10039 access_klass = access_klass->element_class;
10041 if (member_klass->element_class && !member_klass->enumtype)
10042 member_klass = member_klass->element_class;
10044 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10046 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10049 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10052 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10055 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10058 /*Non nested type with nested visibility. We just fail it.*/
10059 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10062 switch (access_level) {
10063 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10064 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10066 case TYPE_ATTRIBUTE_PUBLIC:
10069 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10072 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10073 return is_nesting_type (member_klass, access_klass);
10075 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10076 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10078 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10079 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10081 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10082 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10083 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10085 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10086 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10087 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10092 /* FIXME: check visibility of type, too */
10094 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10096 MonoClass *member_generic_def;
10097 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10100 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10101 access_klass->generic_container) &&
10102 (member_generic_def = get_generic_definition_class (member_klass))) {
10103 MonoClass *access_container;
10105 if (access_klass->generic_container)
10106 access_container = access_klass;
10108 access_container = access_klass->generic_class->container_class;
10110 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10114 /* Partition I 8.5.3.2 */
10115 /* the access level values are the same for fields and methods */
10116 switch (access_level) {
10117 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10118 /* same compilation unit */
10119 return access_klass->image == member_klass->image;
10120 case FIELD_ATTRIBUTE_PRIVATE:
10121 return access_klass == member_klass;
10122 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10123 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10124 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10127 case FIELD_ATTRIBUTE_ASSEMBLY:
10128 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10129 case FIELD_ATTRIBUTE_FAMILY:
10130 if (is_valid_family_access (access_klass, member_klass, context_klass))
10133 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10134 if (is_valid_family_access (access_klass, member_klass, context_klass))
10136 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10137 case FIELD_ATTRIBUTE_PUBLIC:
10144 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10146 /* FIXME: check all overlapping fields */
10147 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10149 MonoClass *nested = method->klass->nested_in;
10151 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10154 nested = nested->nested_in;
10161 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10163 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10165 MonoClass *nested = method->klass->nested_in;
10167 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10170 nested = nested->nested_in;
10175 * with generics calls to explicit interface implementations can be expressed
10176 * directly: the method is private, but we must allow it. This may be opening
10177 * a hole or the generics code should handle this differently.
10178 * Maybe just ensure the interface type is public.
10180 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10186 * mono_method_can_access_method_full:
10187 * @method: The caller method
10188 * @called: The called method
10189 * @context_klass: The static type on stack of the owner @called object used
10191 * This function must be used with instance calls, as they have more strict family accessibility.
10192 * It can be used with static methods, but context_klass should be NULL.
10194 * Returns: TRUE if caller have proper visibility and acessibility to @called
10197 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10199 MonoClass *access_class = method->klass;
10200 MonoClass *member_class = called->klass;
10201 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10203 MonoClass *nested = access_class->nested_in;
10205 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10208 nested = nested->nested_in;
10215 can = can_access_type (access_class, member_class);
10217 MonoClass *nested = access_class->nested_in;
10219 can = can_access_type (nested, member_class);
10222 nested = nested->nested_in;
10229 if (called->is_inflated) {
10230 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10231 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10240 * mono_method_can_access_field_full:
10241 * @method: The caller method
10242 * @field: The accessed field
10243 * @context_klass: The static type on stack of the owner @field object used
10245 * This function must be used with instance fields, as they have more strict family accessibility.
10246 * It can be used with static fields, but context_klass should be NULL.
10248 * Returns: TRUE if caller have proper visibility and acessibility to @field
10251 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10253 MonoClass *access_class = method->klass;
10254 MonoClass *member_class = field->parent;
10255 /* FIXME: check all overlapping fields */
10256 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10258 MonoClass *nested = access_class->nested_in;
10260 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10263 nested = nested->nested_in;
10270 can = can_access_type (access_class, member_class);
10272 MonoClass *nested = access_class->nested_in;
10274 can = can_access_type (nested, member_class);
10277 nested = nested->nested_in;
10287 * mono_class_can_access_class:
10288 * @source_class: The source class
10289 * @target_class: The accessed class
10291 * This function returns is @target_class is visible to @source_class
10293 * Returns: TRUE if source have proper visibility and acessibility to target
10296 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10298 return can_access_type (source_class, target_class);
10302 * mono_type_is_valid_enum_basetype:
10303 * @type: The MonoType to check
10305 * Returns: TRUE if the type can be used as the basetype of an enum
10307 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10308 switch (type->type) {
10311 case MONO_TYPE_BOOLEAN:
10314 case MONO_TYPE_CHAR:
10328 * mono_class_is_valid_enum:
10329 * @klass: An enum class to be validated
10331 * This method verify the required properties an enum should have.
10333 * Returns: TRUE if the informed enum class is valid
10335 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10336 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10337 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10339 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10340 MonoClassField * field;
10341 gpointer iter = NULL;
10342 gboolean found_base_field = FALSE;
10344 g_assert (klass->enumtype);
10345 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10346 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10350 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10353 while ((field = mono_class_get_fields (klass, &iter))) {
10354 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10355 if (found_base_field)
10357 found_base_field = TRUE;
10358 if (!mono_type_is_valid_enum_basetype (field->type))
10363 if (!found_base_field)
10366 if (klass->method.count > 0)
10373 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10375 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10379 * mono_class_setup_interface_id:
10381 * Initializes MonoClass::interface_id if required.
10383 * LOCKING: Acquires the loader lock.
10386 mono_class_setup_interface_id (MonoClass *class)
10388 mono_loader_lock ();
10389 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10390 class->interface_id = mono_get_unique_iid (class);
10391 mono_loader_unlock ();
10395 * mono_class_alloc_ext:
10397 * Allocate klass->ext if not already done.
10400 mono_class_alloc_ext (MonoClass *klass)
10407 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10408 mono_image_lock (klass->image);
10409 mono_memory_barrier ();
10412 class_ext_size += sizeof (MonoClassExt);
10413 mono_image_unlock (klass->image);
10417 * mono_class_setup_interfaces:
10419 * Initialize class->interfaces/interfaces_count.
10420 * LOCKING: Acquires the loader lock.
10421 * This function can fail the type.
10424 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10426 int i, interface_count;
10427 MonoClass **interfaces;
10429 mono_error_init (error);
10431 if (klass->interfaces_inited)
10434 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10435 MonoType *args [1];
10437 /* generic IList, ICollection, IEnumerable */
10438 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10439 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10441 args [0] = &klass->element_class->byval_arg;
10442 interfaces [0] = mono_class_bind_generic_parameters (
10443 mono_defaults.generic_ilist_class, 1, args, FALSE);
10444 if (interface_count > 1)
10445 interfaces [1] = mono_class_bind_generic_parameters (
10446 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10447 } else if (klass->generic_class) {
10448 MonoClass *gklass = klass->generic_class->container_class;
10450 mono_class_setup_interfaces (gklass, error);
10451 if (!mono_error_ok (error)) {
10452 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10456 interface_count = gklass->interface_count;
10457 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10458 for (i = 0; i < interface_count; i++) {
10459 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10460 if (!mono_error_ok (error)) {
10461 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10466 interface_count = 0;
10470 mono_image_lock (klass->image);
10472 if (!klass->interfaces_inited) {
10473 klass->interface_count = interface_count;
10474 klass->interfaces = interfaces;
10476 mono_memory_barrier ();
10478 klass->interfaces_inited = TRUE;
10481 mono_image_unlock (klass->image);
10485 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10487 MonoClass *class = field->parent;
10488 MonoImage *image = class->image;
10489 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10490 int field_idx = field - class->fields;
10492 mono_error_init (error);
10495 MonoClassField *gfield = >d->fields [field_idx];
10496 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10497 if (!mono_error_ok (error)) {
10498 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10499 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10503 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10504 if (!mono_error_ok (error)) {
10505 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10506 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10511 guint32 cols [MONO_FIELD_SIZE];
10512 MonoGenericContainer *container = NULL;
10513 int idx = class->field.first + field_idx;
10515 /*FIXME, in theory we do not lazy load SRE fields*/
10516 g_assert (!image_is_dynamic (image));
10518 if (class->generic_container) {
10519 container = class->generic_container;
10521 container = gtd->generic_container;
10522 g_assert (container);
10525 /* class->field.first and idx points into the fieldptr table */
10526 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10528 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10529 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10530 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10534 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10536 mono_metadata_decode_value (sig, &sig);
10537 /* FIELD signature == 0x06 */
10538 g_assert (*sig == 0x06);
10539 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10541 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10546 mono_field_resolve_flags (MonoClassField *field)
10548 MonoClass *class = field->parent;
10549 MonoImage *image = class->image;
10550 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10551 int field_idx = field - class->fields;
10555 MonoClassField *gfield = >d->fields [field_idx];
10556 return mono_field_get_flags (gfield);
10558 int idx = class->field.first + field_idx;
10560 /*FIXME, in theory we do not lazy load SRE fields*/
10561 g_assert (!image_is_dynamic (image));
10563 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10568 * mono_class_setup_basic_field_info:
10569 * @class: The class to initialize
10571 * Initializes the class->fields array of fields.
10572 * Aquires the loader lock.
10575 mono_class_setup_basic_field_info_locking (MonoClass *class)
10577 mono_loader_lock ();
10578 mono_class_setup_basic_field_info (class);
10579 mono_loader_unlock ();
10583 * mono_class_get_fields_lazy:
10584 * @klass: the MonoClass to act on
10586 * This routine is an iterator routine for retrieving the fields in a class.
10587 * Only minimal information about fields are loaded. Accessors must be used
10588 * for all MonoClassField returned.
10590 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10591 * iterate over all of the elements. When no more values are
10592 * available, the return value is NULL.
10594 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10597 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10599 MonoClassField* field;
10603 mono_class_setup_basic_field_info_locking (klass);
10604 if (!klass->fields)
10606 /* start from the first */
10607 if (klass->field.count) {
10608 return *iter = &klass->fields [0];
10616 if (field < &klass->fields [klass->field.count]) {
10617 return *iter = field;
10623 mono_class_full_name (MonoClass *klass)
10625 return mono_type_full_name (&klass->byval_arg);