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;
1013 mono_error_init (error);
1015 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1016 while (method->is_inflated) {
1017 MonoGenericContext *method_context = mono_method_get_context (method);
1018 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1020 tmp_context = inflate_generic_context (method_context, context, error);
1021 if (!mono_error_ok (error))
1023 context = &tmp_context;
1025 if (mono_metadata_generic_context_equal (method_context, context))
1028 method = imethod->declaring;
1032 * A method only needs to be inflated if the context has argument for which it is
1035 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1036 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1039 if (!((method->is_generic && context->method_inst) ||
1040 (method->klass->generic_container && context->class_inst)))
1043 iresult = g_new0 (MonoMethodInflated, 1);
1044 iresult->context = *context;
1045 iresult->declaring = method;
1047 if (!context->method_inst && method->is_generic)
1048 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1050 if (!context->class_inst) {
1051 g_assert (!iresult->declaring->klass->generic_class);
1052 if (iresult->declaring->klass->generic_container)
1053 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1054 else if (iresult->declaring->klass->generic_class)
1055 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1057 /* This can happen with some callers like mono_object_get_virtual_method () */
1058 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1059 iresult->context.class_inst = NULL;
1061 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1064 mono_image_set_lock (set);
1065 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1066 mono_image_set_unlock (set);
1070 return (MonoMethod*)cached;
1073 mono_stats.inflated_method_count++;
1075 inflated_methods_size += sizeof (MonoMethodInflated);
1077 sig = mono_method_signature (method);
1079 char *name = mono_type_get_full_name (method->klass);
1080 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1086 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1088 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1091 result = (MonoMethod *) iresult;
1092 result->is_inflated = TRUE;
1093 result->is_generic = FALSE;
1094 result->sre_method = FALSE;
1095 result->signature = NULL;
1097 if (!context->method_inst) {
1098 /* Set the generic_container of the result to the generic_container of method */
1099 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1101 if (generic_container) {
1102 result->is_generic = 1;
1103 mono_method_set_generic_container (result, generic_container);
1107 if (!klass_hint || !klass_hint->generic_class ||
1108 klass_hint->generic_class->container_class != method->klass ||
1109 klass_hint->generic_class->context.class_inst != context->class_inst)
1112 if (method->klass->generic_container)
1113 result->klass = klass_hint;
1115 if (!result->klass) {
1116 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1117 if (!mono_error_ok (error))
1120 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1122 mono_metadata_free_type (inflated);
1126 * FIXME: This should hold, but it doesn't:
1128 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1129 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1130 * g_assert (result->is_generic);
1133 * Fixing this here causes other things to break, hence a very
1134 * ugly hack in mini-trampolines.c - see
1135 * is_generic_method_definition().
1139 mono_image_set_lock (set);
1140 cached = g_hash_table_lookup (set->gmethod_cache, iresult);
1142 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1143 iresult->owner = set;
1146 mono_image_set_unlock (set);
1148 return (MonoMethod*)cached;
1156 * mono_get_inflated_method:
1158 * Obsolete. We keep it around since it's mentioned in the public API.
1161 mono_get_inflated_method (MonoMethod *method)
1167 * mono_method_get_context_general:
1169 * @uninflated: handle uninflated methods?
1171 * Returns the generic context of a method or NULL if it doesn't have
1172 * one. For an inflated method that's the context stored in the
1173 * method. Otherwise it's in the method's generic container or in the
1174 * generic container of the method's class.
1177 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1179 if (method->is_inflated) {
1180 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1181 return &imethod->context;
1185 if (method->is_generic)
1186 return &(mono_method_get_generic_container (method)->context);
1187 if (method->klass->generic_container)
1188 return &method->klass->generic_container->context;
1193 * mono_method_get_context:
1196 * Returns the generic context for method if it's inflated, otherwise
1200 mono_method_get_context (MonoMethod *method)
1202 return mono_method_get_context_general (method, FALSE);
1206 * mono_method_get_generic_container:
1208 * Returns the generic container of METHOD, which should be a generic method definition.
1209 * Returns NULL if METHOD is not a generic method definition.
1210 * LOCKING: Acquires the loader lock.
1212 MonoGenericContainer*
1213 mono_method_get_generic_container (MonoMethod *method)
1215 MonoGenericContainer *container;
1217 if (!method->is_generic)
1220 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1221 g_assert (container);
1227 * mono_method_set_generic_container:
1229 * Sets the generic container of METHOD to CONTAINER.
1230 * LOCKING: Acquires the image lock.
1233 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1235 g_assert (method->is_generic);
1237 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1241 * mono_class_find_enum_basetype:
1242 * @class: The enum class
1244 * Determine the basetype of an enum by iterating through its fields. We do this
1245 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1248 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1250 MonoGenericContainer *container = NULL;
1251 MonoImage *m = class->image;
1252 const int top = class->field.count;
1255 g_assert (class->enumtype);
1257 mono_error_init (error);
1259 if (class->generic_container)
1260 container = class->generic_container;
1261 else if (class->generic_class) {
1262 MonoClass *gklass = class->generic_class->container_class;
1264 container = gklass->generic_container;
1265 g_assert (container);
1269 * Fetch all the field information.
1271 for (i = 0; i < top; i++){
1273 guint32 cols [MONO_FIELD_SIZE];
1274 int idx = class->field.first + i;
1277 /* class->field.first and idx points into the fieldptr table */
1278 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1280 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1283 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1284 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1288 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1289 mono_metadata_decode_value (sig, &sig);
1290 /* FIELD signature == 0x06 */
1292 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1296 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1298 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1299 mono_error_set_from_loader_error (error);
1301 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1304 if (class->generic_class) {
1305 //FIXME do we leak here?
1306 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1307 if (!mono_error_ok (error))
1309 ftype->attrs = cols [MONO_FIELD_FLAGS];
1314 mono_error_set_type_load_class (error, class, "Could not find base type");
1317 mono_loader_assert_no_error ();
1322 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1325 mono_type_has_exceptions (MonoType *type)
1327 switch (type->type) {
1328 case MONO_TYPE_CLASS:
1329 case MONO_TYPE_VALUETYPE:
1330 case MONO_TYPE_SZARRAY:
1331 return type->data.klass->exception_type;
1332 case MONO_TYPE_ARRAY:
1333 return type->data.array->eklass->exception_type;
1334 case MONO_TYPE_GENERICINST:
1335 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1344 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1348 mono_class_alloc (MonoClass *class, int size)
1350 if (class->generic_class)
1351 return mono_image_set_alloc (class->generic_class->owner, size);
1353 return mono_image_alloc (class->image, size);
1357 mono_class_alloc0 (MonoClass *class, int size)
1361 res = mono_class_alloc (class, size);
1362 memset (res, 0, size);
1366 #define mono_class_new0(class,struct_type, n_structs) \
1367 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1370 * mono_class_setup_basic_field_info:
1371 * @class: The class to initialize
1373 * Initializes the class->fields.
1374 * LOCKING: Assumes the loader lock is held.
1377 mono_class_setup_basic_field_info (MonoClass *class)
1379 MonoClassField *field;
1387 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1388 image = class->image;
1389 top = class->field.count;
1391 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1393 * This happens when a generic instance of an unfinished generic typebuilder
1394 * is used as an element type for creating an array type. We can't initialize
1395 * the fields of this class using the fields of gklass, since gklass is not
1396 * finished yet, fields could be added to it later.
1402 mono_class_setup_basic_field_info (gtd);
1404 top = gtd->field.count;
1405 class->field.first = gtd->field.first;
1406 class->field.count = gtd->field.count;
1409 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1412 * Fetch all the field information.
1414 for (i = 0; i < top; i++){
1415 field = &class->fields [i];
1416 field->parent = class;
1419 field->name = mono_field_get_name (>d->fields [i]);
1421 int idx = class->field.first + i;
1422 /* class->field.first and idx points into the fieldptr table */
1423 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1424 /* The name is needed for fieldrefs */
1425 field->name = mono_metadata_string_heap (image, name_idx);
1431 * mono_class_setup_fields:
1432 * @class: The class to initialize
1434 * Initializes the class->fields.
1435 * LOCKING: Assumes the loader lock is held.
1438 mono_class_setup_fields (MonoClass *class)
1441 MonoImage *m = class->image;
1443 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1444 int i, blittable = TRUE;
1445 guint32 real_size = 0;
1446 guint32 packing_size = 0;
1447 gboolean explicit_size;
1448 MonoClassField *field;
1449 MonoGenericContainer *container = NULL;
1450 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1453 * FIXME: We have a race condition here. It's possible that this function returns
1454 * to its caller with `instance_size` set to `0` instead of the actual size. This
1455 * is not a problem when the function is called recursively on the same class,
1456 * because the size will be initialized by the outer invocation. What follows is a
1457 * description of how it can occur in other cases, too. There it is a problem,
1458 * because it can lead to the GC being asked to allocate an object of size `0`,
1459 * which SGen chokes on. The race condition is triggered infrequently by
1460 * `tests/sgen-suspend.cs`.
1462 * This function is called for a class whenever one of its subclasses is inited.
1463 * For example, it's called for every subclass of Object. What it does is this:
1465 * if (class->setup_fields_called)
1468 * class->instance_size = 0;
1470 * class->setup_fields_called = 1;
1471 * ... critical point
1472 * class->instance_size = actual_instance_size;
1474 * The last two steps are sometimes reversed, but that only changes the way in which
1475 * the race condition works.
1477 * Assume thread A goes through this function and makes it to the critical point.
1478 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1479 * immediately, but `instance_size` is incorrect.
1481 * The other case looks like this:
1483 * if (class->setup_fields_called)
1485 * ... critical point X
1486 * class->instance_size = 0;
1487 * ... critical point Y
1488 * class->instance_size = actual_instance_size;
1490 * class->setup_fields_called = 1;
1492 * Assume thread A goes through the function and makes it to critical point X. Now
1493 * thread B runs through the whole of the function, returning, assuming
1494 * `instance_size` is set. At that point thread A gets to run and makes it to
1495 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1498 if (class->setup_fields_called)
1501 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1503 * This happens when a generic instance of an unfinished generic typebuilder
1504 * is used as an element type for creating an array type. We can't initialize
1505 * the fields of this class using the fields of gklass, since gklass is not
1506 * finished yet, fields could be added to it later.
1511 mono_class_setup_basic_field_info (class);
1512 top = class->field.count;
1515 mono_class_setup_fields (gtd);
1516 if (gtd->exception_type) {
1517 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1522 class->instance_size = 0;
1524 class->sizes.class_size = 0;
1526 if (class->parent) {
1527 /* For generic instances, class->parent might not have been initialized */
1528 mono_class_init (class->parent);
1529 if (!class->parent->size_inited) {
1530 mono_class_setup_fields (class->parent);
1531 if (class->parent->exception_type) {
1532 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1536 class->instance_size += class->parent->instance_size;
1537 class->min_align = class->parent->min_align;
1538 /* we use |= since it may have been set already */
1539 class->has_references |= class->parent->has_references;
1540 blittable = class->parent->blittable;
1542 class->instance_size = sizeof (MonoObject);
1543 class->min_align = 1;
1546 /* We can't really enable 16 bytes alignment until the GC supports it.
1547 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1548 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1549 Bug #506144 is an example of this issue.
1551 if (class->simd_type)
1552 class->min_align = 16;
1554 /* Get the real size */
1555 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1557 if (explicit_size) {
1558 if ((packing_size & 0xffffff00) != 0) {
1559 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1560 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1563 class->packing_size = packing_size;
1564 real_size += class->instance_size;
1568 if (explicit_size && real_size) {
1569 class->instance_size = MAX (real_size, class->instance_size);
1571 class->blittable = blittable;
1572 mono_memory_barrier ();
1573 class->size_inited = 1;
1574 class->fields_inited = 1;
1575 class->setup_fields_called = 1;
1579 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (class->image) && !strcmp (class->name_space, "System") && !strcmp (class->name, "ValueType")))
1582 /* Prevent infinite loops if the class references itself */
1583 class->setup_fields_called = 1;
1585 if (class->generic_container) {
1586 container = class->generic_container;
1588 container = gtd->generic_container;
1589 g_assert (container);
1593 * Fetch all the field information.
1595 for (i = 0; i < top; i++){
1596 int idx = class->field.first + i;
1597 field = &class->fields [i];
1599 field->parent = class;
1602 mono_field_resolve_type (field, &error);
1603 if (!mono_error_ok (&error)) {
1604 /*mono_field_resolve_type already failed class*/
1605 mono_error_cleanup (&error);
1609 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1610 g_assert (field->type);
1613 if (mono_field_is_deleted (field))
1616 MonoClassField *gfield = >d->fields [i];
1617 field->offset = gfield->offset;
1619 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1621 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1622 field->offset = offset;
1624 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1625 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1628 if (field->offset < -1) { /*-1 is used to encode special static fields */
1629 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1632 if (class->generic_container) {
1633 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1639 /* Only do these checks if we still think this type is blittable */
1640 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1641 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1644 MonoClass *field_class = mono_class_from_mono_type (field->type);
1646 mono_class_setup_fields (field_class);
1647 if (field_class->exception_type) {
1648 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1652 if (!field_class || !field_class->blittable)
1657 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1658 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1659 blittable = class->element_class->blittable;
1662 if (mono_type_has_exceptions (field->type)) {
1663 char *class_name = mono_type_get_full_name (class);
1664 char *type_name = mono_type_full_name (field->type);
1666 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1667 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1668 g_free (class_name);
1672 /* The def_value of fields is compute lazily during vtable creation */
1675 if (class == mono_defaults.string_class)
1678 class->blittable = blittable;
1680 if (class->enumtype && !mono_class_enum_basetype (class)) {
1681 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1684 if (explicit_size && real_size) {
1685 class->instance_size = MAX (real_size, class->instance_size);
1688 if (class->exception_type)
1690 mono_class_layout_fields (class);
1692 /*valuetypes can't be neither bigger than 1Mb or empty. */
1693 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1694 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1696 mono_memory_barrier ();
1697 class->fields_inited = 1;
1701 * mono_class_setup_fields_locking:
1702 * @class: The class to initialize
1704 * Initializes the class->fields array of fields.
1705 * Aquires the loader lock.
1708 mono_class_setup_fields_locking (MonoClass *class)
1710 /* This can be checked without locks */
1711 if (class->fields_inited)
1713 mono_loader_lock ();
1714 mono_class_setup_fields (class);
1715 mono_loader_unlock ();
1719 * mono_class_has_references:
1721 * Returns whenever @klass->has_references is set, initializing it if needed.
1722 * Aquires the loader lock.
1725 mono_class_has_references (MonoClass *klass)
1727 if (klass->init_pending) {
1728 /* Be conservative */
1731 mono_class_init (klass);
1733 return klass->has_references;
1738 * mono_type_get_basic_type_from_generic:
1741 * Returns a closed type corresponding to the possibly open type
1745 mono_type_get_basic_type_from_generic (MonoType *type)
1747 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1748 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1749 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1750 return &mono_defaults.object_class->byval_arg;
1755 type_has_references (MonoClass *klass, MonoType *ftype)
1757 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)))))
1759 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1760 MonoGenericParam *gparam = ftype->data.generic_param;
1762 if (gparam->gshared_constraint)
1763 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1769 * mono_class_layout_fields:
1772 * Compute the placement of fields inside an object or struct, according to
1773 * the layout rules and set the following fields in @class:
1774 * - has_references (if the class contains instance references firled or structs that contain references)
1775 * - has_static_refs (same, but for static fields)
1776 * - instance_size (size of the object in memory)
1777 * - class_size (size needed for the static fields)
1778 * - size_inited (flag set when the instance_size is set)
1780 * LOCKING: this is supposed to be called with the loader lock held.
1783 mono_class_layout_fields (MonoClass *class)
1786 const int top = class->field.count;
1787 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1788 guint32 pass, passes, real_size;
1789 gboolean gc_aware_layout = FALSE;
1790 gboolean has_static_fields = FALSE;
1791 MonoClassField *field;
1794 * When we do generic sharing we need to have layout
1795 * information for open generic classes (either with a generic
1796 * context containing type variables or with a generic
1797 * container), so we don't return in that case anymore.
1801 * Enable GC aware auto layout: in this mode, reference
1802 * fields are grouped together inside objects, increasing collector
1804 * Requires that all classes whose layout is known to native code be annotated
1805 * with [StructLayout (LayoutKind.Sequential)]
1806 * Value types have gc_aware_layout disabled by default, as per
1807 * what the default is for other runtimes.
1809 /* corlib is missing [StructLayout] directives in many places */
1810 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1811 if (!class->valuetype)
1812 gc_aware_layout = TRUE;
1815 /* Compute klass->has_references */
1817 * Process non-static fields first, since static fields might recursively
1818 * refer to the class itself.
1820 for (i = 0; i < top; i++) {
1823 field = &class->fields [i];
1825 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1826 ftype = mono_type_get_underlying_type (field->type);
1827 ftype = mono_type_get_basic_type_from_generic (ftype);
1828 if (type_has_references (class, ftype))
1829 class->has_references = TRUE;
1833 for (i = 0; i < top; i++) {
1836 field = &class->fields [i];
1838 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1839 ftype = mono_type_get_underlying_type (field->type);
1840 ftype = mono_type_get_basic_type_from_generic (ftype);
1841 if (type_has_references (class, ftype))
1842 class->has_static_refs = TRUE;
1846 for (i = 0; i < top; i++) {
1849 field = &class->fields [i];
1851 ftype = mono_type_get_underlying_type (field->type);
1852 ftype = mono_type_get_basic_type_from_generic (ftype);
1853 if (type_has_references (class, ftype)) {
1854 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1855 class->has_static_refs = TRUE;
1857 class->has_references = TRUE;
1862 * Compute field layout and total size (not considering static fields)
1866 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1867 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1869 if (gc_aware_layout)
1874 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1877 if (class->parent) {
1878 mono_class_setup_fields (class->parent);
1879 if (class->parent->exception_type) {
1880 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1883 real_size = class->parent->instance_size;
1885 real_size = sizeof (MonoObject);
1888 for (pass = 0; pass < passes; ++pass) {
1889 for (i = 0; i < top; i++){
1894 field = &class->fields [i];
1896 if (mono_field_is_deleted (field))
1898 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1901 ftype = mono_type_get_underlying_type (field->type);
1902 ftype = mono_type_get_basic_type_from_generic (ftype);
1903 if (gc_aware_layout) {
1904 if (type_has_references (class, ftype)) {
1913 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1914 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1915 /* This field is a hack inserted by MCS to empty structures */
1919 size = mono_type_size (field->type, &align);
1921 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1922 align = class->packing_size ? MIN (class->packing_size, align): align;
1923 /* if the field has managed references, we need to force-align it
1926 if (type_has_references (class, ftype))
1927 align = MAX (align, sizeof (gpointer));
1929 class->min_align = MAX (align, class->min_align);
1930 field->offset = real_size;
1932 field->offset += align - 1;
1933 field->offset &= ~(align - 1);
1935 /*TypeBuilders produce all sort of weird things*/
1936 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1937 real_size = field->offset + size;
1940 class->instance_size = MAX (real_size, class->instance_size);
1942 if (class->instance_size & (class->min_align - 1)) {
1943 class->instance_size += class->min_align - 1;
1944 class->instance_size &= ~(class->min_align - 1);
1948 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1952 for (i = 0; i < top; i++) {
1957 field = &class->fields [i];
1960 * There must be info about all the fields in a type if it
1961 * uses explicit layout.
1963 if (mono_field_is_deleted (field))
1965 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1968 size = mono_type_size (field->type, &align);
1969 align = class->packing_size ? MIN (class->packing_size, align): align;
1970 class->min_align = MAX (align, class->min_align);
1973 * When we get here, field->offset is already set by the
1974 * loader (for either runtime fields or fields loaded from metadata).
1975 * The offset is from the start of the object: this works for both
1976 * classes and valuetypes.
1978 field->offset += sizeof (MonoObject);
1979 ftype = mono_type_get_underlying_type (field->type);
1980 ftype = mono_type_get_basic_type_from_generic (ftype);
1981 if (type_has_references (class, ftype)) {
1982 if (field->offset % sizeof (gpointer)) {
1983 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1990 real_size = MAX (real_size, size + field->offset);
1993 if (class->has_references) {
1994 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1996 /* Check for overlapping reference and non-reference fields */
1997 for (i = 0; i < top; i++) {
2000 field = &class->fields [i];
2002 if (mono_field_is_deleted (field))
2004 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2006 ftype = mono_type_get_underlying_type (field->type);
2007 if (MONO_TYPE_IS_REFERENCE (ftype))
2008 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2010 for (i = 0; i < top; i++) {
2011 field = &class->fields [i];
2013 if (mono_field_is_deleted (field))
2015 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2018 // FIXME: Too much code does this
2020 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2021 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);
2022 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2026 g_free (ref_bitmap);
2029 class->instance_size = MAX (real_size, class->instance_size);
2030 if (class->instance_size & (class->min_align - 1)) {
2031 class->instance_size += class->min_align - 1;
2032 class->instance_size &= ~(class->min_align - 1);
2038 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2040 * This leads to all kinds of problems with nested structs, so only
2041 * enable it when a MONO_DEBUG property is set.
2043 * For small structs, set min_align to at least the struct size to improve
2044 * performance, and since the JIT memset/memcpy code assumes this and generates
2045 * unaligned accesses otherwise. See #78990 for a testcase.
2047 if (mono_align_small_structs) {
2048 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2049 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2053 mono_memory_barrier ();
2054 class->size_inited = 1;
2057 * Compute static field layout and size
2059 for (i = 0; i < top; i++){
2063 field = &class->fields [i];
2065 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2067 if (mono_field_is_deleted (field))
2070 if (mono_type_has_exceptions (field->type)) {
2071 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2075 has_static_fields = TRUE;
2077 size = mono_type_size (field->type, &align);
2078 field->offset = class->sizes.class_size;
2079 /*align is always non-zero here*/
2080 field->offset += align - 1;
2081 field->offset &= ~(align - 1);
2082 class->sizes.class_size = field->offset + size;
2085 if (has_static_fields && class->sizes.class_size == 0)
2086 /* Simplify code which depends on class_size != 0 if the class has static fields */
2087 class->sizes.class_size = 8;
2091 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2095 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2096 method->klass = class;
2097 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2098 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2099 method->signature = sig;
2100 method->name = name;
2103 if (name [0] == '.') {
2104 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2106 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2112 * mono_class_setup_methods:
2115 * Initializes the 'methods' array in CLASS.
2116 * Calling this method should be avoided if possible since it allocates a lot
2117 * of long-living MonoMethod structures.
2118 * Methods belonging to an interface are assigned a sequential slot starting
2121 * On failure this function sets class->exception_type
2124 mono_class_setup_methods (MonoClass *class)
2127 MonoMethod **methods;
2132 if (class->generic_class) {
2134 MonoClass *gklass = class->generic_class->container_class;
2136 mono_class_init (gklass);
2137 if (!gklass->exception_type)
2138 mono_class_setup_methods (gklass);
2139 if (gklass->exception_type) {
2140 /* FIXME make exception_data less opaque so it's possible to dup it here */
2141 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2145 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2146 count = gklass->method.count;
2147 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2149 for (i = 0; i < count; i++) {
2150 methods [i] = mono_class_inflate_generic_method_full_checked (
2151 gklass->methods [i], class, mono_class_get_context (class), &error);
2152 if (!mono_error_ok (&error)) {
2153 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2154 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)));
2157 mono_error_cleanup (&error);
2161 } else if (class->rank) {
2163 MonoMethod *amethod;
2164 MonoMethodSignature *sig;
2165 int count_generic = 0, first_generic = 0;
2167 gboolean jagged_ctor = FALSE;
2169 count = 3 + (class->rank > 1? 2: 1);
2171 mono_class_setup_interfaces (class, &error);
2172 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2174 if (class->rank == 1 && class->element_class->rank) {
2176 class->method.count ++;
2179 if (class->interface_count) {
2180 count_generic = generic_array_methods (class);
2181 first_generic = count;
2182 count += class->interface_count * count_generic;
2185 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2187 sig = mono_metadata_signature_alloc (class->image, class->rank);
2188 sig->ret = &mono_defaults.void_class->byval_arg;
2189 sig->pinvoke = TRUE;
2190 sig->hasthis = TRUE;
2191 for (i = 0; i < class->rank; ++i)
2192 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2194 amethod = create_array_method (class, ".ctor", sig);
2195 methods [method_num++] = amethod;
2196 if (class->rank > 1) {
2197 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2198 sig->ret = &mono_defaults.void_class->byval_arg;
2199 sig->pinvoke = TRUE;
2200 sig->hasthis = TRUE;
2201 for (i = 0; i < class->rank * 2; ++i)
2202 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2204 amethod = create_array_method (class, ".ctor", sig);
2205 methods [method_num++] = amethod;
2209 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2210 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2211 sig->ret = &mono_defaults.void_class->byval_arg;
2212 sig->pinvoke = TRUE;
2213 sig->hasthis = TRUE;
2214 for (i = 0; i < class->rank + 1; ++i)
2215 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2216 amethod = create_array_method (class, ".ctor", sig);
2217 methods [method_num++] = amethod;
2220 /* element Get (idx11, [idx2, ...]) */
2221 sig = mono_metadata_signature_alloc (class->image, class->rank);
2222 sig->ret = &class->element_class->byval_arg;
2223 sig->pinvoke = TRUE;
2224 sig->hasthis = TRUE;
2225 for (i = 0; i < class->rank; ++i)
2226 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2227 amethod = create_array_method (class, "Get", sig);
2228 methods [method_num++] = amethod;
2229 /* element& Address (idx11, [idx2, ...]) */
2230 sig = mono_metadata_signature_alloc (class->image, class->rank);
2231 sig->ret = &class->element_class->this_arg;
2232 sig->pinvoke = TRUE;
2233 sig->hasthis = TRUE;
2234 for (i = 0; i < class->rank; ++i)
2235 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2236 amethod = create_array_method (class, "Address", sig);
2237 methods [method_num++] = amethod;
2238 /* void Set (idx11, [idx2, ...], element) */
2239 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2240 sig->ret = &mono_defaults.void_class->byval_arg;
2241 sig->pinvoke = TRUE;
2242 sig->hasthis = TRUE;
2243 for (i = 0; i < class->rank; ++i)
2244 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2245 sig->params [i] = &class->element_class->byval_arg;
2246 amethod = create_array_method (class, "Set", sig);
2247 methods [method_num++] = amethod;
2249 for (i = 0; i < class->interface_count; i++)
2250 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2254 count = class->method.count;
2255 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2256 for (i = 0; i < count; ++i) {
2257 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2258 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2260 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)));
2261 mono_error_cleanup (&error);
2266 if (MONO_CLASS_IS_INTERFACE (class)) {
2268 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2269 for (i = 0; i < count; ++i) {
2270 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2271 methods [i]->slot = slot++;
2275 mono_image_lock (class->image);
2277 if (!class->methods) {
2278 class->method.count = count;
2280 /* Needed because of the double-checking locking pattern */
2281 mono_memory_barrier ();
2283 class->methods = methods;
2286 mono_image_unlock (class->image);
2290 * mono_class_get_method_by_index:
2292 * Returns class->methods [index], initializing class->methods if neccesary.
2294 * LOCKING: Acquires the loader lock.
2297 mono_class_get_method_by_index (MonoClass *class, int index)
2300 /* Avoid calling setup_methods () if possible */
2301 if (class->generic_class && !class->methods) {
2302 MonoClass *gklass = class->generic_class->container_class;
2305 m = mono_class_inflate_generic_method_full_checked (
2306 gklass->methods [index], class, mono_class_get_context (class), &error);
2307 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2309 * If setup_methods () is called later for this class, no duplicates are created,
2310 * since inflate_generic_method guarantees that only one instance of a method
2311 * is created for each context.
2314 mono_class_setup_methods (class);
2315 g_assert (m == class->methods [index]);
2319 mono_class_setup_methods (class);
2320 if (class->exception_type) /*FIXME do proper error handling*/
2322 g_assert (index >= 0 && index < class->method.count);
2323 return class->methods [index];
2328 * mono_class_get_inflated_method:
2330 * Given an inflated class CLASS and a method METHOD which should be a method of
2331 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2334 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2336 MonoClass *gklass = class->generic_class->container_class;
2339 g_assert (method->klass == gklass);
2341 mono_class_setup_methods (gklass);
2342 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2344 for (i = 0; i < gklass->method.count; ++i) {
2345 if (gklass->methods [i] == method) {
2346 if (class->methods) {
2347 return class->methods [i];
2350 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2351 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2361 * mono_class_get_vtable_entry:
2363 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2364 * LOCKING: Acquires the loader lock.
2367 mono_class_get_vtable_entry (MonoClass *class, int offset)
2371 if (class->rank == 1) {
2373 * szarrays do not overwrite any methods of Array, so we can avoid
2374 * initializing their vtables in some cases.
2376 mono_class_setup_vtable (class->parent);
2377 if (offset < class->parent->vtable_size)
2378 return class->parent->vtable [offset];
2381 if (class->generic_class) {
2383 MonoClass *gklass = class->generic_class->container_class;
2384 mono_class_setup_vtable (gklass);
2385 m = gklass->vtable [offset];
2387 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2388 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2390 mono_class_setup_vtable (class);
2391 if (class->exception_type)
2393 m = class->vtable [offset];
2400 * mono_class_get_vtable_size:
2402 * Return the vtable size for KLASS.
2405 mono_class_get_vtable_size (MonoClass *klass)
2407 mono_class_setup_vtable (klass);
2409 return klass->vtable_size;
2413 * mono_class_setup_properties:
2415 * Initialize class->ext.property and class->ext.properties.
2417 * This method can fail the class.
2420 mono_class_setup_properties (MonoClass *class)
2422 guint startm, endm, i, j;
2423 guint32 cols [MONO_PROPERTY_SIZE];
2424 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2425 MonoProperty *properties;
2429 if (class->ext && class->ext->properties)
2432 if (class->generic_class) {
2433 MonoClass *gklass = class->generic_class->container_class;
2435 mono_class_init (gklass);
2436 mono_class_setup_properties (gklass);
2437 if (gklass->exception_type) {
2438 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2442 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2444 for (i = 0; i < gklass->ext->property.count; i++) {
2446 MonoProperty *prop = &properties [i];
2448 *prop = gklass->ext->properties [i];
2451 prop->get = mono_class_inflate_generic_method_full_checked (
2452 prop->get, class, mono_class_get_context (class), &error);
2454 prop->set = mono_class_inflate_generic_method_full_checked (
2455 prop->set, class, mono_class_get_context (class), &error);
2457 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2458 prop->parent = class;
2461 first = gklass->ext->property.first;
2462 count = gklass->ext->property.count;
2464 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2465 count = last - first;
2468 mono_class_setup_methods (class);
2469 if (class->exception_type)
2473 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2474 for (i = first; i < last; ++i) {
2475 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2476 properties [i - first].parent = class;
2477 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2478 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2480 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2481 for (j = startm; j < endm; ++j) {
2484 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2486 if (class->image->uncompressed_metadata) {
2488 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2489 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2490 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2492 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2495 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2496 case METHOD_SEMANTIC_SETTER:
2497 properties [i - first].set = method;
2499 case METHOD_SEMANTIC_GETTER:
2500 properties [i - first].get = method;
2509 mono_class_alloc_ext (class);
2511 mono_image_lock (class->image);
2513 if (class->ext->properties) {
2514 /* We leak 'properties' which was allocated from the image mempool */
2515 mono_image_unlock (class->image);
2519 class->ext->property.first = first;
2520 class->ext->property.count = count;
2522 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2523 mono_memory_barrier ();
2525 /* Leave this assignment as the last op in the function */
2526 class->ext->properties = properties;
2528 mono_image_unlock (class->image);
2532 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2534 MonoMethod **om, **retval;
2537 for (om = methods, count = 0; *om; ++om, ++count)
2540 retval = g_new0 (MonoMethod*, count + 1);
2542 for (om = methods, count = 0; *om; ++om, ++count) {
2544 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2545 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2551 /*This method can fail the class.*/
2553 mono_class_setup_events (MonoClass *class)
2556 guint startm, endm, i, j;
2557 guint32 cols [MONO_EVENT_SIZE];
2558 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2562 if (class->ext && class->ext->events)
2565 if (class->generic_class) {
2566 MonoClass *gklass = class->generic_class->container_class;
2567 MonoGenericContext *context = NULL;
2569 mono_class_setup_events (gklass);
2570 if (gklass->exception_type) {
2571 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2575 first = gklass->ext->event.first;
2576 count = gklass->ext->event.count;
2578 events = mono_class_new0 (class, MonoEvent, count);
2581 context = mono_class_get_context (class);
2583 for (i = 0; i < count; i++) {
2585 MonoEvent *event = &events [i];
2586 MonoEvent *gevent = &gklass->ext->events [i];
2588 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2590 event->parent = class;
2591 event->name = gevent->name;
2592 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2593 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2594 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2595 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2596 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2597 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2599 #ifndef MONO_SMALL_CONFIG
2600 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2602 event->attrs = gevent->attrs;
2605 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2606 count = last - first;
2609 mono_class_setup_methods (class);
2610 if (class->exception_type) {
2611 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2616 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2617 for (i = first; i < last; ++i) {
2618 MonoEvent *event = &events [i - first];
2620 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2621 event->parent = class;
2622 event->attrs = cols [MONO_EVENT_FLAGS];
2623 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2625 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2626 for (j = startm; j < endm; ++j) {
2629 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2631 if (class->image->uncompressed_metadata) {
2633 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2634 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2635 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2637 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2640 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2641 case METHOD_SEMANTIC_ADD_ON:
2642 event->add = method;
2644 case METHOD_SEMANTIC_REMOVE_ON:
2645 event->remove = method;
2647 case METHOD_SEMANTIC_FIRE:
2648 event->raise = method;
2650 case METHOD_SEMANTIC_OTHER: {
2651 #ifndef MONO_SMALL_CONFIG
2654 if (event->other == NULL) {
2655 event->other = g_new0 (MonoMethod*, 2);
2657 while (event->other [n])
2659 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2661 event->other [n] = method;
2662 /* NULL terminated */
2663 event->other [n + 1] = NULL;
2674 mono_class_alloc_ext (class);
2676 mono_image_lock (class->image);
2678 if (class->ext->events) {
2679 mono_image_unlock (class->image);
2683 class->ext->event.first = first;
2684 class->ext->event.count = count;
2686 /* Flush any pending writes as we do double checked locking on class->ext.events */
2687 mono_memory_barrier ();
2689 /* Leave this assignment as the last op in the function */
2690 class->ext->events = events;
2692 mono_image_unlock (class->image);
2696 * Global pool of interface IDs, represented as a bitset.
2697 * LOCKING: Protected by the classes lock.
2699 static MonoBitSet *global_interface_bitset = NULL;
2702 * mono_unload_interface_ids:
2703 * @bitset: bit set of interface IDs
2705 * When an image is unloaded, the interface IDs associated with
2706 * the image are put back in the global pool of IDs so the numbers
2710 mono_unload_interface_ids (MonoBitSet *bitset)
2713 mono_bitset_sub (global_interface_bitset, bitset);
2718 mono_unload_interface_id (MonoClass *class)
2720 if (global_interface_bitset && class->interface_id) {
2722 mono_bitset_clear (global_interface_bitset, class->interface_id);
2728 * mono_get_unique_iid:
2731 * Assign a unique integer ID to the interface represented by @class.
2732 * The ID will positive and as small as possible.
2733 * LOCKING: Acquires the classes lock.
2734 * Returns: the new ID.
2737 mono_get_unique_iid (MonoClass *class)
2741 g_assert (MONO_CLASS_IS_INTERFACE (class));
2745 if (!global_interface_bitset) {
2746 global_interface_bitset = mono_bitset_new (128, 0);
2749 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2751 int old_size = mono_bitset_size (global_interface_bitset);
2752 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2753 mono_bitset_free (global_interface_bitset);
2754 global_interface_bitset = new_set;
2757 mono_bitset_set (global_interface_bitset, iid);
2758 /* set the bit also in the per-image set */
2759 if (!class->generic_class) {
2760 if (class->image->interface_bitset) {
2761 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2762 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2763 mono_bitset_free (class->image->interface_bitset);
2764 class->image->interface_bitset = new_set;
2767 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2769 mono_bitset_set (class->image->interface_bitset, iid);
2774 #ifndef MONO_SMALL_CONFIG
2775 if (mono_print_vtable) {
2777 char *type_name = mono_type_full_name (&class->byval_arg);
2778 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2779 generic_id = class->generic_class->context.class_inst->id;
2780 g_assert (generic_id != 0);
2784 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2789 g_assert (iid <= 65535);
2794 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2799 mono_class_setup_interfaces (klass, error);
2800 if (!mono_error_ok (error))
2803 for (i = 0; i < klass->interface_count; i++) {
2804 ic = klass->interfaces [i];
2807 *res = g_ptr_array_new ();
2808 g_ptr_array_add (*res, ic);
2809 mono_class_init (ic);
2810 if (ic->exception_type) {
2811 mono_error_set_type_load_class (error, ic, "Error Loading class");
2815 collect_implemented_interfaces_aux (ic, res, error);
2816 if (!mono_error_ok (error))
2822 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2824 GPtrArray *res = NULL;
2826 collect_implemented_interfaces_aux (klass, &res, error);
2827 if (!mono_error_ok (error)) {
2829 g_ptr_array_free (res, TRUE);
2836 compare_interface_ids (const void *p_key, const void *p_element) {
2837 const MonoClass *key = p_key;
2838 const MonoClass *element = *(MonoClass**) p_element;
2840 return (key->interface_id - element->interface_id);
2843 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2845 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2846 MonoClass **result = mono_binary_search (
2848 klass->interfaces_packed,
2849 klass->interface_offsets_count,
2850 sizeof (MonoClass *),
2851 compare_interface_ids);
2853 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2860 * mono_class_interface_offset_with_variance:
2862 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2863 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2865 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2867 * FIXME figure out MS disambiguation rules and fix this function.
2870 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2871 int i = mono_class_interface_offset (klass, itf);
2872 *non_exact_match = FALSE;
2876 if (!mono_class_has_variant_generic_params (itf))
2879 for (i = 0; i < klass->interface_offsets_count; i++) {
2880 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2881 *non_exact_match = TRUE;
2882 return klass->interface_offsets_packed [i];
2890 print_implemented_interfaces (MonoClass *klass) {
2893 GPtrArray *ifaces = NULL;
2895 int ancestor_level = 0;
2897 name = mono_type_get_full_name (klass);
2898 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2901 for (i = 0; i < klass->interface_offsets_count; i++)
2902 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2903 klass->interfaces_packed [i]->interface_id,
2904 klass->interface_offsets_packed [i],
2905 klass->interfaces_packed [i]->method.count,
2906 klass->interfaces_packed [i]->name_space,
2907 klass->interfaces_packed [i]->name );
2908 printf ("Interface flags: ");
2909 for (i = 0; i <= klass->max_interface_id; i++)
2910 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2911 printf ("(%d,T)", i);
2913 printf ("(%d,F)", i);
2915 printf ("Dump interface flags:");
2916 #ifdef COMPRESSED_INTERFACE_BITMAP
2918 const uint8_t* p = klass->interface_bitmap;
2919 i = klass->max_interface_id;
2921 printf (" %d x 00 %02X", p [0], p [1]);
2927 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2928 printf (" %02X", klass->interface_bitmap [i]);
2931 while (klass != NULL) {
2932 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2933 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2934 if (!mono_error_ok (&error)) {
2935 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2936 mono_error_cleanup (&error);
2937 } else if (ifaces) {
2938 for (i = 0; i < ifaces->len; i++) {
2939 MonoClass *ic = g_ptr_array_index (ifaces, i);
2940 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2941 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2943 mono_class_interface_offset (klass, ic),
2948 g_ptr_array_free (ifaces, TRUE);
2951 klass = klass->parent;
2956 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2959 args [0] = &arg0->byval_arg;
2961 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2965 array_class_get_if_rank (MonoClass *class, guint rank)
2967 return rank ? mono_array_class_get (class, rank) : class;
2971 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2973 valuetype_types [0] = eclass;
2974 if (eclass == mono_defaults.int16_class)
2975 valuetype_types [1] = mono_defaults.uint16_class;
2976 else if (eclass == mono_defaults.uint16_class)
2977 valuetype_types [1] = mono_defaults.int16_class;
2978 else if (eclass == mono_defaults.int32_class)
2979 valuetype_types [1] = mono_defaults.uint32_class;
2980 else if (eclass == mono_defaults.uint32_class)
2981 valuetype_types [1] = mono_defaults.int32_class;
2982 else if (eclass == mono_defaults.int64_class)
2983 valuetype_types [1] = mono_defaults.uint64_class;
2984 else if (eclass == mono_defaults.uint64_class)
2985 valuetype_types [1] = mono_defaults.int64_class;
2986 else if (eclass == mono_defaults.byte_class)
2987 valuetype_types [1] = mono_defaults.sbyte_class;
2988 else if (eclass == mono_defaults.sbyte_class)
2989 valuetype_types [1] = mono_defaults.byte_class;
2990 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2991 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2994 /* this won't be needed once bug #325495 is completely fixed
2995 * though we'll need something similar to know which interfaces to allow
2996 * in arrays when they'll be lazyly created
2998 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2999 * MS returns diferrent types based on which instance is called. For example:
3000 * object obj = new byte[10][];
3001 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3002 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3005 * Fixing this should kill quite some code, save some bits and improve compatibility.
3008 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3010 MonoClass *eclass = class->element_class;
3011 static MonoClass* generic_icollection_class = NULL;
3012 static MonoClass* generic_ienumerable_class = NULL;
3013 static MonoClass* generic_ienumerator_class = NULL;
3014 static MonoClass* generic_ireadonlylist_class = NULL;
3015 static MonoClass* generic_ireadonlycollection_class = NULL;
3016 MonoClass *valuetype_types[2] = { NULL, NULL };
3017 MonoClass **interfaces = NULL;
3018 int i, nifaces, interface_count, real_count, original_rank;
3020 gboolean internal_enumerator;
3021 gboolean eclass_is_valuetype;
3023 if (!mono_defaults.generic_ilist_class) {
3027 internal_enumerator = FALSE;
3028 eclass_is_valuetype = FALSE;
3029 original_rank = eclass->rank;
3030 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3031 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3033 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3035 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3036 original_rank = eclass->rank;
3038 eclass = eclass->element_class;
3039 internal_enumerator = TRUE;
3040 *is_enumerator = TRUE;
3048 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3049 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3051 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3053 if (!generic_icollection_class) {
3054 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3055 "System.Collections.Generic", "ICollection`1");
3056 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3057 "System.Collections.Generic", "IEnumerable`1");
3058 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3059 "System.Collections.Generic", "IEnumerator`1");
3060 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3061 "System.Collections.Generic", "IReadOnlyList`1");
3062 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3063 "System.Collections.Generic", "IReadOnlyCollection`1");
3066 mono_class_init (eclass);
3069 * Arrays in 2.0 need to implement a number of generic interfaces
3070 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3071 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3072 * We collect the types needed to build the
3073 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3074 * the generic interfaces needed to implement.
3076 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3077 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3079 if (eclass->valuetype) {
3080 nifaces = generic_ireadonlylist_class ? 5 : 3;
3081 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3083 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3084 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3085 if (internal_enumerator) {
3087 if (valuetype_types [1])
3091 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3092 interfaces [0] = valuetype_types [0];
3093 if (valuetype_types [1])
3094 interfaces [nifaces] = valuetype_types [1];
3096 eclass_is_valuetype = TRUE;
3099 int idepth = eclass->idepth;
3100 if (!internal_enumerator)
3102 nifaces = generic_ireadonlylist_class ? 2 : 3;
3104 // FIXME: This doesn't seem to work/required for generic params
3105 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3106 mono_class_setup_interface_offsets (eclass);
3108 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3109 /* we add object for interfaces and the supertypes for the other
3110 * types. The last of the supertypes is the element class itself which we
3111 * already created the explicit interfaces for (so we include it for IEnumerator
3112 * and exclude it for arrays).
3114 if (MONO_CLASS_IS_INTERFACE (eclass))
3117 interface_count += idepth;
3118 if (eclass->rank && eclass->element_class->valuetype) {
3119 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3120 if (valuetype_types [1])
3123 /* IList, ICollection, IEnumerable, IReadOnlyList */
3124 interface_count *= nifaces;
3125 real_count = interface_count;
3126 if (internal_enumerator) {
3127 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3128 if (valuetype_types [1])
3131 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3132 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3133 interfaces [0] = mono_defaults.object_class;
3137 for (i = 0; i < idepth; i++) {
3138 mono_class_init (eclass->supertypes [i]);
3139 interfaces [j] = eclass->supertypes [i];
3143 if (all_interfaces) {
3144 for (i = 0; i < eclass->interface_offsets_count; i++) {
3145 interfaces [j] = eclass->interfaces_packed [i];
3149 for (i = 0; i < eclass->interface_count; i++) {
3150 interfaces [j] = eclass->interfaces [i];
3154 if (valuetype_types [1]) {
3155 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3160 /* instantiate the generic interfaces */
3161 for (i = 0; i < interface_count; i += nifaces) {
3162 MonoClass *iface = interfaces [i];
3164 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3165 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3167 if (eclass->valuetype) {
3168 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3169 if (generic_ireadonlylist_class) {
3170 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3171 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3174 if (!generic_ireadonlylist_class)
3175 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3178 if (internal_enumerator) {
3180 /* instantiate IEnumerator<iface> */
3181 for (i = 0; i < interface_count; i++) {
3182 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3184 j = interface_count;
3185 if (!eclass_is_valuetype) {
3186 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3187 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3190 for (i = 0; i < eclass->idepth; i++) {
3191 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3195 for (i = 0; i < eclass->interface_offsets_count; i++) {
3196 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3200 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3202 if (valuetype_types [1])
3203 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3207 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3208 for (i = 0; i < real_count; ++i) {
3209 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3210 g_print ("%s implements %s\n", type_name, name);
3221 find_array_interface (MonoClass *klass, const char *name)
3224 for (i = 0; i < klass->interface_count; ++i) {
3225 if (strcmp (klass->interfaces [i]->name, name) == 0)
3232 * Return the number of virtual methods.
3233 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3234 * Return -1 on failure.
3235 * FIXME It would be nice if this information could be cached somewhere.
3238 count_virtual_methods (MonoClass *class)
3242 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3244 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3245 mono_class_setup_methods (class);
3246 if (class->exception_type)
3249 for (i = 0; i < class->method.count; ++i) {
3250 flags = class->methods [i]->flags;
3251 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3255 for (i = 0; i < class->method.count; ++i) {
3256 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3258 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3266 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3274 m = (l + num_ifaces) / 2;
3275 if (interfaces_full [m] == ic)
3277 if (l == num_ifaces)
3279 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3288 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3290 int i = find_interface (num_ifaces, interfaces_full, ic);
3292 return interface_offsets_full [i];
3297 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3299 int i = find_interface (num_ifaces, interfaces_full, ic);
3303 interface_offsets_full [i] = offset;
3306 for (i = 0; i < num_ifaces; ++i) {
3307 if (interfaces_full [i]) {
3309 if (interfaces_full [i]->interface_id < ic->interface_id)
3312 while (end < num_ifaces && interfaces_full [end]) end++;
3313 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3314 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3316 interfaces_full [i] = ic;
3317 interface_offsets_full [i] = offset;
3323 #ifdef COMPRESSED_INTERFACE_BITMAP
3326 * Compressed interface bitmap design.
3328 * Interface bitmaps take a large amount of memory, because their size is
3329 * linear with the maximum interface id assigned in the process (each interface
3330 * is assigned a unique id as it is loaded). The number of interface classes
3331 * is high because of the many implicit interfaces implemented by arrays (we'll
3332 * need to lazy-load them in the future).
3333 * Most classes implement a very small number of interfaces, so the bitmap is
3334 * sparse. This bitmap needs to be checked by interface casts, so access to the
3335 * needed bit must be fast and doable with few jit instructions.
3337 * The current compression format is as follows:
3338 * *) it is a sequence of one or more two-byte elements
3339 * *) the first byte in the element is the count of empty bitmap bytes
3340 * at the current bitmap position
3341 * *) the second byte in the element is an actual bitmap byte at the current
3344 * As an example, the following compressed bitmap bytes:
3345 * 0x07 0x01 0x00 0x7
3346 * correspond to the following bitmap:
3347 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3349 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3350 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3351 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3355 * mono_compress_bitmap:
3356 * @dest: destination buffer
3357 * @bitmap: bitmap buffer
3358 * @size: size of @bitmap in bytes
3360 * This is a mono internal function.
3361 * The @bitmap data is compressed into a format that is small but
3362 * still searchable in few instructions by the JIT and runtime.
3363 * The compressed data is stored in the buffer pointed to by the
3364 * @dest array. Passing a #NULL value for @dest allows to just compute
3365 * the size of the buffer.
3366 * This compression algorithm assumes the bits set in the bitmap are
3367 * few and far between, like in interface bitmaps.
3368 * Returns: the size of the compressed bitmap in bytes.
3371 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3375 const uint8_t *end = bitmap + size;
3376 while (bitmap < end) {
3377 if (*bitmap || numz == 255) {
3401 * mono_class_interface_match:
3402 * @bitmap: a compressed bitmap buffer
3403 * @id: the index to check in the bitmap
3405 * This is a mono internal function.
3406 * Checks if a bit is set in a compressed interface bitmap. @id must
3407 * be already checked for being smaller than the maximum id encoded in the
3410 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3414 mono_class_interface_match (const uint8_t *bitmap, int id)
3417 id -= bitmap [0] * 8;
3421 return bitmap [1] & (1 << id);
3430 * LOCKING: this is supposed to be called with the loader lock held.
3431 * Return -1 on failure and set exception_type
3434 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3438 int i, j, max_iid, num_ifaces;
3439 MonoClass **interfaces_full = NULL;
3440 int *interface_offsets_full = NULL;
3442 GPtrArray **ifaces_array = NULL;
3443 int interface_offsets_count;
3444 MonoClass **array_interfaces = NULL;
3445 int num_array_interfaces;
3446 int is_enumerator = FALSE;
3448 mono_class_setup_supertypes (class);
3450 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3451 * implicit interfaces have the property that they are assigned the same slot in the
3452 * vtables for compatible interfaces
3454 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3456 /* compute maximum number of slots and maximum interface id */
3458 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3459 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3460 for (j = 0; j < class->idepth; j++) {
3461 k = class->supertypes [j];
3462 num_ifaces += k->interface_count;
3463 for (i = 0; i < k->interface_count; i++) {
3464 ic = k->interfaces [i];
3467 mono_class_init (ic);
3469 if (max_iid < ic->interface_id)
3470 max_iid = ic->interface_id;
3472 ifaces = mono_class_get_implemented_interfaces (k, &error);
3473 if (!mono_error_ok (&error)) {
3474 char *name = mono_type_get_full_name (k);
3475 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)));
3477 mono_error_cleanup (&error);
3482 num_ifaces += ifaces->len;
3483 for (i = 0; i < ifaces->len; ++i) {
3484 ic = g_ptr_array_index (ifaces, i);
3485 if (max_iid < ic->interface_id)
3486 max_iid = ic->interface_id;
3488 ifaces_array [j] = ifaces;
3492 for (i = 0; i < num_array_interfaces; ++i) {
3493 ic = array_interfaces [i];
3494 mono_class_init (ic);
3495 if (max_iid < ic->interface_id)
3496 max_iid = ic->interface_id;
3499 if (MONO_CLASS_IS_INTERFACE (class)) {
3501 if (max_iid < class->interface_id)
3502 max_iid = class->interface_id;
3504 class->max_interface_id = max_iid;
3505 /* compute vtable offset for interfaces */
3506 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3507 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3509 for (i = 0; i < num_ifaces; i++) {
3510 interface_offsets_full [i] = -1;
3513 /* skip the current class */
3514 for (j = 0; j < class->idepth - 1; j++) {
3515 k = class->supertypes [j];
3516 ifaces = ifaces_array [j];
3519 for (i = 0; i < ifaces->len; ++i) {
3521 ic = g_ptr_array_index (ifaces, i);
3523 /*Force the sharing of interface offsets between parent and subtypes.*/
3524 io = mono_class_interface_offset (k, ic);
3526 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3531 g_assert (class == class->supertypes [class->idepth - 1]);
3532 ifaces = ifaces_array [class->idepth - 1];
3534 for (i = 0; i < ifaces->len; ++i) {
3536 ic = g_ptr_array_index (ifaces, i);
3537 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3539 count = count_virtual_methods (ic);
3541 char *name = mono_type_get_full_name (ic);
3542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3551 if (MONO_CLASS_IS_INTERFACE (class))
3552 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3554 if (num_array_interfaces) {
3555 if (is_enumerator) {
3556 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3557 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3558 g_assert (ienumerator_offset >= 0);
3559 for (i = 0; i < num_array_interfaces; ++i) {
3560 ic = array_interfaces [i];
3561 if (strcmp (ic->name, "IEnumerator`1") == 0)
3562 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3564 g_assert_not_reached ();
3565 /*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);*/
3568 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3569 int ilist_iface_idx = find_array_interface (class, "IList`1");
3570 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3571 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3572 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3573 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3574 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3575 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3576 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3577 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3578 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3579 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3580 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3581 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3582 for (i = 0; i < num_array_interfaces; ++i) {
3584 ic = array_interfaces [i];
3585 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3586 offset = ilist_offset;
3587 else if (strcmp (ic->name, "ICollection`1") == 0)
3588 offset = icollection_offset;
3589 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3590 offset = ienumerable_offset;
3591 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3592 offset = ireadonlylist_offset;
3593 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3594 offset = ireadonlycollection_offset;
3596 g_assert_not_reached ();
3597 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3598 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3603 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3604 if (interface_offsets_full [i] != -1) {
3605 interface_offsets_count ++;
3610 * We might get called multiple times:
3611 * - mono_class_init ()
3612 * - mono_class_setup_vtable ().
3613 * - mono_class_setup_interface_offsets ().
3614 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3615 * means we have to overwrite those when called from other places (#4440).
3617 if (class->interfaces_packed) {
3619 g_assert (class->interface_offsets_count == interface_offsets_count);
3623 class->interface_offsets_count = interface_offsets_count;
3624 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3625 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3626 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3627 #ifdef COMPRESSED_INTERFACE_BITMAP
3628 bitmap = g_malloc0 (bsize);
3630 bitmap = mono_class_alloc0 (class, bsize);
3632 for (i = 0; i < interface_offsets_count; i++) {
3633 int id = interfaces_full [i]->interface_id;
3634 bitmap [id >> 3] |= (1 << (id & 7));
3635 class->interfaces_packed [i] = interfaces_full [i];
3636 class->interface_offsets_packed [i] = interface_offsets_full [i];
3637 /*if (num_array_interfaces)
3638 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]);*/
3640 #ifdef COMPRESSED_INTERFACE_BITMAP
3641 i = mono_compress_bitmap (NULL, bitmap, bsize);
3642 class->interface_bitmap = mono_class_alloc0 (class, i);
3643 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3646 class->interface_bitmap = bitmap;
3651 g_free (interfaces_full);
3652 g_free (interface_offsets_full);
3653 g_free (array_interfaces);
3654 for (i = 0; i < class->idepth; i++) {
3655 ifaces = ifaces_array [i];
3657 g_ptr_array_free (ifaces, TRUE);
3659 g_free (ifaces_array);
3661 //printf ("JUST DONE: ");
3662 //print_implemented_interfaces (class);
3668 * Setup interface offsets for interfaces.
3670 * - class->max_interface_id
3671 * - class->interface_offsets_count
3672 * - class->interfaces_packed
3673 * - class->interface_offsets_packed
3674 * - class->interface_bitmap
3676 * This function can fail @class.
3679 mono_class_setup_interface_offsets (MonoClass *class)
3681 mono_loader_lock ();
3683 setup_interface_offsets (class, 0, FALSE);
3685 mono_loader_unlock ();
3688 /*Checks if @klass has @parent as one of it's parents type gtd
3692 * Bar<T> : Foo<Bar<Bar<T>>>
3696 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3698 klass = mono_class_get_generic_type_definition (klass);
3699 parent = mono_class_get_generic_type_definition (parent);
3700 mono_class_setup_supertypes (klass);
3701 mono_class_setup_supertypes (parent);
3703 return klass->idepth >= parent->idepth &&
3704 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3708 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3710 MonoGenericInst *ginst;
3712 if (!class->generic_class) {
3713 mono_class_setup_vtable_full (class, in_setup);
3714 return class->exception_type == 0;
3717 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3718 if (class->generic_class->container_class->exception_type) {
3719 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3723 ginst = class->generic_class->context.class_inst;
3724 for (i = 0; i < ginst->type_argc; ++i) {
3726 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3728 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3729 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3730 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3732 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3733 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3741 * mono_class_setup_vtable:
3743 * Creates the generic vtable of CLASS.
3744 * Initializes the following fields in MonoClass:
3747 * Plus all the fields initialized by setup_interface_offsets ().
3748 * If there is an error during vtable construction, class->exception_type is set.
3750 * LOCKING: Acquires the loader lock.
3753 mono_class_setup_vtable (MonoClass *class)
3755 mono_class_setup_vtable_full (class, NULL);
3759 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3761 MonoMethod **overrides;
3762 MonoGenericContext *context;
3770 if (MONO_CLASS_IS_INTERFACE (class)) {
3771 /* This sets method->slot for all methods if this is an interface */
3772 mono_class_setup_methods (class);
3776 if (class->exception_type)
3779 if (g_list_find (in_setup, class))
3782 mono_loader_lock ();
3784 if (class->vtable) {
3785 mono_loader_unlock ();
3789 mono_stats.generic_vtable_count ++;
3790 in_setup = g_list_prepend (in_setup, class);
3792 if (class->generic_class) {
3793 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3794 mono_loader_unlock ();
3795 g_list_remove (in_setup, class);
3799 context = mono_class_get_context (class);
3800 type_token = class->generic_class->container_class->type_token;
3802 context = (MonoGenericContext *) class->generic_container;
3803 type_token = class->type_token;
3806 if (image_is_dynamic (class->image)) {
3807 /* Generic instances can have zero method overrides without causing any harm.
3808 * This is true since we don't do layout all over again for them, we simply inflate
3809 * the layout of the parent.
3811 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3813 /* The following call fails if there are missing methods in the type */
3814 /* FIXME it's probably a good idea to avoid this for generic instances. */
3815 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3819 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3821 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3825 mono_loader_unlock ();
3826 g_list_remove (in_setup, class);
3831 #define DEBUG_INTERFACE_VTABLE_CODE 0
3832 #define TRACE_INTERFACE_VTABLE_CODE 0
3833 #define VERIFY_INTERFACE_VTABLE_CODE 0
3834 #define VTABLE_SELECTOR (1)
3836 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3837 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3838 if (!(VTABLE_SELECTOR)) break; \
3842 #define DEBUG_INTERFACE_VTABLE(stmt)
3845 #if TRACE_INTERFACE_VTABLE_CODE
3846 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3847 if (!(VTABLE_SELECTOR)) break; \
3851 #define TRACE_INTERFACE_VTABLE(stmt)
3854 #if VERIFY_INTERFACE_VTABLE_CODE
3855 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3856 if (!(VTABLE_SELECTOR)) break; \
3860 #define VERIFY_INTERFACE_VTABLE(stmt)
3864 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3866 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3870 GString *res = g_string_new ("");
3872 g_string_append_c (res, '(');
3873 for (i = 0; i < sig->param_count; ++i) {
3875 g_string_append_c (res, ',');
3876 mono_type_get_desc (res, sig->params [i], include_namespace);
3878 g_string_append (res, ")=>");
3879 if (sig->ret != NULL) {
3880 mono_type_get_desc (res, sig->ret, include_namespace);
3882 g_string_append (res, "NULL");
3885 g_string_free (res, FALSE);
3889 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3890 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3891 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3892 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3900 is_wcf_hack_disabled (void)
3902 static gboolean disabled;
3903 static gboolean inited = FALSE;
3905 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3912 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3914 MonoMethodSignature *cmsig, *imsig;
3915 if (strcmp (im->name, cm->name) == 0) {
3916 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3917 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3920 if (! slot_is_empty) {
3921 if (require_newslot) {
3922 if (! interface_is_explicitly_implemented_by_class) {
3923 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3926 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3927 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3931 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3934 cmsig = mono_method_signature (cm);
3935 imsig = mono_method_signature (im);
3936 if (!cmsig || !imsig) {
3937 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3941 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3942 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3943 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3944 TRACE_INTERFACE_VTABLE (printf ("]"));
3947 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3948 if (mono_security_core_clr_enabled ())
3949 mono_security_core_clr_check_override (class, cm, im);
3951 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3952 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3953 char *body_name = mono_method_full_name (cm, TRUE);
3954 char *decl_name = mono_method_full_name (im, TRUE);
3955 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));
3963 MonoClass *ic = im->klass;
3964 const char *ic_name_space = ic->name_space;
3965 const char *ic_name = ic->name;
3968 if (! require_newslot) {
3969 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3972 if (cm->klass->rank == 0) {
3973 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3976 cmsig = mono_method_signature (cm);
3977 imsig = mono_method_signature (im);
3978 if (!cmsig || !imsig) {
3979 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3983 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3984 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3985 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3986 TRACE_INTERFACE_VTABLE (printf ("]"));
3989 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3990 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3993 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3994 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3997 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))) {
3998 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4002 subname = strstr (cm->name, ic_name_space);
4003 if (subname != cm->name) {
4004 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4007 subname += strlen (ic_name_space);
4008 if (subname [0] != '.') {
4009 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4013 if (strstr (subname, ic_name) != subname) {
4014 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4017 subname += strlen (ic_name);
4018 if (subname [0] != '.') {
4019 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4023 if (strcmp (subname, im->name) != 0) {
4024 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4028 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4029 if (mono_security_core_clr_enabled ())
4030 mono_security_core_clr_check_override (class, cm, im);
4032 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4033 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4034 char *body_name = mono_method_full_name (cm, TRUE);
4035 char *decl_name = mono_method_full_name (im, TRUE);
4036 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));
4046 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4048 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4049 MonoMethod *method = key;
4050 MonoMethod *override = value;
4051 MonoClass *method_class = mono_method_get_class (method);
4052 MonoClass *override_class = mono_method_get_class (override);
4054 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4055 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4056 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4059 print_overrides (GHashTable *override_map, const char *message) {
4061 printf ("Override map \"%s\" START:\n", message);
4062 g_hash_table_foreach (override_map, foreach_override, NULL);
4063 printf ("Override map \"%s\" END.\n", message);
4065 printf ("Override map \"%s\" EMPTY.\n", message);
4069 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4070 char *full_name = mono_type_full_name (&class->byval_arg);
4074 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4076 if (print_interfaces) {
4077 print_implemented_interfaces (class);
4078 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4081 if (class->parent) {
4082 parent_size = class->parent->vtable_size;
4086 for (i = 0; i < size; ++i) {
4087 MonoMethod *cm = vtable [i];
4088 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4089 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4091 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4099 #if VERIFY_INTERFACE_VTABLE_CODE
4101 mono_method_try_get_vtable_index (MonoMethod *method)
4103 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4104 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4105 if (imethod->declaring->is_generic)
4106 return imethod->declaring->slot;
4108 return method->slot;
4112 mono_class_verify_vtable (MonoClass *class)
4115 char *full_name = mono_type_full_name (&class->byval_arg);
4117 printf ("*** Verifying VTable of class '%s' \n", full_name);
4121 if (!class->methods)
4124 for (i = 0; i < class->method.count; ++i) {
4125 MonoMethod *cm = class->methods [i];
4128 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4132 full_name = mono_method_full_name (cm, TRUE);
4134 slot = mono_method_try_get_vtable_index (cm);
4136 if (slot >= class->vtable_size) {
4137 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4141 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4142 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4143 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4144 g_free (other_name);
4147 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4154 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4156 char *method_signature;
4159 for (index = 0; index < onum; ++index) {
4160 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4161 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4163 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4164 type_name = mono_type_full_name (&class->byval_arg);
4165 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4166 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4167 g_free (method_signature);
4169 mono_class_setup_methods (class);
4170 if (class->exception_type) {
4171 char *name = mono_type_get_full_name (class);
4172 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4176 for (index = 0; index < class->method.count; ++index) {
4177 MonoMethod *cm = class->methods [index];
4178 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4180 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4181 g_free (method_signature);
4186 mono_method_get_method_definition (MonoMethod *method)
4188 while (method->is_inflated)
4189 method = ((MonoMethodInflated*)method)->declaring;
4194 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4198 for (i = 0; i < onum; ++i) {
4199 MonoMethod *decl = overrides [i * 2];
4200 MonoMethod *body = overrides [i * 2 + 1];
4202 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4203 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4207 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4208 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4209 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4211 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4215 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4216 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4217 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4219 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4223 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4224 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4228 body = mono_method_get_method_definition (body);
4229 decl = mono_method_get_method_definition (decl);
4231 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4232 char *body_name = mono_method_full_name (body, TRUE);
4233 char *decl_name = mono_method_full_name (decl, TRUE);
4234 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));
4244 mono_class_need_stelemref_method (MonoClass *class)
4246 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4250 * LOCKING: this is supposed to be called with the loader lock held.
4253 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4257 MonoMethod **vtable;
4258 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4259 GPtrArray *ifaces = NULL;
4260 GHashTable *override_map = NULL;
4262 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4263 int first_non_interface_slot;
4265 GSList *virt_methods = NULL, *l;
4266 int stelemref_slot = 0;
4271 if (overrides && !verify_class_overrides (class, overrides, onum))
4274 ifaces = mono_class_get_implemented_interfaces (class, &error);
4275 if (!mono_error_ok (&error)) {
4276 char *name = mono_type_get_full_name (class);
4277 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)));
4279 mono_error_cleanup (&error);
4281 } else if (ifaces) {
4282 for (i = 0; i < ifaces->len; i++) {
4283 MonoClass *ic = g_ptr_array_index (ifaces, i);
4284 max_vtsize += ic->method.count;
4286 g_ptr_array_free (ifaces, TRUE);
4290 if (class->parent) {
4291 mono_class_init (class->parent);
4292 mono_class_setup_vtable_full (class->parent, in_setup);
4294 if (class->parent->exception_type) {
4295 char *name = mono_type_get_full_name (class->parent);
4296 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4301 max_vtsize += class->parent->vtable_size;
4302 cur_slot = class->parent->vtable_size;
4305 max_vtsize += class->method.count;
4307 /*Array have a slot for stelemref*/
4308 if (mono_class_need_stelemref_method (class)) {
4309 stelemref_slot = cur_slot;
4314 vtable = alloca (sizeof (gpointer) * max_vtsize);
4315 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4317 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4319 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4320 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4323 max_iid = class->max_interface_id;
4324 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4326 /* Optimized version for generic instances */
4327 if (class->generic_class) {
4329 MonoClass *gklass = class->generic_class->container_class;
4332 mono_class_setup_vtable_full (gklass, in_setup);
4333 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4334 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4338 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4339 class->vtable_size = gklass->vtable_size;
4340 for (i = 0; i < gklass->vtable_size; ++i)
4341 if (gklass->vtable [i]) {
4342 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4343 if (!mono_error_ok (&error)) {
4344 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4345 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4347 mono_error_cleanup (&error);
4351 tmp [i]->slot = gklass->vtable [i]->slot;
4353 mono_memory_barrier ();
4354 class->vtable = tmp;
4356 /* Have to set method->slot for abstract virtual methods */
4357 if (class->methods && gklass->methods) {
4358 for (i = 0; i < class->method.count; ++i)
4359 if (class->methods [i]->slot == -1)
4360 class->methods [i]->slot = gklass->methods [i]->slot;
4366 if (class->parent && class->parent->vtable_size) {
4367 MonoClass *parent = class->parent;
4370 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4372 // Also inherit parent interface vtables, just as a starting point.
4373 // This is needed otherwise bug-77127.exe fails when the property methods
4374 // have different names in the iterface and the class, because for child
4375 // classes the ".override" information is not used anymore.
4376 for (i = 0; i < parent->interface_offsets_count; i++) {
4377 MonoClass *parent_interface = parent->interfaces_packed [i];
4378 int interface_offset = mono_class_interface_offset (class, parent_interface);
4379 /*FIXME this is now dead code as this condition will never hold true.
4380 Since interface offsets are inherited then the offset of an interface implemented
4381 by a parent will never be the out of it's vtable boundary.
4383 if (interface_offset >= parent->vtable_size) {
4384 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4387 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4388 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4389 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4390 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4391 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4392 parent_interface_offset + j, parent_interface_offset, j,
4393 interface_offset + j, interface_offset, j));
4400 /*Array have a slot for stelemref*/
4401 if (mono_class_need_stelemref_method (class)) {
4402 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4404 method->slot = stelemref_slot;
4406 g_assert (method->slot == stelemref_slot);
4408 vtable [stelemref_slot] = method;
4411 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4412 /* override interface methods */
4413 for (i = 0; i < onum; i++) {
4414 MonoMethod *decl = overrides [i*2];
4415 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4417 dslot = mono_method_get_vtable_slot (decl);
4419 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4423 dslot += mono_class_interface_offset (class, decl->klass);
4424 vtable [dslot] = overrides [i*2 + 1];
4425 vtable [dslot]->slot = dslot;
4427 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4429 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4431 if (mono_security_core_clr_enabled ())
4432 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4435 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4436 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4439 * Create a list of virtual methods to avoid calling
4440 * mono_class_get_virtual_methods () which is slow because of the metadata
4444 gpointer iter = NULL;
4447 virt_methods = NULL;
4448 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4449 virt_methods = g_slist_prepend (virt_methods, cm);
4451 if (class->exception_type)
4455 // Loop on all implemented interfaces...
4456 for (i = 0; i < class->interface_offsets_count; i++) {
4457 MonoClass *parent = class->parent;
4459 gboolean interface_is_explicitly_implemented_by_class;
4462 ic = class->interfaces_packed [i];
4463 ic_offset = mono_class_interface_offset (class, ic);
4465 mono_class_setup_methods (ic);
4466 if (ic->exception_type)
4469 // Check if this interface is explicitly implemented (instead of just inherited)
4470 if (parent != NULL) {
4471 int implemented_interfaces_index;
4472 interface_is_explicitly_implemented_by_class = FALSE;
4473 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4474 if (ic == class->interfaces [implemented_interfaces_index]) {
4475 interface_is_explicitly_implemented_by_class = TRUE;
4480 interface_is_explicitly_implemented_by_class = TRUE;
4483 // Loop on all interface methods...
4484 for (im_index = 0; im_index < ic->method.count; im_index++) {
4485 MonoMethod *im = ic->methods [im_index];
4486 int im_slot = ic_offset + im->slot;
4487 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4489 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4492 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4494 // If there is an explicit implementation, just use it right away,
4495 // otherwise look for a matching method
4496 if (override_im == NULL) {
4500 // First look for a suitable method among the class methods
4501 for (l = virt_methods; l; l = l->next) {
4503 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)));
4504 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4505 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4506 vtable [im_slot] = cm;
4507 /* Why do we need this? */
4512 TRACE_INTERFACE_VTABLE (printf ("\n"));
4513 if (class->exception_type) /*Might be set by check_interface_method_override*/
4517 // If the slot is still empty, look in all the inherited virtual methods...
4518 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4519 MonoClass *parent = class->parent;
4520 // Reverse order, so that last added methods are preferred
4521 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4522 MonoMethod *cm = parent->vtable [cm_index];
4524 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));
4525 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
4526 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4527 vtable [im_slot] = cm;
4528 /* Why do we need this? */
4534 if (class->exception_type) /*Might be set by check_interface_method_override*/
4536 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4540 g_assert (vtable [im_slot] == override_im);
4545 // If the class is not abstract, check that all its interface slots are full.
4546 // The check is done here and not directly at the end of the loop above because
4547 // it can happen (for injected generic array interfaces) that the same slot is
4548 // processed multiple times (those interfaces have overlapping slots), and it
4549 // will not always be the first pass the one that fills the slot.
4550 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4551 for (i = 0; i < class->interface_offsets_count; i++) {
4555 ic = class->interfaces_packed [i];
4556 ic_offset = mono_class_interface_offset (class, ic);
4558 for (im_index = 0; im_index < ic->method.count; im_index++) {
4559 MonoMethod *im = ic->methods [im_index];
4560 int im_slot = ic_offset + im->slot;
4562 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4565 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4566 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4567 if (vtable [im_slot] == NULL) {
4568 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4575 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4576 for (l = virt_methods; l; l = l->next) {
4579 * If the method is REUSE_SLOT, we must check in the
4580 * base class for a method to override.
4582 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4584 for (k = class->parent; k ; k = k->parent) {
4589 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4590 MonoMethodSignature *cmsig, *m1sig;
4592 cmsig = mono_method_signature (cm);
4593 m1sig = mono_method_signature (m1);
4595 if (!cmsig || !m1sig) {
4596 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4600 if (!strcmp(cm->name, m1->name) &&
4601 mono_metadata_signature_equal (cmsig, m1sig)) {
4603 if (mono_security_core_clr_enabled ())
4604 mono_security_core_clr_check_override (class, cm, m1);
4606 slot = mono_method_get_vtable_slot (m1);
4610 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4611 char *body_name = mono_method_full_name (cm, TRUE);
4612 char *decl_name = mono_method_full_name (m1, TRUE);
4613 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));
4619 g_assert (cm->slot < max_vtsize);
4621 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4622 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4623 mono_method_full_name (m1, 1), m1,
4624 mono_method_full_name (cm, 1), cm));
4625 g_hash_table_insert (override_map, m1, cm);
4629 if (k->exception_type)
4639 /*Non final newslot methods must be given a non-interface vtable slot*/
4640 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4644 cm->slot = cur_slot++;
4646 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4647 vtable [cm->slot] = cm;
4650 /* override non interface methods */
4651 for (i = 0; i < onum; i++) {
4652 MonoMethod *decl = overrides [i*2];
4653 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4654 g_assert (decl->slot != -1);
4655 vtable [decl->slot] = overrides [i*2 + 1];
4656 overrides [i * 2 + 1]->slot = decl->slot;
4658 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4659 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4660 mono_method_full_name (decl, 1), decl,
4661 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4662 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4664 if (mono_security_core_clr_enabled ())
4665 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4670 * If a method occupies more than one place in the vtable, and it is
4671 * overriden, then change the other occurances too.
4676 for (i = 0; i < max_vtsize; ++i)
4678 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4680 cm = g_hash_table_lookup (override_map, vtable [i]);
4685 g_hash_table_destroy (override_map);
4686 override_map = NULL;
4689 g_slist_free (virt_methods);
4690 virt_methods = NULL;
4692 /* Ensure that all vtable slots are filled with concrete instance methods */
4693 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4694 for (i = 0; i < cur_slot; ++i) {
4695 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4696 char *type_name = mono_type_get_full_name (class);
4697 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4698 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));
4700 g_free (method_name);
4706 if (class->generic_class) {
4707 MonoClass *gklass = class->generic_class->container_class;
4709 mono_class_init (gklass);
4711 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4713 /* Check that the vtable_size value computed in mono_class_init () is correct */
4714 if (class->vtable_size)
4715 g_assert (cur_slot == class->vtable_size);
4716 class->vtable_size = cur_slot;
4719 /* Try to share the vtable with our parent. */
4720 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4721 mono_memory_barrier ();
4722 class->vtable = class->parent->vtable;
4724 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4725 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4726 mono_memory_barrier ();
4727 class->vtable = tmp;
4730 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4731 if (mono_print_vtable) {
4734 print_implemented_interfaces (class);
4736 for (i = 0; i <= max_iid; i++)
4737 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4740 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4741 class->vtable_size, icount);
4743 for (i = 0; i < cur_slot; ++i) {
4748 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4749 mono_method_full_name (cm, TRUE));
4755 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4756 class->name, max_iid);
4758 for (i = 0; i < class->interface_count; i++) {
4759 ic = class->interfaces [i];
4760 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4761 mono_class_interface_offset (class, ic),
4762 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4765 for (k = class->parent; k ; k = k->parent) {
4766 for (i = 0; i < k->interface_count; i++) {
4767 ic = k->interfaces [i];
4768 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4769 mono_class_interface_offset (class, ic),
4770 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4776 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4781 char *name = mono_type_get_full_name (class);
4782 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4785 g_hash_table_destroy (override_map);
4787 g_slist_free (virt_methods);
4792 * mono_method_get_vtable_slot:
4794 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4795 * LOCKING: Acquires the loader lock.
4797 * FIXME Use proper MonoError machinery here.
4800 mono_method_get_vtable_slot (MonoMethod *method)
4802 if (method->slot == -1) {
4803 mono_class_setup_vtable (method->klass);
4804 if (method->klass->exception_type)
4806 if (method->slot == -1) {
4810 if (!method->klass->generic_class) {
4811 g_assert (method->is_inflated);
4812 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4815 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4816 g_assert (method->klass->generic_class);
4817 gklass = method->klass->generic_class->container_class;
4818 mono_class_setup_methods (method->klass);
4819 g_assert (method->klass->methods);
4820 for (i = 0; i < method->klass->method.count; ++i) {
4821 if (method->klass->methods [i] == method)
4824 g_assert (i < method->klass->method.count);
4825 g_assert (gklass->methods);
4826 method->slot = gklass->methods [i]->slot;
4828 g_assert (method->slot != -1);
4830 return method->slot;
4834 * mono_method_get_vtable_index:
4837 * Returns the index into the runtime vtable to access the method or,
4838 * in the case of a virtual generic method, the virtual generic method
4839 * thunk. Returns -1 on failure.
4841 * FIXME Use proper MonoError machinery here.
4844 mono_method_get_vtable_index (MonoMethod *method)
4846 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4847 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4848 if (imethod->declaring->is_generic)
4849 return mono_method_get_vtable_slot (imethod->declaring);
4851 return mono_method_get_vtable_slot (method);
4854 static MonoMethod *default_ghc = NULL;
4855 static MonoMethod *default_finalize = NULL;
4856 static int finalize_slot = -1;
4857 static int ghc_slot = -1;
4860 initialize_object_slots (MonoClass *class)
4865 if (class == mono_defaults.object_class) {
4866 mono_class_setup_vtable (class);
4867 for (i = 0; i < class->vtable_size; ++i) {
4868 MonoMethod *cm = class->vtable [i];
4870 if (!strcmp (cm->name, "GetHashCode"))
4872 else if (!strcmp (cm->name, "Finalize"))
4876 g_assert (ghc_slot > 0);
4877 default_ghc = class->vtable [ghc_slot];
4879 g_assert (finalize_slot > 0);
4880 default_finalize = class->vtable [finalize_slot];
4885 MonoMethod *array_method;
4887 } GenericArrayMethodInfo;
4889 static int generic_array_method_num = 0;
4890 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4893 generic_array_methods (MonoClass *class)
4895 int i, count_generic = 0;
4896 GList *list = NULL, *tmp;
4897 if (generic_array_method_num)
4898 return generic_array_method_num;
4899 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4900 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4901 for (i = 0; i < class->parent->method.count; i++) {
4902 MonoMethod *m = class->parent->methods [i];
4903 if (!strncmp (m->name, "InternalArray__", 15)) {
4905 list = g_list_prepend (list, m);
4908 list = g_list_reverse (list);
4909 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4911 for (tmp = list; tmp; tmp = tmp->next) {
4912 const char *mname, *iname;
4914 MonoMethod *m = tmp->data;
4915 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4916 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4918 generic_array_method_info [i].array_method = m;
4919 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4920 iname = "System.Collections.Generic.ICollection`1.";
4921 mname = m->name + 27;
4922 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4923 iname = "System.Collections.Generic.IEnumerable`1.";
4924 mname = m->name + 27;
4925 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4926 iname = "System.Collections.Generic.IReadOnlyList`1.";
4927 mname = m->name + strlen (ireadonlylist_prefix);
4928 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4929 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4930 mname = m->name + strlen (ireadonlycollection_prefix);
4931 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4932 iname = "System.Collections.Generic.IList`1.";
4933 mname = m->name + 15;
4935 g_assert_not_reached ();
4938 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4939 strcpy (name, iname);
4940 strcpy (name + strlen (iname), mname);
4941 generic_array_method_info [i].name = name;
4944 /*g_print ("array generic methods: %d\n", count_generic);*/
4946 generic_array_method_num = count_generic;
4948 return generic_array_method_num;
4952 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4954 MonoGenericContext tmp_context;
4957 tmp_context.class_inst = NULL;
4958 tmp_context.method_inst = iface->generic_class->context.class_inst;
4959 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4961 for (i = 0; i < generic_array_method_num; i++) {
4963 MonoMethod *m = generic_array_method_info [i].array_method;
4964 MonoMethod *inflated;
4966 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4967 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4968 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4973 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4975 int null_length = strlen ("(null)");
4976 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4977 char *s = mono_image_alloc (image, len);
4980 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4981 g_assert (result == len - 1);
4987 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4989 gpointer exception_data = NULL;
4991 switch (error->exception_type) {
4992 case MONO_EXCEPTION_TYPE_LOAD:
4993 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4996 case MONO_EXCEPTION_MISSING_METHOD:
4997 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5000 case MONO_EXCEPTION_MISSING_FIELD: {
5001 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5002 const char *class_name;
5005 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5007 class_name = error->klass->name;
5009 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5012 g_free ((void*)class_name);
5016 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5019 if (error->ref_only)
5020 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.";
5022 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5024 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5028 case MONO_EXCEPTION_BAD_IMAGE:
5029 exception_data = error->msg;
5033 g_assert_not_reached ();
5036 mono_class_set_failure (class, error->exception_type, exception_data);
5041 * @class: the class to initialize
5043 * Compute the instance_size, class_size and other infos that cannot be
5044 * computed at mono_class_get() time. Also compute vtable_size if possible.
5045 * Returns TRUE on success or FALSE if there was a problem in loading
5046 * the type (incorrect assemblies, missing assemblies, methods, etc).
5048 * LOCKING: Acquires the loader lock.
5051 mono_class_init (MonoClass *class)
5054 MonoCachedClassInfo cached_info;
5055 gboolean has_cached_info;
5059 /* Double-checking locking pattern */
5060 if (class->inited || class->exception_type)
5061 return class->exception_type == MONO_EXCEPTION_NONE;
5063 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5065 /* We do everything inside the lock to prevent races */
5066 mono_loader_lock ();
5068 if (class->inited || class->exception_type) {
5069 mono_loader_unlock ();
5070 /* Somebody might have gotten in before us */
5071 return class->exception_type == MONO_EXCEPTION_NONE;
5074 if (class->init_pending) {
5075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5079 class->init_pending = 1;
5081 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5082 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5087 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5088 MonoClass *element_class = class->element_class;
5089 if (!element_class->inited)
5090 mono_class_init (element_class);
5091 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5092 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5097 mono_stats.initialized_class_count++;
5099 if (class->generic_class && !class->generic_class->is_dynamic) {
5100 MonoClass *gklass = class->generic_class->container_class;
5102 mono_stats.generic_class_count++;
5104 class->method = gklass->method;
5105 class->field = gklass->field;
5107 mono_class_init (gklass);
5108 // FIXME: Why is this needed ?
5109 if (!gklass->exception_type)
5110 mono_class_setup_methods (gklass);
5111 if (gklass->exception_type) {
5112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5116 if (MONO_CLASS_IS_INTERFACE (class))
5117 class->interface_id = mono_get_unique_iid (class);
5120 if (class->parent && !class->parent->inited)
5121 mono_class_init (class->parent);
5123 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5125 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5126 class->nested_classes_inited = TRUE;
5129 * Computes the size used by the fields, and their locations
5131 if (has_cached_info) {
5132 class->instance_size = cached_info.instance_size;
5133 class->sizes.class_size = cached_info.class_size;
5134 class->packing_size = cached_info.packing_size;
5135 class->min_align = cached_info.min_align;
5136 class->blittable = cached_info.blittable;
5137 class->has_references = cached_info.has_references;
5138 class->has_static_refs = cached_info.has_static_refs;
5139 class->no_special_static_fields = cached_info.no_special_static_fields;
5142 if (!class->size_inited){
5143 mono_class_setup_fields (class);
5144 if (class->exception_type || mono_loader_get_last_error ())
5148 /* Initialize arrays */
5150 class->method.count = 3 + (class->rank > 1? 2: 1);
5152 if (class->interface_count) {
5153 int count_generic = generic_array_methods (class);
5154 class->method.count += class->interface_count * count_generic;
5158 mono_class_setup_supertypes (class);
5161 initialize_object_slots (class);
5164 * Initialize the rest of the data without creating a generic vtable if possible.
5165 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5166 * also avoid computing a generic vtable.
5168 if (has_cached_info) {
5170 class->vtable_size = cached_info.vtable_size;
5171 class->has_finalize = cached_info.has_finalize;
5172 class->has_finalize_inited = TRUE;
5173 class->ghcimpl = cached_info.ghcimpl;
5174 class->has_cctor = cached_info.has_cctor;
5175 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5176 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5177 * The first slot if for array with.
5179 static int szarray_vtable_size[2] = { 0 };
5181 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5184 if (!szarray_vtable_size [slot]) {
5185 mono_class_setup_vtable (class);
5186 szarray_vtable_size [slot] = class->vtable_size;
5188 class->vtable_size = szarray_vtable_size[slot];
5190 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5191 MonoClass *gklass = class->generic_class->container_class;
5193 /* Generic instance case */
5194 class->ghcimpl = gklass->ghcimpl;
5195 class->has_cctor = gklass->has_cctor;
5197 mono_class_setup_vtable (gklass);
5198 if (gklass->exception_type) {
5199 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5203 class->vtable_size = gklass->vtable_size;
5207 /* ghcimpl is not currently used
5209 if (class->parent) {
5210 MonoMethod *cmethod = class->vtable [ghc_slot];
5211 if (cmethod->is_inflated)
5212 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5213 if (cmethod == default_ghc) {
5219 /* C# doesn't allow interfaces to have cctors */
5220 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5221 MonoMethod *cmethod = NULL;
5223 if (class->type_token) {
5224 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5225 /* The find_method function ignores the 'flags' argument */
5226 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5227 class->has_cctor = 1;
5229 mono_class_setup_methods (class);
5230 if (class->exception_type)
5233 for (i = 0; i < class->method.count; ++i) {
5234 MonoMethod *method = class->methods [i];
5235 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5236 (strcmp (".cctor", method->name) == 0)) {
5237 class->has_cctor = 1;
5245 if (class->parent) {
5246 int first_iface_slot;
5247 /* This will compute class->parent->vtable_size for some classes */
5248 mono_class_init (class->parent);
5249 if (class->parent->exception_type) {
5250 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5253 if (mono_loader_get_last_error ())
5255 if (!class->parent->vtable_size) {
5256 /* FIXME: Get rid of this somehow */
5257 mono_class_setup_vtable (class->parent);
5258 if (class->parent->exception_type) {
5259 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5262 if (mono_loader_get_last_error ())
5265 first_iface_slot = class->parent->vtable_size;
5266 if (mono_class_need_stelemref_method (class))
5268 setup_interface_offsets (class, first_iface_slot, TRUE);
5270 setup_interface_offsets (class, 0, TRUE);
5273 if (mono_security_core_clr_enabled ())
5274 mono_security_core_clr_check_inheritance (class);
5276 if (mono_loader_get_last_error ()) {
5277 if (class->exception_type == MONO_EXCEPTION_NONE) {
5278 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5280 mono_loader_clear_error ();
5283 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5284 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5289 /* Because of the double-checking locking pattern */
5290 mono_memory_barrier ();
5292 class->init_pending = 0;
5294 mono_loader_unlock ();
5296 return class->exception_type == MONO_EXCEPTION_NONE;
5300 * mono_class_has_finalizer:
5302 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5306 mono_class_has_finalizer (MonoClass *klass)
5308 MonoClass *class = klass;
5309 gboolean has_finalize = FALSE;
5311 if (klass->has_finalize_inited)
5312 return klass->has_finalize;
5314 /* Interfaces and valuetypes are not supposed to have finalizers */
5315 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5316 MonoMethod *cmethod = NULL;
5318 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5319 } else if (class->generic_class) {
5320 MonoClass *gklass = class->generic_class->container_class;
5322 has_finalize = mono_class_has_finalizer (gklass);
5323 } else if (class->parent && class->parent->has_finalize) {
5324 has_finalize = TRUE;
5326 if (class->parent) {
5328 * Can't search in metadata for a method named Finalize, because that
5329 * ignores overrides.
5331 mono_class_setup_vtable (class);
5332 if (class->exception_type || mono_loader_get_last_error ())
5335 cmethod = class->vtable [finalize_slot];
5339 g_assert (class->vtable_size > finalize_slot);
5341 if (class->parent) {
5342 if (cmethod->is_inflated)
5343 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5344 if (cmethod != default_finalize)
5345 has_finalize = TRUE;
5351 mono_image_lock (klass->image);
5353 if (!klass->has_finalize_inited) {
5354 klass->has_finalize = has_finalize ? 1 : 0;
5356 mono_memory_barrier ();
5357 klass->has_finalize_inited = TRUE;
5360 mono_image_unlock (klass->image);
5362 return klass->has_finalize;
5366 mono_is_corlib_image (MonoImage *image)
5368 /* FIXME: allow the dynamic case for our compilers and with full trust */
5369 if (image_is_dynamic (image))
5370 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5372 return image == mono_defaults.corlib;
5376 * LOCKING: this assumes the loader lock is held
5379 mono_class_setup_mono_type (MonoClass *class)
5381 const char *name = class->name;
5382 const char *nspace = class->name_space;
5383 gboolean is_corlib = mono_is_corlib_image (class->image);
5385 class->this_arg.byref = 1;
5386 class->this_arg.data.klass = class;
5387 class->this_arg.type = MONO_TYPE_CLASS;
5388 class->byval_arg.data.klass = class;
5389 class->byval_arg.type = MONO_TYPE_CLASS;
5391 if (is_corlib && !strcmp (nspace, "System")) {
5392 if (!strcmp (name, "ValueType")) {
5394 * do not set the valuetype bit for System.ValueType.
5395 * class->valuetype = 1;
5397 class->blittable = TRUE;
5398 } else if (!strcmp (name, "Enum")) {
5400 * do not set the valuetype bit for System.Enum.
5401 * class->valuetype = 1;
5403 class->valuetype = 0;
5404 class->enumtype = 0;
5405 } else if (!strcmp (name, "Object")) {
5406 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5407 } else if (!strcmp (name, "String")) {
5408 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5409 } else if (!strcmp (name, "TypedReference")) {
5410 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5414 if (class->valuetype) {
5415 int t = MONO_TYPE_VALUETYPE;
5417 if (is_corlib && !strcmp (nspace, "System")) {
5420 if (!strcmp (name, "Boolean")) {
5421 t = MONO_TYPE_BOOLEAN;
5422 } else if (!strcmp(name, "Byte")) {
5424 class->blittable = TRUE;
5428 if (!strcmp (name, "Char")) {
5433 if (!strcmp (name, "Double")) {
5435 class->blittable = TRUE;
5439 if (!strcmp (name, "Int32")) {
5441 class->blittable = TRUE;
5442 } else if (!strcmp(name, "Int16")) {
5444 class->blittable = TRUE;
5445 } else if (!strcmp(name, "Int64")) {
5447 class->blittable = TRUE;
5448 } else if (!strcmp(name, "IntPtr")) {
5450 class->blittable = TRUE;
5454 if (!strcmp (name, "Single")) {
5456 class->blittable = TRUE;
5457 } else if (!strcmp(name, "SByte")) {
5459 class->blittable = TRUE;
5463 if (!strcmp (name, "UInt32")) {
5465 class->blittable = TRUE;
5466 } else if (!strcmp(name, "UInt16")) {
5468 class->blittable = TRUE;
5469 } else if (!strcmp(name, "UInt64")) {
5471 class->blittable = TRUE;
5472 } else if (!strcmp(name, "UIntPtr")) {
5474 class->blittable = TRUE;
5478 if (!strcmp (name, "TypedReference")) {
5479 t = MONO_TYPE_TYPEDBYREF;
5480 class->blittable = TRUE;
5484 if (!strcmp (name, "Void")) {
5492 class->this_arg.type = class->byval_arg.type = t;
5495 if (MONO_CLASS_IS_INTERFACE (class))
5496 class->interface_id = mono_get_unique_iid (class);
5502 * COM initialization is delayed until needed.
5503 * However when a [ComImport] attribute is present on a type it will trigger
5504 * the initialization. This is not a problem unless the BCL being executed
5505 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5508 init_com_from_comimport (MonoClass *class)
5510 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5511 if (mono_security_core_clr_enabled ()) {
5512 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5513 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5514 /* but it can not be made available for application (i.e. user code) since all COM calls
5515 * are considered native calls. In this case we fail with a TypeLoadException (just like
5516 * Silverlight 2 does */
5517 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5522 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5524 #endif /*DISABLE_COM*/
5527 * LOCKING: this assumes the loader lock is held
5530 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5532 gboolean system_namespace;
5533 gboolean is_corlib = mono_is_corlib_image (class->image);
5535 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5537 /* if root of the hierarchy */
5538 if (system_namespace && !strcmp (class->name, "Object")) {
5539 class->parent = NULL;
5540 class->instance_size = sizeof (MonoObject);
5543 if (!strcmp (class->name, "<Module>")) {
5544 class->parent = NULL;
5545 class->instance_size = 0;
5549 if (!MONO_CLASS_IS_INTERFACE (class)) {
5550 /* Imported COM Objects always derive from __ComObject. */
5552 if (MONO_CLASS_IS_IMPORT (class)) {
5553 init_com_from_comimport (class);
5554 if (parent == mono_defaults.object_class)
5555 parent = mono_class_get_com_object_class ();
5559 /* set the parent to something useful and safe, but mark the type as broken */
5560 parent = mono_defaults.object_class;
5561 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5564 class->parent = parent;
5566 if (parent->generic_class && !parent->name) {
5568 * If the parent is a generic instance, we may get
5569 * called before it is fully initialized, especially
5570 * before it has its name.
5575 #ifndef DISABLE_REMOTING
5576 class->marshalbyref = parent->marshalbyref;
5577 class->contextbound = parent->contextbound;
5580 class->delegate = parent->delegate;
5582 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5583 mono_class_set_is_com_object (class);
5585 if (system_namespace) {
5586 #ifndef DISABLE_REMOTING
5587 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5588 class->marshalbyref = 1;
5590 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5591 class->contextbound = 1;
5593 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5594 class->delegate = 1;
5597 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5598 (strcmp (class->parent->name_space, "System") == 0)))
5599 class->valuetype = 1;
5600 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5601 class->valuetype = class->enumtype = 1;
5603 /*class->enumtype = class->parent->enumtype; */
5605 /* initialize com types if COM interfaces are present */
5607 if (MONO_CLASS_IS_IMPORT (class))
5608 init_com_from_comimport (class);
5610 class->parent = NULL;
5616 * mono_class_setup_supertypes:
5619 * Build the data structure needed to make fast type checks work.
5620 * This currently sets two fields in @class:
5621 * - idepth: distance between @class and System.Object in the type
5623 * - supertypes: array of classes: each element has a class in the hierarchy
5624 * starting from @class up to System.Object
5626 * LOCKING: This function is atomic, in case of contention we waste memory.
5629 mono_class_setup_supertypes (MonoClass *class)
5632 MonoClass **supertypes;
5634 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5638 if (class->parent && !class->parent->supertypes)
5639 mono_class_setup_supertypes (class->parent);
5641 class->idepth = class->parent->idepth + 1;
5645 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5646 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5648 if (class->parent) {
5649 supertypes [class->idepth - 1] = class;
5650 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5652 supertypes [0] = class;
5655 mono_atomic_store_release (&class->supertypes, supertypes);
5659 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5661 MonoClass *gtd = (MonoClass*)user_data;
5662 /* Only try to fix generic instances of @gtd */
5663 if (gclass->generic_class->container_class != gtd)
5666 /* Check if the generic instance has no parent. */
5667 if (gtd->parent && !gclass->parent)
5668 mono_generic_class_setup_parent (gclass, gtd);
5674 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5676 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5677 mono_error_set_type_load_class (error, class, msg);
5681 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5683 MonoLoaderError *lerror = mono_loader_get_last_error ();
5686 set_failure_from_loader_error (class, lerror);
5687 mono_error_set_from_loader_error (error);
5691 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5692 mono_error_set_type_load_class (error, class, msg);
5697 * mono_class_create_from_typedef:
5698 * @image: image where the token is valid
5699 * @type_token: typedef token
5700 * @error: used to return any error found while creating the type
5702 * Create the MonoClass* representing the specified type token.
5703 * @type_token must be a TypeDef token.
5705 * FIXME: don't return NULL on failure, just the the caller figure it out.
5708 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5710 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5711 MonoClass *class, *parent = NULL;
5712 guint32 cols [MONO_TYPEDEF_SIZE];
5713 guint32 cols_next [MONO_TYPEDEF_SIZE];
5714 guint tidx = mono_metadata_token_index (type_token);
5715 MonoGenericContext *context = NULL;
5716 const char *name, *nspace;
5718 MonoClass **interfaces;
5719 guint32 field_last, method_last;
5720 guint32 nesting_tokeen;
5722 mono_error_init (error);
5724 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5725 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5726 mono_loader_assert_no_error ();
5730 mono_loader_lock ();
5732 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5733 mono_loader_unlock ();
5734 mono_loader_assert_no_error ();
5738 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5740 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5741 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5743 class = mono_image_alloc0 (image, sizeof (MonoClass));
5746 class->name_space = nspace;
5748 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5750 class->image = image;
5751 class->type_token = type_token;
5752 class->flags = cols [MONO_TYPEDEF_FLAGS];
5754 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5756 classes_size += sizeof (MonoClass);
5759 * Check whether we're a generic type definition.
5761 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5762 if (class->generic_container) {
5763 class->is_generic = 1;
5764 class->generic_container->owner.klass = class;
5765 context = &class->generic_container->context;
5768 if (class->generic_container)
5769 enable_gclass_recording ();
5771 if (cols [MONO_TYPEDEF_EXTENDS]) {
5773 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5775 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5776 /*WARNING: this must satisfy mono_metadata_type_hash*/
5777 class->this_arg.byref = 1;
5778 class->this_arg.data.klass = class;
5779 class->this_arg.type = MONO_TYPE_CLASS;
5780 class->byval_arg.data.klass = class;
5781 class->byval_arg.type = MONO_TYPE_CLASS;
5783 parent = mono_class_get_checked (image, parent_token, error);
5784 if (parent && context) /* Always inflate */
5785 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5787 if (parent == NULL) {
5788 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5789 goto parent_failure;
5792 for (tmp = parent; tmp; tmp = tmp->parent) {
5794 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5795 goto parent_failure;
5797 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5798 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5799 goto parent_failure;
5804 mono_class_setup_parent (class, parent);
5806 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5807 mono_class_setup_mono_type (class);
5809 if (class->generic_container)
5810 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5813 * This might access class->byval_arg for recursion generated by generic constraints,
5814 * so it has to come after setup_mono_type ().
5816 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5817 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5818 if (!mono_error_ok (error)) {
5819 /*FIXME implement a mono_class_set_failure_from_mono_error */
5820 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5821 mono_loader_unlock ();
5822 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5823 mono_loader_assert_no_error ();
5828 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5832 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5836 class->cast_class = class->element_class = class;
5838 if (!class->enumtype) {
5839 if (!mono_metadata_interfaces_from_typedef_full (
5840 image, type_token, &interfaces, &icount, FALSE, context, error)){
5842 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5843 mono_loader_unlock ();
5844 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5848 class->interfaces = interfaces;
5849 class->interface_count = icount;
5850 class->interfaces_inited = 1;
5853 /*g_print ("Load class %s\n", name);*/
5856 * Compute the field and method lists
5858 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5859 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5861 if (tt->rows > tidx){
5862 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5863 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5864 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5866 field_last = image->tables [MONO_TABLE_FIELD].rows;
5867 method_last = image->tables [MONO_TABLE_METHOD].rows;
5870 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5871 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5872 class->field.count = field_last - class->field.first;
5874 class->field.count = 0;
5876 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5877 class->method.count = method_last - class->method.first;
5879 class->method.count = 0;
5881 /* reserve space to store vector pointer in arrays */
5882 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5883 class->instance_size += 2 * sizeof (gpointer);
5884 g_assert (class->field.count == 0);
5887 if (class->enumtype) {
5888 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5889 if (!enum_basetype) {
5890 /*set it to a default value as the whole runtime can't handle this to be null*/
5891 class->cast_class = class->element_class = mono_defaults.int32_class;
5892 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5893 mono_loader_unlock ();
5894 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5895 mono_loader_assert_no_error ();
5898 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5902 * If we're a generic type definition, load the constraints.
5903 * We must do this after the class has been constructed to make certain recursive scenarios
5906 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5907 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)));
5908 mono_loader_unlock ();
5909 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5910 mono_loader_assert_no_error ();
5914 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5915 if (!strncmp (name, "Vector", 6))
5916 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");
5919 mono_loader_unlock ();
5921 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5922 mono_loader_assert_no_error ();
5927 mono_class_setup_mono_type (class);
5928 mono_loader_unlock ();
5929 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5930 mono_loader_assert_no_error ();
5934 /** is klass Nullable<T>? */
5936 mono_class_is_nullable (MonoClass *klass)
5938 return klass->generic_class != NULL &&
5939 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5943 /** if klass is T? return T */
5945 mono_class_get_nullable_param (MonoClass *klass)
5947 g_assert (mono_class_is_nullable (klass));
5948 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5952 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5956 MonoGenericClass *gclass = klass->generic_class;
5958 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5959 if (!mono_error_ok (&error)) {
5960 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5961 klass->parent = mono_defaults.object_class;
5962 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5963 mono_error_cleanup (&error);
5967 mono_class_setup_parent (klass, klass->parent);
5969 if (klass->enumtype) {
5970 klass->cast_class = gtd->cast_class;
5971 klass->element_class = gtd->element_class;
5977 * Create the `MonoClass' for an instantiation of a generic type.
5978 * We only do this if we actually need it.
5981 mono_generic_class_get_class (MonoGenericClass *gclass)
5983 MonoClass *klass, *gklass;
5985 if (gclass->cached_class)
5986 return gclass->cached_class;
5988 mono_loader_lock ();
5989 if (gclass->cached_class) {
5990 mono_loader_unlock ();
5991 return gclass->cached_class;
5994 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5996 gklass = gclass->container_class;
5998 if (record_gclass_instantiation > 0)
5999 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6001 if (gklass->nested_in) {
6002 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6003 klass->nested_in = gklass->nested_in;
6006 klass->name = gklass->name;
6007 klass->name_space = gklass->name_space;
6009 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6011 klass->image = gklass->image;
6012 klass->flags = gklass->flags;
6013 klass->type_token = gklass->type_token;
6014 klass->field.count = gklass->field.count;
6016 klass->is_inflated = 1;
6017 klass->generic_class = gclass;
6019 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6020 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6021 klass->this_arg.byref = TRUE;
6022 klass->enumtype = gklass->enumtype;
6023 klass->valuetype = gklass->valuetype;
6025 klass->cast_class = klass->element_class = klass;
6027 if (mono_class_is_nullable (klass))
6028 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6031 * We're not interested in the nested classes of a generic instance.
6032 * We use the generic type definition to look for nested classes.
6035 mono_generic_class_setup_parent (klass, gklass);
6037 if (gclass->is_dynamic) {
6039 * 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.
6040 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6041 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6043 if (!gklass->wastypebuilder)
6046 mono_class_setup_supertypes (klass);
6048 if (klass->enumtype) {
6050 * For enums, gklass->fields might not been set, but instance_size etc. is
6051 * already set in mono_reflection_create_internal_class (). For non-enums,
6052 * these will be computed normally in mono_class_layout_fields ().
6054 klass->instance_size = gklass->instance_size;
6055 klass->sizes.class_size = gklass->sizes.class_size;
6056 mono_memory_barrier ();
6057 klass->size_inited = 1;
6061 mono_memory_barrier ();
6062 gclass->cached_class = klass;
6064 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6066 inflated_classes ++;
6067 inflated_classes_size += sizeof (MonoClass);
6069 mono_loader_unlock ();
6075 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6077 MonoClass *klass, **ptr;
6079 MonoGenericContainer *container = mono_generic_param_owner (param);
6083 image = mono_defaults.corlib;
6085 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6086 classes_size += sizeof (MonoClass);
6089 klass->name = pinfo->name;
6091 int n = mono_generic_param_num (param);
6092 klass->name = mono_image_alloc0 (image, 16);
6093 sprintf ((char*)klass->name, "%d", n);
6098 MonoMethod *omethod = container->owner.method;
6099 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6101 MonoClass *oklass = container->owner.klass;
6102 klass->name_space = oklass ? oklass->name_space : "";
6105 klass->name_space = "";
6108 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6112 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6116 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6117 klass->parent = pinfo->constraints [0];
6119 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6120 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6122 klass->parent = mono_defaults.object_class;
6125 if (count - pos > 0) {
6126 klass->interface_count = count - pos;
6127 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6128 klass->interfaces_inited = TRUE;
6129 for (i = pos; i < count; i++)
6130 klass->interfaces [i - pos] = pinfo->constraints [i];
6133 klass->image = image;
6135 klass->inited = TRUE;
6136 klass->cast_class = klass->element_class = klass;
6137 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6139 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6140 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6141 klass->this_arg.byref = TRUE;
6143 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6144 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6146 /*Init these fields to sane values*/
6147 klass->min_align = 1;
6149 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6150 * constrained to, the JIT depends on this.
6152 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6153 mono_memory_barrier ();
6154 klass->size_inited = 1;
6155 klass->setup_fields_called = 1;
6157 mono_class_setup_supertypes (klass);
6159 if (count - pos > 0) {
6160 mono_class_setup_vtable (klass->parent);
6161 if (klass->parent->exception_type)
6162 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6164 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6170 #define FAST_CACHE_SIZE 16
6173 * LOCKING: Takes the image lock depending on @take_lock.
6176 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6178 int n = mono_generic_param_num (param);
6179 MonoImage *image = param->image;
6180 MonoClass *klass = NULL;
6185 if (param->gshared_constraint) {
6186 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6189 mono_image_lock (image);
6190 klass = g_hash_table_lookup (ht, param);
6192 mono_image_unlock (image);
6197 if (n < FAST_CACHE_SIZE) {
6199 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6201 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6203 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6206 mono_image_lock (image);
6207 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6209 mono_image_unlock (image);
6216 * LOCKING: Image lock (param->image) must be held
6219 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6221 int n = mono_generic_param_num (param);
6222 MonoImage *image = param->image;
6226 if (param->gshared_constraint) {
6227 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6229 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6230 mono_memory_barrier ();
6232 image->mvar_cache_constrained = ht;
6234 image->var_cache_constrained = ht;
6236 g_hash_table_insert (ht, param, klass);
6237 } else if (n < FAST_CACHE_SIZE) {
6239 /* Requires locking to avoid droping an already published class */
6240 if (!image->mvar_cache_fast)
6241 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6242 image->mvar_cache_fast [n] = klass;
6244 if (!image->var_cache_fast)
6245 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6246 image->var_cache_fast [n] = klass;
6249 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6251 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6253 ht = g_hash_table_new (NULL, NULL);
6254 mono_memory_barrier ();
6256 image->mvar_cache_slow = ht;
6258 image->var_cache_slow = ht;
6261 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6266 * LOCKING: Acquires the image lock (@image).
6269 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6271 MonoGenericContainer *container = mono_generic_param_owner (param);
6272 MonoGenericParamInfo *pinfo = NULL;
6273 MonoClass *klass, *klass2;
6276 pinfo = mono_generic_param_info (param);
6277 klass = pinfo->pklass;
6280 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6285 if (!image && container) {
6287 MonoMethod *method = container->owner.method;
6288 image = (method && method->klass) ? method->klass->image : NULL;
6290 MonoClass *klass = container->owner.klass;
6291 // FIXME: 'klass' should not be null
6292 // But, monodis creates GenericContainers without associating a owner to it
6293 image = klass ? klass->image : NULL;
6297 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6299 mono_memory_barrier ();
6301 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6302 image = mono_defaults.corlib;
6304 mono_image_lock (image);
6306 klass2 = pinfo->pklass;
6308 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6314 pinfo->pklass = klass;
6316 set_anon_gparam_class (param, is_mvar, klass);
6318 mono_image_unlock (image);
6320 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6322 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6324 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6330 mono_ptr_class_get (MonoType *type)
6333 MonoClass *el_class;
6337 el_class = mono_class_from_mono_type (type);
6338 image = el_class->image;
6340 mono_image_lock (image);
6341 if (image->ptr_cache) {
6342 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6343 mono_image_unlock (image);
6347 mono_image_unlock (image);
6349 result = mono_image_alloc0 (image, sizeof (MonoClass));
6351 classes_size += sizeof (MonoClass);
6353 result->parent = NULL; /* no parent for PTR types */
6354 result->name_space = el_class->name_space;
6355 name = g_strdup_printf ("%s*", el_class->name);
6356 result->name = mono_image_strdup (image, name);
6359 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6361 result->image = el_class->image;
6362 result->inited = TRUE;
6363 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6364 /* Can pointers get boxed? */
6365 result->instance_size = sizeof (gpointer);
6366 result->cast_class = result->element_class = el_class;
6367 result->blittable = TRUE;
6369 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6370 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6371 result->this_arg.byref = TRUE;
6373 mono_class_setup_supertypes (result);
6375 mono_image_lock (image);
6376 if (image->ptr_cache) {
6378 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6379 mono_image_unlock (image);
6380 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6384 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6386 g_hash_table_insert (image->ptr_cache, el_class, result);
6387 mono_image_unlock (image);
6389 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6395 mono_fnptr_class_get (MonoMethodSignature *sig)
6398 static GHashTable *ptr_hash = NULL;
6400 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6402 mono_loader_lock ();
6405 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6407 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6408 mono_loader_unlock ();
6411 result = g_new0 (MonoClass, 1);
6413 result->parent = NULL; /* no parent for PTR types */
6414 result->name_space = "System";
6415 result->name = "MonoFNPtrFakeClass";
6417 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6419 result->image = mono_defaults.corlib; /* need to fix... */
6420 result->inited = TRUE;
6421 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6422 /* Can pointers get boxed? */
6423 result->instance_size = sizeof (gpointer);
6424 result->cast_class = result->element_class = result;
6425 result->blittable = TRUE;
6427 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6428 result->this_arg.data.method = result->byval_arg.data.method = sig;
6429 result->this_arg.byref = TRUE;
6430 result->blittable = TRUE;
6432 mono_class_setup_supertypes (result);
6434 g_hash_table_insert (ptr_hash, sig, result);
6436 mono_loader_unlock ();
6438 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6444 mono_class_from_mono_type (MonoType *type)
6446 switch (type->type) {
6447 case MONO_TYPE_OBJECT:
6448 return type->data.klass? type->data.klass: mono_defaults.object_class;
6449 case MONO_TYPE_VOID:
6450 return type->data.klass? type->data.klass: mono_defaults.void_class;
6451 case MONO_TYPE_BOOLEAN:
6452 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6453 case MONO_TYPE_CHAR:
6454 return type->data.klass? type->data.klass: mono_defaults.char_class;
6456 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6458 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6460 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6462 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6464 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6466 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6468 return type->data.klass? type->data.klass: mono_defaults.int_class;
6470 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6472 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6474 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6476 return type->data.klass? type->data.klass: mono_defaults.single_class;
6478 return type->data.klass? type->data.klass: mono_defaults.double_class;
6479 case MONO_TYPE_STRING:
6480 return type->data.klass? type->data.klass: mono_defaults.string_class;
6481 case MONO_TYPE_TYPEDBYREF:
6482 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6483 case MONO_TYPE_ARRAY:
6484 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6486 return mono_ptr_class_get (type->data.type);
6487 case MONO_TYPE_FNPTR:
6488 return mono_fnptr_class_get (type->data.method);
6489 case MONO_TYPE_SZARRAY:
6490 return mono_array_class_get (type->data.klass, 1);
6491 case MONO_TYPE_CLASS:
6492 case MONO_TYPE_VALUETYPE:
6493 return type->data.klass;
6494 case MONO_TYPE_GENERICINST:
6495 return mono_generic_class_get_class (type->data.generic_class);
6497 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6498 case MONO_TYPE_MVAR:
6499 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6501 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6502 g_assert_not_reached ();
6509 * mono_type_retrieve_from_typespec
6510 * @image: context where the image is created
6511 * @type_spec: typespec token
6512 * @context: the generic context used to evaluate generic instantiations in
6515 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6517 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6519 *did_inflate = FALSE;
6524 if (context && (context->class_inst || context->method_inst)) {
6525 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6527 if (!mono_error_ok (error)) {
6528 mono_loader_assert_no_error ();
6534 *did_inflate = TRUE;
6541 * mono_class_create_from_typespec
6542 * @image: context where the image is created
6543 * @type_spec: typespec token
6544 * @context: the generic context used to evaluate generic instantiations in
6547 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6550 gboolean inflated = FALSE;
6551 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6552 if (!mono_error_ok (error))
6554 ret = mono_class_from_mono_type (t);
6556 mono_metadata_free_type (t);
6561 * mono_bounded_array_class_get:
6562 * @element_class: element class
6563 * @rank: the dimension of the array class
6564 * @bounded: whenever the array has non-zero bounds
6566 * Returns: a class object describing the array with element type @element_type and
6570 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6574 MonoClass *parent = NULL;
6575 GSList *list, *rootlist = NULL;
6578 gboolean corlib_type = FALSE;
6580 g_assert (rank <= 255);
6583 /* bounded only matters for one-dimensional arrays */
6586 image = eclass->image;
6588 if (rank == 1 && !bounded) {
6590 * This case is very frequent not just during compilation because of calls
6591 * from mono_class_from_mono_type (), mono_array_new (),
6592 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6594 mono_mutex_lock (&image->szarray_cache_lock);
6595 if (!image->szarray_cache)
6596 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6597 class = g_hash_table_lookup (image->szarray_cache, eclass);
6598 mono_mutex_unlock (&image->szarray_cache_lock);
6602 mono_loader_lock ();
6604 mono_loader_lock ();
6606 if (!image->array_cache)
6607 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6609 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6610 for (; list; list = list->next) {
6612 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6613 mono_loader_unlock ();
6620 /* for the building corlib use System.Array from it */
6621 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6622 parent = mono_class_from_name (image, "System", "Array");
6625 parent = mono_defaults.array_class;
6626 if (!parent->inited)
6627 mono_class_init (parent);
6630 class = mono_image_alloc0 (image, sizeof (MonoClass));
6632 class->image = image;
6633 class->name_space = eclass->name_space;
6634 nsize = strlen (eclass->name);
6635 name = g_malloc (nsize + 2 + rank + 1);
6636 memcpy (name, eclass->name, nsize);
6639 memset (name + nsize + 1, ',', rank - 1);
6641 name [nsize + rank] = '*';
6642 name [nsize + rank + bounded] = ']';
6643 name [nsize + rank + bounded + 1] = 0;
6644 class->name = mono_image_strdup (image, name);
6647 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6649 classes_size += sizeof (MonoClass);
6651 class->type_token = 0;
6652 /* all arrays are marked serializable and sealed, bug #42779 */
6653 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6654 class->parent = parent;
6655 class->instance_size = mono_class_instance_size (class->parent);
6657 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6658 /*Arrays of those two types are invalid.*/
6659 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6660 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6661 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6662 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6663 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6665 /* element_size -1 is ok as this is not an instantitable type*/
6666 class->sizes.element_size = -1;
6668 class->sizes.element_size = mono_class_array_element_size (eclass);
6670 mono_class_setup_supertypes (class);
6672 if (eclass->generic_class)
6673 mono_class_init (eclass);
6674 if (!eclass->size_inited)
6675 mono_class_setup_fields (eclass);
6676 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6677 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6679 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6683 if (eclass->enumtype)
6684 class->cast_class = eclass->element_class;
6686 class->cast_class = eclass;
6688 switch (class->cast_class->byval_arg.type) {
6690 class->cast_class = mono_defaults.byte_class;
6693 class->cast_class = mono_defaults.int16_class;
6696 #if SIZEOF_VOID_P == 4
6700 class->cast_class = mono_defaults.int32_class;
6703 #if SIZEOF_VOID_P == 8
6707 class->cast_class = mono_defaults.int64_class;
6713 class->element_class = eclass;
6715 if ((rank > 1) || bounded) {
6716 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6717 class->byval_arg.type = MONO_TYPE_ARRAY;
6718 class->byval_arg.data.array = at;
6719 at->eklass = eclass;
6721 /* FIXME: complete.... */
6723 class->byval_arg.type = MONO_TYPE_SZARRAY;
6724 class->byval_arg.data.klass = eclass;
6726 class->this_arg = class->byval_arg;
6727 class->this_arg.byref = 1;
6732 class->generic_container = eclass->generic_container;
6734 if (rank == 1 && !bounded) {
6735 MonoClass *prev_class;
6737 mono_mutex_lock (&image->szarray_cache_lock);
6738 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6740 /* Someone got in before us */
6743 g_hash_table_insert (image->szarray_cache, eclass, class);
6744 mono_mutex_unlock (&image->szarray_cache_lock);
6746 list = g_slist_append (rootlist, class);
6747 g_hash_table_insert (image->array_cache, eclass, list);
6750 mono_loader_unlock ();
6752 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6758 * mono_array_class_get:
6759 * @element_class: element class
6760 * @rank: the dimension of the array class
6762 * Returns: a class object describing the array with element type @element_type and
6766 mono_array_class_get (MonoClass *eclass, guint32 rank)
6768 return mono_bounded_array_class_get (eclass, rank, FALSE);
6772 * mono_class_instance_size:
6775 * Returns: the size of an object instance
6778 mono_class_instance_size (MonoClass *klass)
6780 if (!klass->size_inited)
6781 mono_class_init (klass);
6783 return klass->instance_size;
6787 * mono_class_min_align:
6790 * Returns: minimm alignment requirements
6793 mono_class_min_align (MonoClass *klass)
6795 if (!klass->size_inited)
6796 mono_class_init (klass);
6798 return klass->min_align;
6802 * mono_class_value_size:
6805 * This function is used for value types, and return the
6806 * space and the alignment to store that kind of value object.
6808 * Returns: the size of a value of kind @klass
6811 mono_class_value_size (MonoClass *klass, guint32 *align)
6815 /* fixme: check disable, because we still have external revereces to
6816 * mscorlib and Dummy Objects
6818 /*g_assert (klass->valuetype);*/
6820 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6823 *align = klass->min_align;
6829 * mono_class_data_size:
6832 * Returns: the size of the static class data
6835 mono_class_data_size (MonoClass *klass)
6838 mono_class_init (klass);
6839 /* This can happen with dynamically created types */
6840 if (!klass->fields_inited)
6841 mono_class_setup_fields_locking (klass);
6843 /* in arrays, sizes.class_size is unioned with element_size
6844 * and arrays have no static fields
6848 return klass->sizes.class_size;
6852 * Auxiliary routine to mono_class_get_field
6854 * Takes a field index instead of a field token.
6856 static MonoClassField *
6857 mono_class_get_field_idx (MonoClass *class, int idx)
6859 mono_class_setup_fields_locking (class);
6860 if (class->exception_type)
6864 if (class->image->uncompressed_metadata) {
6866 * class->field.first points to the FieldPtr table, while idx points into the
6867 * Field table, so we have to do a search.
6869 /*FIXME this is broken for types with multiple fields with the same name.*/
6870 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6873 for (i = 0; i < class->field.count; ++i)
6874 if (mono_field_get_name (&class->fields [i]) == name)
6875 return &class->fields [i];
6876 g_assert_not_reached ();
6878 if (class->field.count) {
6879 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6880 return &class->fields [idx - class->field.first];
6884 class = class->parent;
6890 * mono_class_get_field:
6891 * @class: the class to lookup the field.
6892 * @field_token: the field token
6894 * Returns: A MonoClassField representing the type and offset of
6895 * the field, or a NULL value if the field does not belong to this
6899 mono_class_get_field (MonoClass *class, guint32 field_token)
6901 int idx = mono_metadata_token_index (field_token);
6903 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6905 return mono_class_get_field_idx (class, idx - 1);
6909 * mono_class_get_field_from_name:
6910 * @klass: the class to lookup the field.
6911 * @name: the field name
6913 * Search the class @klass and it's parents for a field with the name @name.
6915 * Returns: the MonoClassField pointer of the named field or NULL
6918 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6920 return mono_class_get_field_from_name_full (klass, name, NULL);
6924 * mono_class_get_field_from_name_full:
6925 * @klass: the class to lookup the field.
6926 * @name: the field name
6927 * @type: the type of the fields. This optional.
6929 * Search the class @klass and it's parents for a field with the name @name and type @type.
6931 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6932 * of its generic type definition.
6934 * Returns: the MonoClassField pointer of the named field or NULL
6937 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6941 mono_class_setup_fields_locking (klass);
6942 if (klass->exception_type)
6946 for (i = 0; i < klass->field.count; ++i) {
6947 MonoClassField *field = &klass->fields [i];
6949 if (strcmp (name, mono_field_get_name (field)) != 0)
6953 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6954 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6959 klass = klass->parent;
6965 * mono_class_get_field_token:
6966 * @field: the field we need the token of
6968 * Get the token of a field. Note that the tokesn is only valid for the image
6969 * the field was loaded from. Don't use this function for fields in dynamic types.
6971 * Returns: the token representing the field in the image it was loaded from.
6974 mono_class_get_field_token (MonoClassField *field)
6976 MonoClass *klass = field->parent;
6979 mono_class_setup_fields_locking (klass);
6984 for (i = 0; i < klass->field.count; ++i) {
6985 if (&klass->fields [i] == field) {
6986 int idx = klass->field.first + i + 1;
6988 if (klass->image->uncompressed_metadata)
6989 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6990 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6993 klass = klass->parent;
6996 g_assert_not_reached ();
7001 mono_field_get_index (MonoClassField *field)
7003 int index = field - field->parent->fields;
7005 g_assert (index >= 0 && index < field->parent->field.count);
7011 * mono_class_get_field_default_value:
7013 * Return the default value of the field as a pointer into the metadata blob.
7016 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7019 guint32 constant_cols [MONO_CONSTANT_SIZE];
7021 MonoClass *klass = field->parent;
7023 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7025 if (!klass->ext || !klass->ext->field_def_values) {
7026 MonoFieldDefaultValue *def_values;
7028 mono_class_alloc_ext (klass);
7030 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7032 mono_image_lock (klass->image);
7033 mono_memory_barrier ();
7034 if (!klass->ext->field_def_values)
7035 klass->ext->field_def_values = def_values;
7036 mono_image_unlock (klass->image);
7039 field_index = mono_field_get_index (field);
7041 if (!klass->ext->field_def_values [field_index].data) {
7042 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7046 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7048 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7049 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7050 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7053 *def_type = klass->ext->field_def_values [field_index].def_type;
7054 return klass->ext->field_def_values [field_index].data;
7058 mono_property_get_index (MonoProperty *prop)
7060 int index = prop - prop->parent->ext->properties;
7062 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7068 * mono_class_get_property_default_value:
7070 * Return the default value of the field as a pointer into the metadata blob.
7073 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7076 guint32 constant_cols [MONO_CONSTANT_SIZE];
7077 MonoClass *klass = property->parent;
7079 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7081 * We don't cache here because it is not used by C# so it's quite rare, but
7082 * we still do the lookup in klass->ext because that is where the data
7083 * is stored for dynamic assemblies.
7086 if (image_is_dynamic (klass->image)) {
7087 int prop_index = mono_property_get_index (property);
7088 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7089 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7090 return klass->ext->prop_def_values [prop_index].data;
7094 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7098 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7099 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7100 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7104 mono_class_get_event_token (MonoEvent *event)
7106 MonoClass *klass = event->parent;
7111 for (i = 0; i < klass->ext->event.count; ++i) {
7112 if (&klass->ext->events [i] == event)
7113 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7116 klass = klass->parent;
7119 g_assert_not_reached ();
7124 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7128 gpointer iter = NULL;
7129 while ((p = mono_class_get_properties (klass, &iter))) {
7130 if (! strcmp (name, p->name))
7133 klass = klass->parent;
7139 mono_class_get_property_token (MonoProperty *prop)
7141 MonoClass *klass = prop->parent;
7145 gpointer iter = NULL;
7146 while ((p = mono_class_get_properties (klass, &iter))) {
7147 if (&klass->ext->properties [i] == prop)
7148 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7152 klass = klass->parent;
7155 g_assert_not_reached ();
7160 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7162 const char *name, *nspace;
7163 if (image_is_dynamic (image))
7164 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7166 switch (type_token & 0xff000000){
7167 case MONO_TOKEN_TYPE_DEF: {
7168 guint32 cols [MONO_TYPEDEF_SIZE];
7169 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7170 guint tidx = mono_metadata_token_index (type_token);
7172 if (tidx > tt->rows)
7173 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7175 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7176 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7177 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7178 if (strlen (nspace) == 0)
7179 return g_strdup_printf ("%s", name);
7181 return g_strdup_printf ("%s.%s", nspace, name);
7184 case MONO_TOKEN_TYPE_REF: {
7186 guint32 cols [MONO_TYPEREF_SIZE];
7187 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7188 guint tidx = mono_metadata_token_index (type_token);
7191 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7193 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7194 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7195 mono_error_cleanup (&error);
7199 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7200 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7201 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7202 if (strlen (nspace) == 0)
7203 return g_strdup_printf ("%s", name);
7205 return g_strdup_printf ("%s.%s", nspace, name);
7208 case MONO_TOKEN_TYPE_SPEC:
7209 return g_strdup_printf ("Typespec 0x%08x", type_token);
7211 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7216 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7218 if (image_is_dynamic (image))
7219 return g_strdup_printf ("DynamicAssembly %s", image->name);
7221 switch (type_token & 0xff000000){
7222 case MONO_TOKEN_TYPE_DEF:
7223 if (image->assembly)
7224 return mono_stringify_assembly_name (&image->assembly->aname);
7225 else if (image->assembly_name)
7226 return g_strdup (image->assembly_name);
7227 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7228 case MONO_TOKEN_TYPE_REF: {
7230 MonoAssemblyName aname;
7231 guint32 cols [MONO_TYPEREF_SIZE];
7232 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7233 guint32 idx = mono_metadata_token_index (type_token);
7236 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7238 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7239 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7240 mono_error_cleanup (&error);
7243 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7245 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7246 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7247 case MONO_RESOLUTION_SCOPE_MODULE:
7249 return g_strdup ("");
7250 case MONO_RESOLUTION_SCOPE_MODULEREF:
7252 return g_strdup ("");
7253 case MONO_RESOLUTION_SCOPE_TYPEREF:
7255 return g_strdup ("");
7256 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7257 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7258 return mono_stringify_assembly_name (&aname);
7260 g_assert_not_reached ();
7264 case MONO_TOKEN_TYPE_SPEC:
7266 return g_strdup ("");
7268 g_assert_not_reached ();
7275 * mono_class_get_full:
7276 * @image: the image where the class resides
7277 * @type_token: the token for the class
7278 * @context: the generic context used to evaluate generic instantiations in
7279 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7281 * Returns: the MonoClass that represents @type_token in @image
7284 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7288 class = mono_class_get_checked (image, type_token, &error);
7290 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7291 class = mono_class_inflate_generic_class_checked (class, context, &error);
7293 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7299 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7303 mono_error_init (error);
7304 class = mono_class_get_checked (image, type_token, error);
7306 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7307 class = mono_class_inflate_generic_class_checked (class, context, error);
7312 * mono_class_get_checked:
7313 * @image: the image where the class resides
7314 * @type_token: the token for the class
7315 * @error: error object to return any error
7317 * Returns: the MonoClass that represents @type_token in @image
7320 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7322 MonoClass *class = NULL;
7324 mono_error_init (error);
7326 if (image_is_dynamic (image)) {
7327 int table = mono_metadata_token_table (type_token);
7329 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7330 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7333 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7337 switch (type_token & 0xff000000){
7338 case MONO_TOKEN_TYPE_DEF:
7339 class = mono_class_create_from_typedef (image, type_token, error);
7341 case MONO_TOKEN_TYPE_REF:
7342 class = mono_class_from_typeref_checked (image, type_token, error);
7344 case MONO_TOKEN_TYPE_SPEC:
7345 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7348 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7352 /* Generic case, should be avoided for when a better error is possible. */
7353 if (!class && mono_error_ok (error)) {
7354 char *name = mono_class_name_from_token (image, type_token);
7355 char *assembly = mono_assembly_name_from_token (image, type_token);
7356 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7364 * mono_type_get_checked:
7365 * @image: the image where the type resides
7366 * @type_token: the token for the type
7367 * @context: the generic context used to evaluate generic instantiations in
7368 * @error: Error handling context
7370 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7372 * Returns: the MonoType that represents @type_token in @image
7375 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7377 MonoType *type = NULL;
7378 gboolean inflated = FALSE;
7380 mono_error_init (error);
7382 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7383 if (image_is_dynamic (image))
7384 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7386 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7387 MonoClass *class = mono_class_get_checked (image, type_token, error);
7390 mono_loader_assert_no_error ();
7395 return mono_class_get_type (class);
7398 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7401 mono_loader_assert_no_error ();
7406 MonoType *tmp = type;
7407 type = mono_class_get_type (mono_class_from_mono_type (type));
7408 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7409 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7410 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7412 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7414 if (type->type != tmp->type)
7417 mono_metadata_free_type (tmp);
7424 mono_class_get (MonoImage *image, guint32 type_token)
7426 return mono_class_get_full (image, type_token, NULL);
7430 * mono_image_init_name_cache:
7432 * Initializes the class name cache stored in image->name_cache.
7434 * LOCKING: Acquires the corresponding image lock.
7437 mono_image_init_name_cache (MonoImage *image)
7439 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7440 guint32 cols [MONO_TYPEDEF_SIZE];
7443 guint32 i, visib, nspace_index;
7444 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7446 if (image->name_cache)
7449 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7451 if (image_is_dynamic (image)) {
7452 mono_image_lock (image);
7453 if (image->name_cache) {
7454 /* Somebody initialized it before us */
7455 g_hash_table_destroy (the_name_cache);
7457 mono_atomic_store_release (&image->name_cache, the_name_cache);
7459 mono_image_unlock (image);
7463 /* Temporary hash table to avoid lookups in the nspace_table */
7464 name_cache2 = g_hash_table_new (NULL, NULL);
7466 for (i = 1; i <= t->rows; ++i) {
7467 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7468 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7470 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7471 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7473 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7475 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7476 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7478 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7479 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7480 if (!nspace_table) {
7481 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7482 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7483 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7486 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7489 /* Load type names from EXPORTEDTYPES table */
7491 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7492 guint32 cols [MONO_EXP_TYPE_SIZE];
7495 for (i = 0; i < t->rows; ++i) {
7496 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7497 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7498 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7500 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7501 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7502 if (!nspace_table) {
7503 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7504 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7505 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7508 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7512 g_hash_table_destroy (name_cache2);
7514 mono_image_lock (image);
7515 if (image->name_cache) {
7516 /* Somebody initialized it before us */
7517 g_hash_table_destroy (the_name_cache);
7519 mono_atomic_store_release (&image->name_cache, the_name_cache);
7521 mono_image_unlock (image);
7524 /*FIXME Only dynamic assemblies should allow this operation.*/
7526 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7527 const char *name, guint32 index)
7529 GHashTable *nspace_table;
7530 GHashTable *name_cache;
7533 mono_image_init_name_cache (image);
7534 mono_image_lock (image);
7536 name_cache = image->name_cache;
7537 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7538 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7539 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7542 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7543 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7545 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7547 mono_image_unlock (image);
7556 find_nocase (gpointer key, gpointer value, gpointer user_data)
7558 char *name = (char*)key;
7559 FindUserData *data = (FindUserData*)user_data;
7561 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7562 data->value = value;
7566 * mono_class_from_name_case:
7567 * @image: The MonoImage where the type is looked up in
7568 * @name_space: the type namespace
7569 * @name: the type short name.
7570 * @deprecated: use the _checked variant
7572 * Obtains a MonoClass with a given namespace and a given name which
7573 * is located in the given MonoImage. The namespace and name
7574 * lookups are case insensitive.
7577 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7580 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7581 g_assert (!mono_error_ok (&error));
7586 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7588 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7589 guint32 cols [MONO_TYPEDEF_SIZE];
7594 mono_error_init (error);
7596 if (image_is_dynamic (image)) {
7598 FindUserData user_data;
7600 mono_image_init_name_cache (image);
7601 mono_image_lock (image);
7603 user_data.key = name_space;
7604 user_data.value = NULL;
7605 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7607 if (user_data.value) {
7608 GHashTable *nspace_table = (GHashTable*)user_data.value;
7610 user_data.key = name;
7611 user_data.value = NULL;
7613 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7615 if (user_data.value)
7616 token = GPOINTER_TO_UINT (user_data.value);
7619 mono_image_unlock (image);
7622 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7628 /* add a cache if needed */
7629 for (i = 1; i <= t->rows; ++i) {
7630 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7631 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7633 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7634 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7636 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7638 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7639 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7640 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7641 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7647 return_nested_in (MonoClass *class, char *nested)
7650 char *s = strchr (nested, '/');
7651 gpointer iter = NULL;
7658 while ((found = mono_class_get_nested_types (class, &iter))) {
7659 if (strcmp (found->name, nested) == 0) {
7661 return return_nested_in (found, s);
7669 search_modules (MonoImage *image, const char *name_space, const char *name)
7671 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7672 MonoImage *file_image;
7677 * The EXPORTEDTYPES table only contains public types, so have to search the
7679 * Note: image->modules contains the contents of the MODULEREF table, while
7680 * the real module list is in the FILE table.
7682 for (i = 0; i < file_table->rows; i++) {
7683 guint32 cols [MONO_FILE_SIZE];
7684 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7685 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7688 file_image = mono_image_load_file_for_image (image, i + 1);
7690 class = mono_class_from_name (file_image, name_space, name);
7700 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7702 GHashTable *nspace_table;
7703 MonoImage *loaded_image;
7710 mono_error_init (error);
7712 // Checking visited images avoids stack overflows when cyclic references exist.
7713 if (g_hash_table_lookup (visited_images, image))
7716 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7718 if ((nested = strchr (name, '/'))) {
7719 int pos = nested - name;
7720 int len = strlen (name);
7723 memcpy (buf, name, len + 1);
7725 nested = buf + pos + 1;
7729 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7730 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7731 gboolean res = get_class_from_name (image, name_space, name, &class);
7734 class = search_modules (image, name_space, name);
7736 return class ? return_nested_in (class, nested) : NULL;
7742 mono_image_init_name_cache (image);
7743 mono_image_lock (image);
7745 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7748 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7750 mono_image_unlock (image);
7752 if (!token && image_is_dynamic (image) && image->modules) {
7753 /* Search modules as well */
7754 for (i = 0; i < image->module_count; ++i) {
7755 MonoImage *module = image->modules [i];
7757 class = mono_class_from_name (module, name_space, name);
7764 class = search_modules (image, name_space, name);
7772 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7773 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7774 guint32 cols [MONO_EXP_TYPE_SIZE];
7777 idx = mono_metadata_token_index (token);
7779 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7781 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7782 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7783 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7786 class = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7788 return return_nested_in (class, nested);
7790 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7791 guint32 assembly_idx;
7793 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7795 mono_assembly_load_reference (image, assembly_idx - 1);
7796 g_assert (image->references [assembly_idx - 1]);
7797 if (image->references [assembly_idx - 1] == (gpointer)-1)
7800 return mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7802 g_error ("not yet implemented");
7806 token = MONO_TOKEN_TYPE_DEF | token;
7808 class = mono_class_get_checked (image, token, error);
7810 return return_nested_in (class, nested);
7815 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7818 GHashTable *visited_images;
7820 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7822 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
7824 g_hash_table_destroy (visited_images);
7830 * mono_class_from_name:
7831 * @image: The MonoImage where the type is looked up in
7832 * @name_space: the type namespace
7833 * @name: the type short name.
7835 * Obtains a MonoClass with a given namespace and a given name which
7836 * is located in the given MonoImage.
7838 * To reference nested classes, use the "/" character as a separator.
7839 * For example use "Foo/Bar" to reference the class Bar that is nested
7840 * inside Foo, like this: "class Foo { class Bar {} }".
7843 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7848 klass = mono_class_from_name_checked (image, name_space, name, &error);
7849 if (!mono_error_ok (&error)) {
7850 mono_loader_set_error_from_mono_error (&error);
7851 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7857 * mono_class_is_subclass_of:
7858 * @klass: class to probe if it is a subclass of another one
7859 * @klassc: the class we suspect is the base class
7860 * @check_interfaces: whether we should perform interface checks
7862 * This method determines whether @klass is a subclass of @klassc.
7864 * If the @check_interfaces flag is set, then if @klassc is an interface
7865 * this method return true if the @klass implements the interface or
7866 * if @klass is an interface, if one of its base classes is @klass.
7868 * If @check_interfaces is false then, then if @klass is not an interface
7869 * then it returns true if the @klass is a subclass of @klassc.
7871 * if @klass is an interface and @klassc is System.Object, then this function
7876 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7877 gboolean check_interfaces)
7879 /*FIXME test for interfaces with variant generic arguments*/
7881 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7882 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7884 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7887 for (i = 0; i < klass->interface_count; i ++) {
7888 MonoClass *ic = klass->interfaces [i];
7893 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7898 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7901 if (klassc == mono_defaults.object_class)
7908 mono_type_is_generic_argument (MonoType *type)
7910 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7914 mono_class_has_variant_generic_params (MonoClass *klass)
7917 MonoGenericContainer *container;
7919 if (!klass->generic_class)
7922 container = klass->generic_class->container_class->generic_container;
7924 for (i = 0; i < container->type_argc; ++i)
7925 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7932 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7934 if (target == candidate)
7937 if (check_for_reference_conv &&
7938 mono_type_is_generic_argument (&target->byval_arg) &&
7939 mono_type_is_generic_argument (&candidate->byval_arg)) {
7940 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7941 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7943 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7946 if (!mono_class_is_assignable_from (target, candidate))
7952 * @container the generic container from the GTD
7953 * @klass: the class to be assigned to
7954 * @oklass: the source class
7956 * Both klass and oklass must be instances of the same generic interface.
7957 * Return true if @klass can be assigned to a @klass variable
7960 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7963 MonoType **klass_argv, **oklass_argv;
7964 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7965 MonoGenericContainer *container = klass_gtd->generic_container;
7967 if (klass == oklass)
7970 /*Viable candidates are instances of the same generic interface*/
7971 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7974 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7975 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7977 for (j = 0; j < container->type_argc; ++j) {
7978 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7979 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7981 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7985 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7986 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7988 if (param1_class != param2_class) {
7989 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7990 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7992 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7993 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8003 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8005 MonoGenericParam *gparam, *ogparam;
8006 MonoGenericParamInfo *tinfo, *cinfo;
8007 MonoClass **candidate_class;
8008 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8011 if (target == candidate)
8013 if (target->byval_arg.type != candidate->byval_arg.type)
8016 gparam = target->byval_arg.data.generic_param;
8017 ogparam = candidate->byval_arg.data.generic_param;
8018 tinfo = mono_generic_param_info (gparam);
8019 cinfo = mono_generic_param_info (ogparam);
8021 class_constraint_satisfied = FALSE;
8022 valuetype_constraint_satisfied = FALSE;
8024 /*candidate must have a super set of target's special constraints*/
8025 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8026 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8028 if (cinfo->constraints) {
8029 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8030 MonoClass *cc = *candidate_class;
8032 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8033 class_constraint_satisfied = TRUE;
8034 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8035 valuetype_constraint_satisfied = TRUE;
8038 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8039 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8041 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8043 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8045 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8046 valuetype_constraint_satisfied)) {
8051 /*candidate type constraints must be a superset of target's*/
8052 if (tinfo->constraints) {
8053 MonoClass **target_class;
8054 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8055 MonoClass *tc = *target_class;
8058 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8059 * check it's constraints since it satisfy the constraint by itself.
8061 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8064 if (!cinfo->constraints)
8067 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8068 MonoClass *cc = *candidate_class;
8070 if (mono_class_is_assignable_from (tc, cc))
8074 * This happens when we have the following:
8076 * Bar<K> where K : IFace
8077 * Foo<T, U> where T : U where U : IFace
8079 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8082 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8083 if (mono_gparam_is_assignable_from (target, cc))
8087 if (!*candidate_class)
8092 /*candidate itself must have a constraint that satisfy target*/
8093 if (cinfo->constraints) {
8094 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8095 MonoClass *cc = *candidate_class;
8096 if (mono_class_is_assignable_from (target, cc))
8104 * mono_class_is_assignable_from:
8105 * @klass: the class to be assigned to
8106 * @oklass: the source class
8108 * Return: true if an instance of object oklass can be assigned to an
8109 * instance of object @klass
8112 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8114 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8116 mono_class_init (klass);
8118 if (!oklass->inited)
8119 mono_class_init (oklass);
8121 if (klass->exception_type || oklass->exception_type)
8124 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8125 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8127 return mono_gparam_is_assignable_from (klass, oklass);
8130 if (MONO_CLASS_IS_INTERFACE (klass)) {
8131 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8132 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8133 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8137 for (i = 0; constraints [i]; ++i) {
8138 if (mono_class_is_assignable_from (klass, constraints [i]))
8146 /* interface_offsets might not be set for dynamic classes */
8147 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8149 * oklass might be a generic type parameter but they have
8150 * interface_offsets set.
8152 return mono_reflection_call_is_assignable_to (oklass, klass);
8153 if (!oklass->interface_bitmap)
8154 /* Happens with generic instances of not-yet created dynamic types */
8156 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8159 if (mono_class_has_variant_generic_params (klass)) {
8162 mono_class_setup_interfaces (oklass, &error);
8163 if (!mono_error_ok (&error)) {
8164 mono_error_cleanup (&error);
8168 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8169 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8170 MonoClass *iface = oklass->interfaces_packed [i];
8172 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8177 } else if (klass->delegate) {
8178 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8180 }else if (klass->rank) {
8181 MonoClass *eclass, *eoclass;
8183 if (oklass->rank != klass->rank)
8186 /* vectors vs. one dimensional arrays */
8187 if (oklass->byval_arg.type != klass->byval_arg.type)
8190 eclass = klass->cast_class;
8191 eoclass = oklass->cast_class;
8194 * a is b does not imply a[] is b[] when a is a valuetype, and
8195 * b is a reference type.
8198 if (eoclass->valuetype) {
8199 if ((eclass == mono_defaults.enum_class) ||
8200 (eclass == mono_defaults.enum_class->parent) ||
8201 (eclass == mono_defaults.object_class))
8205 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8206 } else if (mono_class_is_nullable (klass)) {
8207 if (mono_class_is_nullable (oklass))
8208 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8210 return mono_class_is_assignable_from (klass->cast_class, oklass);
8211 } else if (klass == mono_defaults.object_class)
8214 return mono_class_has_parent (oklass, klass);
8217 /*Check if @oklass is variant compatible with @klass.*/
8219 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8222 MonoType **klass_argv, **oklass_argv;
8223 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8224 MonoGenericContainer *container = klass_gtd->generic_container;
8226 /*Viable candidates are instances of the same generic interface*/
8227 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8230 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8231 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8233 for (j = 0; j < container->type_argc; ++j) {
8234 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8235 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8237 if (param1_class->valuetype != param2_class->valuetype)
8241 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8242 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8244 if (param1_class != param2_class) {
8245 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8246 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8248 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8249 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8257 /*Check if @candidate implements the interface @target*/
8259 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8263 gboolean is_variant = mono_class_has_variant_generic_params (target);
8265 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8266 if (mono_class_is_variant_compatible_slow (target, candidate))
8271 if (candidate == target)
8274 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8275 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8276 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8278 if (tb && tb->interfaces) {
8279 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8280 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8281 MonoClass *iface_class;
8283 /* we can't realize the type here since it can do pretty much anything. */
8286 iface_class = mono_class_from_mono_type (iface->type);
8287 if (iface_class == target)
8289 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8291 if (mono_class_implement_interface_slow (target, iface_class))
8296 /*setup_interfaces don't mono_class_init anything*/
8297 /*FIXME this doesn't handle primitive type arrays.
8298 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8299 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8301 mono_class_setup_interfaces (candidate, &error);
8302 if (!mono_error_ok (&error)) {
8303 mono_error_cleanup (&error);
8307 for (i = 0; i < candidate->interface_count; ++i) {
8308 if (candidate->interfaces [i] == target)
8311 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8314 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8318 candidate = candidate->parent;
8319 } while (candidate);
8325 * Check if @oklass can be assigned to @klass.
8326 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8329 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8331 if (candidate == target)
8333 if (target == mono_defaults.object_class)
8336 if (mono_class_has_parent (candidate, target))
8339 /*If target is not an interface there is no need to check them.*/
8340 if (MONO_CLASS_IS_INTERFACE (target))
8341 return mono_class_implement_interface_slow (target, candidate);
8343 if (target->delegate && mono_class_has_variant_generic_params (target))
8344 return mono_class_is_variant_compatible (target, candidate, FALSE);
8347 MonoClass *eclass, *eoclass;
8349 if (target->rank != candidate->rank)
8352 /* vectors vs. one dimensional arrays */
8353 if (target->byval_arg.type != candidate->byval_arg.type)
8356 eclass = target->cast_class;
8357 eoclass = candidate->cast_class;
8360 * a is b does not imply a[] is b[] when a is a valuetype, and
8361 * b is a reference type.
8364 if (eoclass->valuetype) {
8365 if ((eclass == mono_defaults.enum_class) ||
8366 (eclass == mono_defaults.enum_class->parent) ||
8367 (eclass == mono_defaults.object_class))
8371 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8373 /*FIXME properly handle nullables */
8374 /*FIXME properly handle (M)VAR */
8379 * mono_class_get_cctor:
8380 * @klass: A MonoClass pointer
8382 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8385 mono_class_get_cctor (MonoClass *klass)
8387 MonoCachedClassInfo cached_info;
8389 if (image_is_dynamic (klass->image)) {
8391 * has_cctor is not set for these classes because mono_class_init () is
8394 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8397 if (!klass->has_cctor)
8400 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8402 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8403 if (!mono_error_ok (&error))
8404 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8408 if (klass->generic_class && !klass->methods)
8409 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8411 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8415 * mono_class_get_finalizer:
8416 * @klass: The MonoClass pointer
8418 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8421 mono_class_get_finalizer (MonoClass *klass)
8423 MonoCachedClassInfo cached_info;
8426 mono_class_init (klass);
8427 if (!mono_class_has_finalizer (klass))
8430 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8432 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8433 if (!mono_error_ok (&error))
8434 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8437 mono_class_setup_vtable (klass);
8438 return klass->vtable [finalize_slot];
8443 * mono_class_needs_cctor_run:
8444 * @klass: the MonoClass pointer
8445 * @caller: a MonoMethod describing the caller
8447 * Determines whenever the class has a static constructor and whenever it
8448 * needs to be called when executing CALLER.
8451 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8455 method = mono_class_get_cctor (klass);
8457 return (method == caller) ? FALSE : TRUE;
8463 * mono_class_array_element_size:
8466 * Returns: the number of bytes an element of type @klass
8467 * uses when stored into an array.
8470 mono_class_array_element_size (MonoClass *klass)
8472 MonoType *type = &klass->byval_arg;
8475 switch (type->type) {
8478 case MONO_TYPE_BOOLEAN:
8482 case MONO_TYPE_CHAR:
8491 case MONO_TYPE_CLASS:
8492 case MONO_TYPE_STRING:
8493 case MONO_TYPE_OBJECT:
8494 case MONO_TYPE_SZARRAY:
8495 case MONO_TYPE_ARRAY:
8496 return sizeof (gpointer);
8501 case MONO_TYPE_VALUETYPE:
8502 if (type->data.klass->enumtype) {
8503 type = mono_class_enum_basetype (type->data.klass);
8504 klass = klass->element_class;
8507 return mono_class_instance_size (klass) - sizeof (MonoObject);
8508 case MONO_TYPE_GENERICINST:
8509 type = &type->data.generic_class->container_class->byval_arg;
8512 case MONO_TYPE_MVAR: {
8515 return mono_type_size (type, &align);
8517 case MONO_TYPE_VOID:
8521 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8527 * mono_array_element_size:
8528 * @ac: pointer to a #MonoArrayClass
8530 * Returns: the size of single array element.
8533 mono_array_element_size (MonoClass *ac)
8535 g_assert (ac->rank);
8536 return ac->sizes.element_size;
8540 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8541 MonoGenericContext *context)
8544 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8545 g_assert (mono_error_ok (&error));
8550 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8551 MonoGenericContext *context, MonoError *error)
8553 mono_error_init (error);
8555 if (image_is_dynamic (image)) {
8556 MonoClass *tmp_handle_class;
8557 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8559 g_assert (tmp_handle_class);
8561 *handle_class = tmp_handle_class;
8563 if (tmp_handle_class == mono_defaults.typehandle_class)
8564 return &((MonoClass*)obj)->byval_arg;
8569 switch (token & 0xff000000) {
8570 case MONO_TOKEN_TYPE_DEF:
8571 case MONO_TOKEN_TYPE_REF:
8572 case MONO_TOKEN_TYPE_SPEC: {
8575 *handle_class = mono_defaults.typehandle_class;
8576 type = mono_type_get_checked (image, token, context, error);
8580 mono_class_init (mono_class_from_mono_type (type));
8581 /* We return a MonoType* as handle */
8584 case MONO_TOKEN_FIELD_DEF: {
8586 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8588 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8592 *handle_class = mono_defaults.fieldhandle_class;
8593 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8597 mono_class_init (class);
8598 return mono_class_get_field (class, token);
8600 case MONO_TOKEN_METHOD_DEF:
8601 case MONO_TOKEN_METHOD_SPEC: {
8603 meth = mono_get_method_checked (image, token, NULL, context, error);
8605 *handle_class = mono_defaults.methodhandle_class;
8611 case MONO_TOKEN_MEMBER_REF: {
8612 guint32 cols [MONO_MEMBERREF_SIZE];
8614 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8615 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8616 mono_metadata_decode_blob_size (sig, &sig);
8617 if (*sig == 0x6) { /* it's a field */
8619 MonoClassField *field;
8620 field = mono_field_from_token_checked (image, token, &klass, context, error);
8622 *handle_class = mono_defaults.fieldhandle_class;
8626 meth = mono_get_method_checked (image, token, NULL, context, error);
8628 *handle_class = mono_defaults.methodhandle_class;
8633 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8639 * This function might need to call runtime functions so it can't be part
8640 * of the metadata library.
8642 static MonoLookupDynamicToken lookup_dynamic = NULL;
8645 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8647 lookup_dynamic = func;
8651 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8653 MonoClass *handle_class;
8655 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8659 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8661 return lookup_dynamic (image, token, valid_token, handle_class, context);
8664 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8667 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8669 get_cached_class_info = func;
8673 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8675 if (!get_cached_class_info)
8678 return get_cached_class_info (klass, res);
8682 mono_install_get_class_from_name (MonoGetClassFromName func)
8684 get_class_from_name = func;
8688 mono_class_get_image (MonoClass *klass)
8690 return klass->image;
8694 * mono_class_get_element_class:
8695 * @klass: the MonoClass to act on
8697 * Returns: the element class of an array or an enumeration.
8700 mono_class_get_element_class (MonoClass *klass)
8702 return klass->element_class;
8706 * mono_class_is_valuetype:
8707 * @klass: the MonoClass to act on
8709 * Returns: true if the MonoClass represents a ValueType.
8712 mono_class_is_valuetype (MonoClass *klass)
8714 return klass->valuetype;
8718 * mono_class_is_enum:
8719 * @klass: the MonoClass to act on
8721 * Returns: true if the MonoClass represents an enumeration.
8724 mono_class_is_enum (MonoClass *klass)
8726 return klass->enumtype;
8730 * mono_class_enum_basetype:
8731 * @klass: the MonoClass to act on
8733 * Returns: the underlying type representation for an enumeration.
8736 mono_class_enum_basetype (MonoClass *klass)
8738 if (klass->element_class == klass)
8739 /* SRE or broken types */
8742 return &klass->element_class->byval_arg;
8746 * mono_class_get_parent
8747 * @klass: the MonoClass to act on
8749 * Returns: the parent class for this class.
8752 mono_class_get_parent (MonoClass *klass)
8754 return klass->parent;
8758 * mono_class_get_nesting_type;
8759 * @klass: the MonoClass to act on
8761 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8764 mono_class_get_nesting_type (MonoClass *klass)
8766 return klass->nested_in;
8770 * mono_class_get_rank:
8771 * @klass: the MonoClass to act on
8773 * Returns: the rank for the array (the number of dimensions).
8776 mono_class_get_rank (MonoClass *klass)
8782 * mono_class_get_flags:
8783 * @klass: the MonoClass to act on
8785 * The type flags from the TypeDef table from the metadata.
8786 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8789 * Returns: the flags from the TypeDef table.
8792 mono_class_get_flags (MonoClass *klass)
8794 return klass->flags;
8798 * mono_class_get_name
8799 * @klass: the MonoClass to act on
8801 * Returns: the name of the class.
8804 mono_class_get_name (MonoClass *klass)
8810 * mono_class_get_namespace:
8811 * @klass: the MonoClass to act on
8813 * Returns: the namespace of the class.
8816 mono_class_get_namespace (MonoClass *klass)
8818 return klass->name_space;
8822 * mono_class_get_type:
8823 * @klass: the MonoClass to act on
8825 * This method returns the internal Type representation for the class.
8827 * Returns: the MonoType from the class.
8830 mono_class_get_type (MonoClass *klass)
8832 return &klass->byval_arg;
8836 * mono_class_get_type_token
8837 * @klass: the MonoClass to act on
8839 * This method returns type token for the class.
8841 * Returns: the type token for the class.
8844 mono_class_get_type_token (MonoClass *klass)
8846 return klass->type_token;
8850 * mono_class_get_byref_type:
8851 * @klass: the MonoClass to act on
8856 mono_class_get_byref_type (MonoClass *klass)
8858 return &klass->this_arg;
8862 * mono_class_num_fields:
8863 * @klass: the MonoClass to act on
8865 * Returns: the number of static and instance fields in the class.
8868 mono_class_num_fields (MonoClass *klass)
8870 return klass->field.count;
8874 * mono_class_num_methods:
8875 * @klass: the MonoClass to act on
8877 * Returns: the number of methods in the class.
8880 mono_class_num_methods (MonoClass *klass)
8882 return klass->method.count;
8886 * mono_class_num_properties
8887 * @klass: the MonoClass to act on
8889 * Returns: the number of properties in the class.
8892 mono_class_num_properties (MonoClass *klass)
8894 mono_class_setup_properties (klass);
8896 return klass->ext->property.count;
8900 * mono_class_num_events:
8901 * @klass: the MonoClass to act on
8903 * Returns: the number of events in the class.
8906 mono_class_num_events (MonoClass *klass)
8908 mono_class_setup_events (klass);
8910 return klass->ext->event.count;
8914 * mono_class_get_fields:
8915 * @klass: the MonoClass to act on
8917 * This routine is an iterator routine for retrieving the fields in a class.
8919 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8920 * iterate over all of the elements. When no more values are
8921 * available, the return value is NULL.
8923 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8926 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8928 MonoClassField* field;
8932 mono_class_setup_fields_locking (klass);
8933 if (klass->exception_type)
8935 /* start from the first */
8936 if (klass->field.count) {
8937 return *iter = &klass->fields [0];
8945 if (field < &klass->fields [klass->field.count]) {
8946 return *iter = field;
8952 * mono_class_get_methods
8953 * @klass: the MonoClass to act on
8955 * This routine is an iterator routine for retrieving the fields in a class.
8957 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8958 * iterate over all of the elements. When no more values are
8959 * available, the return value is NULL.
8961 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8964 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8966 MonoMethod** method;
8970 mono_class_setup_methods (klass);
8973 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8974 * FIXME we should better report this error to the caller
8976 if (!klass->methods)
8978 /* start from the first */
8979 if (klass->method.count) {
8980 *iter = &klass->methods [0];
8981 return klass->methods [0];
8989 if (method < &klass->methods [klass->method.count]) {
8997 * mono_class_get_virtual_methods:
8999 * Iterate over the virtual methods of KLASS.
9001 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9004 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9006 MonoMethod** method;
9009 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9011 mono_class_setup_methods (klass);
9013 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9014 * FIXME we should better report this error to the caller
9016 if (!klass->methods)
9018 /* start from the first */
9019 method = &klass->methods [0];
9024 while (method < &klass->methods [klass->method.count]) {
9025 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9029 if (method < &klass->methods [klass->method.count]) {
9036 /* Search directly in metadata to avoid calling setup_methods () */
9037 MonoMethod *res = NULL;
9043 start_index = GPOINTER_TO_UINT (*iter);
9046 for (i = start_index; i < klass->method.count; ++i) {
9049 /* class->method.first points into the methodptr table */
9050 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9052 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9056 if (i < klass->method.count) {
9058 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9059 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9061 /* Add 1 here so the if (*iter) check fails */
9062 *iter = GUINT_TO_POINTER (i + 1);
9071 * mono_class_get_properties:
9072 * @klass: the MonoClass to act on
9074 * This routine is an iterator routine for retrieving the properties in a class.
9076 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9077 * iterate over all of the elements. When no more values are
9078 * available, the return value is NULL.
9080 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9083 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9085 MonoProperty* property;
9089 mono_class_setup_properties (klass);
9090 /* start from the first */
9091 if (klass->ext->property.count) {
9092 return *iter = &klass->ext->properties [0];
9100 if (property < &klass->ext->properties [klass->ext->property.count]) {
9101 return *iter = property;
9107 * mono_class_get_events:
9108 * @klass: the MonoClass to act on
9110 * This routine is an iterator routine for retrieving the properties in a class.
9112 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9113 * iterate over all of the elements. When no more values are
9114 * available, the return value is NULL.
9116 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9119 mono_class_get_events (MonoClass* klass, gpointer *iter)
9125 mono_class_setup_events (klass);
9126 /* start from the first */
9127 if (klass->ext->event.count) {
9128 return *iter = &klass->ext->events [0];
9136 if (event < &klass->ext->events [klass->ext->event.count]) {
9137 return *iter = event;
9143 * mono_class_get_interfaces
9144 * @klass: the MonoClass to act on
9146 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9148 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9149 * iterate over all of the elements. When no more values are
9150 * available, the return value is NULL.
9152 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9155 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9163 mono_class_init (klass);
9164 if (!klass->interfaces_inited) {
9165 mono_class_setup_interfaces (klass, &error);
9166 if (!mono_error_ok (&error)) {
9167 mono_error_cleanup (&error);
9171 /* start from the first */
9172 if (klass->interface_count) {
9173 *iter = &klass->interfaces [0];
9174 return klass->interfaces [0];
9182 if (iface < &klass->interfaces [klass->interface_count]) {
9190 setup_nested_types (MonoClass *klass)
9193 GList *classes, *nested_classes, *l;
9196 if (klass->nested_classes_inited)
9199 if (!klass->type_token)
9200 klass->nested_classes_inited = TRUE;
9202 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9206 guint32 cols [MONO_NESTED_CLASS_SIZE];
9207 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9208 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9209 if (!mono_error_ok (&error)) {
9210 /*FIXME don't swallow the error message*/
9211 mono_error_cleanup (&error);
9213 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9217 classes = g_list_prepend (classes, nclass);
9219 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9222 mono_class_alloc_ext (klass);
9224 nested_classes = NULL;
9225 for (l = classes; l; l = l->next)
9226 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9227 g_list_free (classes);
9229 mono_image_lock (klass->image);
9231 mono_memory_barrier ();
9232 if (!klass->nested_classes_inited) {
9233 klass->ext->nested_classes = nested_classes;
9234 mono_memory_barrier ();
9235 klass->nested_classes_inited = TRUE;
9238 mono_image_unlock (klass->image);
9242 * mono_class_get_nested_types
9243 * @klass: the MonoClass to act on
9245 * This routine is an iterator routine for retrieving the nested types of a class.
9246 * This works only if @klass is non-generic, or a generic type definition.
9248 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9249 * iterate over all of the elements. When no more values are
9250 * available, the return value is NULL.
9252 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9255 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9261 if (!klass->nested_classes_inited)
9262 setup_nested_types (klass);
9265 /* start from the first */
9266 if (klass->ext && klass->ext->nested_classes) {
9267 *iter = klass->ext->nested_classes;
9268 return klass->ext->nested_classes->data;
9270 /* no nested types */
9285 * mono_class_is_delegate
9286 * @klass: the MonoClass to act on
9288 * Returns: true if the MonoClass represents a System.Delegate.
9291 mono_class_is_delegate (MonoClass *klass)
9293 return klass->delegate;
9297 * mono_class_implements_interface
9298 * @klass: The MonoClass to act on
9299 * @interface: The interface to check if @klass implements.
9301 * Returns: true if @klass implements @interface.
9304 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9306 return mono_class_is_assignable_from (iface, klass);
9310 * mono_field_get_name:
9311 * @field: the MonoClassField to act on
9313 * Returns: the name of the field.
9316 mono_field_get_name (MonoClassField *field)
9322 * mono_field_get_type:
9323 * @field: the MonoClassField to act on
9325 * Returns: MonoType of the field.
9328 mono_field_get_type (MonoClassField *field)
9331 MonoType *type = mono_field_get_type_checked (field, &error);
9332 if (!mono_error_ok (&error)) {
9333 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9334 mono_error_cleanup (&error);
9341 * mono_field_get_type_checked:
9342 * @field: the MonoClassField to act on
9343 * @error: used to return any erro found while retrieving @field type
9345 * Returns: MonoType of the field.
9348 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9350 mono_error_init (error);
9352 mono_field_resolve_type (field, error);
9357 * mono_field_get_parent:
9358 * @field: the MonoClassField to act on
9360 * Returns: MonoClass where the field was defined.
9363 mono_field_get_parent (MonoClassField *field)
9365 return field->parent;
9369 * mono_field_get_flags;
9370 * @field: the MonoClassField to act on
9372 * The metadata flags for a field are encoded using the
9373 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9375 * Returns: the flags for the field.
9378 mono_field_get_flags (MonoClassField *field)
9381 return mono_field_resolve_flags (field);
9382 return field->type->attrs;
9386 * mono_field_get_offset;
9387 * @field: the MonoClassField to act on
9389 * Returns: the field offset.
9392 mono_field_get_offset (MonoClassField *field)
9394 return field->offset;
9398 mono_field_get_rva (MonoClassField *field)
9402 MonoClass *klass = field->parent;
9403 MonoFieldDefaultValue *field_def_values;
9405 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9407 if (!klass->ext || !klass->ext->field_def_values) {
9408 mono_class_alloc_ext (klass);
9410 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9412 mono_image_lock (klass->image);
9413 if (!klass->ext->field_def_values)
9414 klass->ext->field_def_values = field_def_values;
9415 mono_image_unlock (klass->image);
9418 field_index = mono_field_get_index (field);
9420 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9421 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9423 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9424 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9427 return klass->ext->field_def_values [field_index].data;
9431 * mono_field_get_data;
9432 * @field: the MonoClassField to act on
9434 * Returns: pointer to the metadata constant value or to the field
9435 * data if it has an RVA flag.
9438 mono_field_get_data (MonoClassField *field)
9440 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9441 MonoTypeEnum def_type;
9443 return mono_class_get_field_default_value (field, &def_type);
9444 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9445 return mono_field_get_rva (field);
9452 * mono_property_get_name:
9453 * @prop: the MonoProperty to act on
9455 * Returns: the name of the property
9458 mono_property_get_name (MonoProperty *prop)
9464 * mono_property_get_set_method
9465 * @prop: the MonoProperty to act on.
9467 * Returns: the setter method of the property (A MonoMethod)
9470 mono_property_get_set_method (MonoProperty *prop)
9476 * mono_property_get_get_method
9477 * @prop: the MonoProperty to act on.
9479 * Returns: the setter method of the property (A MonoMethod)
9482 mono_property_get_get_method (MonoProperty *prop)
9488 * mono_property_get_parent:
9489 * @prop: the MonoProperty to act on.
9491 * Returns: the MonoClass where the property was defined.
9494 mono_property_get_parent (MonoProperty *prop)
9496 return prop->parent;
9500 * mono_property_get_flags:
9501 * @prop: the MonoProperty to act on.
9503 * The metadata flags for a property are encoded using the
9504 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9506 * Returns: the flags for the property.
9509 mono_property_get_flags (MonoProperty *prop)
9515 * mono_event_get_name:
9516 * @event: the MonoEvent to act on
9518 * Returns: the name of the event.
9521 mono_event_get_name (MonoEvent *event)
9527 * mono_event_get_add_method:
9528 * @event: The MonoEvent to act on.
9530 * Returns: the @add' method for the event (a MonoMethod).
9533 mono_event_get_add_method (MonoEvent *event)
9539 * mono_event_get_remove_method:
9540 * @event: The MonoEvent to act on.
9542 * Returns: the @remove method for the event (a MonoMethod).
9545 mono_event_get_remove_method (MonoEvent *event)
9547 return event->remove;
9551 * mono_event_get_raise_method:
9552 * @event: The MonoEvent to act on.
9554 * Returns: the @raise method for the event (a MonoMethod).
9557 mono_event_get_raise_method (MonoEvent *event)
9559 return event->raise;
9563 * mono_event_get_parent:
9564 * @event: the MonoEvent to act on.
9566 * Returns: the MonoClass where the event is defined.
9569 mono_event_get_parent (MonoEvent *event)
9571 return event->parent;
9575 * mono_event_get_flags
9576 * @event: the MonoEvent to act on.
9578 * The metadata flags for an event are encoded using the
9579 * EVENT_* constants. See the tabledefs.h file for details.
9581 * Returns: the flags for the event.
9584 mono_event_get_flags (MonoEvent *event)
9586 return event->attrs;
9590 * mono_class_get_method_from_name:
9591 * @klass: where to look for the method
9592 * @name: name of the method
9593 * @param_count: number of parameters. -1 for any number.
9595 * Obtains a MonoMethod with a given name and number of parameters.
9596 * It only works if there are no multiple signatures for any given method name.
9599 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9601 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9605 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9607 MonoMethod *res = NULL;
9610 /* Search directly in the metadata to avoid calling setup_methods () */
9611 for (i = 0; i < klass->method.count; ++i) {
9613 guint32 cols [MONO_METHOD_SIZE];
9615 MonoMethodSignature *sig;
9617 /* class->method.first points into the methodptr table */
9618 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9620 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9621 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9623 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9626 if (param_count == -1) {
9630 sig = mono_method_signature_checked (method, &error);
9632 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9635 if (sig->param_count == param_count) {
9646 * mono_class_get_method_from_name_flags:
9647 * @klass: where to look for the method
9648 * @name_space: name of the method
9649 * @param_count: number of parameters. -1 for any number.
9650 * @flags: flags which must be set in the method
9652 * Obtains a MonoMethod with a given name and number of parameters.
9653 * It only works if there are no multiple signatures for any given method name.
9656 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9658 MonoMethod *res = NULL;
9661 mono_class_init (klass);
9663 if (klass->generic_class && !klass->methods) {
9664 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9667 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9668 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9673 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9674 mono_class_setup_methods (klass);
9676 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9677 See mono/tests/array_load_exception.il
9678 FIXME we should better report this error to the caller
9680 if (!klass->methods)
9682 for (i = 0; i < klass->method.count; ++i) {
9683 MonoMethod *method = klass->methods [i];
9685 if (method->name[0] == name [0] &&
9686 !strcmp (name, method->name) &&
9687 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9688 ((method->flags & flags) == flags)) {
9695 res = find_method_in_metadata (klass, name, param_count, flags);
9702 * mono_class_set_failure:
9703 * @klass: class in which the failure was detected
9704 * @ex_type: the kind of exception/error to be thrown (later)
9705 * @ex_data: exception data (specific to each type of exception/error)
9707 * Keep a detected failure informations in the class for later processing.
9708 * Note that only the first failure is kept.
9710 * LOCKING: Acquires the loader lock.
9713 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9715 if (klass->exception_type)
9718 mono_loader_lock ();
9719 klass->exception_type = ex_type;
9721 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9722 mono_loader_unlock ();
9728 * mono_class_get_exception_data:
9730 * Return the exception_data property of KLASS.
9732 * LOCKING: Acquires the loader lock.
9735 mono_class_get_exception_data (MonoClass *klass)
9737 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9741 * mono_classes_init:
9743 * Initialize the resources used by this module.
9746 mono_classes_init (void)
9748 mono_mutex_init (&classes_mutex);
9750 mono_counters_register ("Inflated methods size",
9751 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9752 mono_counters_register ("Inflated classes",
9753 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9754 mono_counters_register ("Inflated classes size",
9755 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9756 mono_counters_register ("MonoClass size",
9757 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9758 mono_counters_register ("MonoClassExt size",
9759 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9763 * mono_classes_cleanup:
9765 * Free the resources used by this module.
9768 mono_classes_cleanup (void)
9770 if (global_interface_bitset)
9771 mono_bitset_free (global_interface_bitset);
9772 global_interface_bitset = NULL;
9773 mono_mutex_destroy (&classes_mutex);
9777 * mono_class_get_exception_for_failure:
9778 * @klass: class in which the failure was detected
9780 * Return a constructed MonoException than the caller can then throw
9781 * using mono_raise_exception - or NULL if no failure is present (or
9782 * doesn't result in an exception).
9785 mono_class_get_exception_for_failure (MonoClass *klass)
9787 gpointer exception_data = mono_class_get_exception_data (klass);
9789 switch (klass->exception_type) {
9790 case MONO_EXCEPTION_TYPE_LOAD: {
9793 char *str = mono_type_get_full_name (klass);
9794 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9795 name = mono_string_new (mono_domain_get (), str);
9797 ex = mono_get_exception_type_load (name, astr);
9801 case MONO_EXCEPTION_MISSING_METHOD: {
9802 char *class_name = exception_data;
9803 char *assembly_name = class_name + strlen (class_name) + 1;
9805 return mono_get_exception_missing_method (class_name, assembly_name);
9807 case MONO_EXCEPTION_MISSING_FIELD: {
9808 char *class_name = exception_data;
9809 char *member_name = class_name + strlen (class_name) + 1;
9811 return mono_get_exception_missing_field (class_name, member_name);
9813 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9814 char *msg_format = exception_data;
9815 char *assembly_name = msg_format + strlen (msg_format) + 1;
9816 char *msg = g_strdup_printf (msg_format, assembly_name);
9819 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9825 case MONO_EXCEPTION_BAD_IMAGE: {
9826 return mono_get_exception_bad_image_format (exception_data);
9829 MonoLoaderError *error;
9832 error = mono_loader_get_last_error ();
9834 ex = mono_loader_error_prepare_exception (error);
9838 /* TODO - handle other class related failures */
9845 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9847 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9848 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9850 if (outer_klass == inner_klass)
9852 inner_klass = inner_klass->nested_in;
9853 } while (inner_klass);
9858 mono_class_get_generic_type_definition (MonoClass *klass)
9860 return klass->generic_class ? klass->generic_class->container_class : klass;
9864 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9866 * Generic instantiations are ignored for all super types of @klass.
9868 * Visibility checks ignoring generic instantiations.
9871 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9874 klass = mono_class_get_generic_type_definition (klass);
9875 parent = mono_class_get_generic_type_definition (parent);
9876 mono_class_setup_supertypes (klass);
9878 for (i = 0; i < klass->idepth; ++i) {
9879 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9885 * Subtype can only access parent members with family protection if the site object
9886 * is subclass of Subtype. For example:
9887 * class A { protected int x; }
9889 * void valid_access () {
9893 * void invalid_access () {
9900 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9902 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9905 if (context_klass == NULL)
9907 /*if access_klass is not member_klass context_klass must be type compat*/
9908 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9914 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9917 if (accessing == accessed)
9919 if (!accessed || !accessing)
9922 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9923 * anywhere so untrusted friends are not safe to access platform's code internals */
9924 if (mono_security_core_clr_enabled ()) {
9925 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9929 mono_assembly_load_friends (accessed);
9930 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9931 MonoAssemblyName *friend = tmp->data;
9932 /* Be conservative with checks */
9935 if (strcmp (accessing->aname.name, friend->name))
9937 if (friend->public_key_token [0]) {
9938 if (!accessing->aname.public_key_token [0])
9940 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9949 * If klass is a generic type or if it is derived from a generic type, return the
9950 * MonoClass of the generic definition
9951 * Returns NULL if not found
9954 get_generic_definition_class (MonoClass *klass)
9957 if (klass->generic_class && klass->generic_class->container_class)
9958 return klass->generic_class->container_class;
9959 klass = klass->parent;
9965 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9968 for (i = 0; i < ginst->type_argc; ++i) {
9969 MonoType *type = ginst->type_argv[i];
9970 switch (type->type) {
9971 case MONO_TYPE_SZARRAY:
9972 if (!can_access_type (access_klass, type->data.klass))
9975 case MONO_TYPE_ARRAY:
9976 if (!can_access_type (access_klass, type->data.array->eklass))
9980 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9983 case MONO_TYPE_CLASS:
9984 case MONO_TYPE_VALUETYPE:
9985 case MONO_TYPE_GENERICINST:
9986 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9996 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10000 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10003 if (access_klass->element_class && !access_klass->enumtype)
10004 access_klass = access_klass->element_class;
10006 if (member_klass->element_class && !member_klass->enumtype)
10007 member_klass = member_klass->element_class;
10009 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10011 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10014 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10017 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10020 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10023 /*Non nested type with nested visibility. We just fail it.*/
10024 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10027 switch (access_level) {
10028 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10029 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10031 case TYPE_ATTRIBUTE_PUBLIC:
10034 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10037 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10038 return is_nesting_type (member_klass, access_klass);
10040 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10041 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10043 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10044 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10046 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10047 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10048 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10050 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10051 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10052 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10057 /* FIXME: check visibility of type, too */
10059 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10061 MonoClass *member_generic_def;
10062 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10065 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10066 access_klass->generic_container) &&
10067 (member_generic_def = get_generic_definition_class (member_klass))) {
10068 MonoClass *access_container;
10070 if (access_klass->generic_container)
10071 access_container = access_klass;
10073 access_container = access_klass->generic_class->container_class;
10075 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10079 /* Partition I 8.5.3.2 */
10080 /* the access level values are the same for fields and methods */
10081 switch (access_level) {
10082 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10083 /* same compilation unit */
10084 return access_klass->image == member_klass->image;
10085 case FIELD_ATTRIBUTE_PRIVATE:
10086 return access_klass == member_klass;
10087 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10088 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10089 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10092 case FIELD_ATTRIBUTE_ASSEMBLY:
10093 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10094 case FIELD_ATTRIBUTE_FAMILY:
10095 if (is_valid_family_access (access_klass, member_klass, context_klass))
10098 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10099 if (is_valid_family_access (access_klass, member_klass, context_klass))
10101 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10102 case FIELD_ATTRIBUTE_PUBLIC:
10109 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10111 /* FIXME: check all overlapping fields */
10112 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10114 MonoClass *nested = method->klass->nested_in;
10116 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10119 nested = nested->nested_in;
10126 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10128 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10130 MonoClass *nested = method->klass->nested_in;
10132 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10135 nested = nested->nested_in;
10140 * with generics calls to explicit interface implementations can be expressed
10141 * directly: the method is private, but we must allow it. This may be opening
10142 * a hole or the generics code should handle this differently.
10143 * Maybe just ensure the interface type is public.
10145 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10151 * mono_method_can_access_method_full:
10152 * @method: The caller method
10153 * @called: The called method
10154 * @context_klass: The static type on stack of the owner @called object used
10156 * This function must be used with instance calls, as they have more strict family accessibility.
10157 * It can be used with static methods, but context_klass should be NULL.
10159 * Returns: TRUE if caller have proper visibility and acessibility to @called
10162 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10164 MonoClass *access_class = method->klass;
10165 MonoClass *member_class = called->klass;
10166 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10168 MonoClass *nested = access_class->nested_in;
10170 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10173 nested = nested->nested_in;
10180 can = can_access_type (access_class, member_class);
10182 MonoClass *nested = access_class->nested_in;
10184 can = can_access_type (nested, member_class);
10187 nested = nested->nested_in;
10194 if (called->is_inflated) {
10195 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10196 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10205 * mono_method_can_access_field_full:
10206 * @method: The caller method
10207 * @field: The accessed field
10208 * @context_klass: The static type on stack of the owner @field object used
10210 * This function must be used with instance fields, as they have more strict family accessibility.
10211 * It can be used with static fields, but context_klass should be NULL.
10213 * Returns: TRUE if caller have proper visibility and acessibility to @field
10216 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10218 MonoClass *access_class = method->klass;
10219 MonoClass *member_class = field->parent;
10220 /* FIXME: check all overlapping fields */
10221 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10223 MonoClass *nested = access_class->nested_in;
10225 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10228 nested = nested->nested_in;
10235 can = can_access_type (access_class, member_class);
10237 MonoClass *nested = access_class->nested_in;
10239 can = can_access_type (nested, member_class);
10242 nested = nested->nested_in;
10252 * mono_class_can_access_class:
10253 * @source_class: The source class
10254 * @target_class: The accessed class
10256 * This function returns is @target_class is visible to @source_class
10258 * Returns: TRUE if source have proper visibility and acessibility to target
10261 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10263 return can_access_type (source_class, target_class);
10267 * mono_type_is_valid_enum_basetype:
10268 * @type: The MonoType to check
10270 * Returns: TRUE if the type can be used as the basetype of an enum
10272 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10273 switch (type->type) {
10276 case MONO_TYPE_BOOLEAN:
10279 case MONO_TYPE_CHAR:
10293 * mono_class_is_valid_enum:
10294 * @klass: An enum class to be validated
10296 * This method verify the required properties an enum should have.
10298 * Returns: TRUE if the informed enum class is valid
10300 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10301 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10302 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10304 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10305 MonoClassField * field;
10306 gpointer iter = NULL;
10307 gboolean found_base_field = FALSE;
10309 g_assert (klass->enumtype);
10310 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10311 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10315 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10318 while ((field = mono_class_get_fields (klass, &iter))) {
10319 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10320 if (found_base_field)
10322 found_base_field = TRUE;
10323 if (!mono_type_is_valid_enum_basetype (field->type))
10328 if (!found_base_field)
10331 if (klass->method.count > 0)
10338 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10340 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10344 * mono_class_setup_interface_id:
10346 * Initializes MonoClass::interface_id if required.
10348 * LOCKING: Acquires the loader lock.
10351 mono_class_setup_interface_id (MonoClass *class)
10353 mono_loader_lock ();
10354 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10355 class->interface_id = mono_get_unique_iid (class);
10356 mono_loader_unlock ();
10360 * mono_class_alloc_ext:
10362 * Allocate klass->ext if not already done.
10365 mono_class_alloc_ext (MonoClass *klass)
10372 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10373 mono_image_lock (klass->image);
10374 mono_memory_barrier ();
10377 class_ext_size += sizeof (MonoClassExt);
10378 mono_image_unlock (klass->image);
10382 * mono_class_setup_interfaces:
10384 * Initialize class->interfaces/interfaces_count.
10385 * LOCKING: Acquires the loader lock.
10386 * This function can fail the type.
10389 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10391 int i, interface_count;
10392 MonoClass **interfaces;
10394 mono_error_init (error);
10396 if (klass->interfaces_inited)
10399 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10400 MonoType *args [1];
10402 /* generic IList, ICollection, IEnumerable */
10403 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10404 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10406 args [0] = &klass->element_class->byval_arg;
10407 interfaces [0] = mono_class_bind_generic_parameters (
10408 mono_defaults.generic_ilist_class, 1, args, FALSE);
10409 if (interface_count > 1)
10410 interfaces [1] = mono_class_bind_generic_parameters (
10411 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10412 } else if (klass->generic_class) {
10413 MonoClass *gklass = klass->generic_class->container_class;
10415 mono_class_setup_interfaces (gklass, error);
10416 if (!mono_error_ok (error)) {
10417 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10421 interface_count = gklass->interface_count;
10422 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10423 for (i = 0; i < interface_count; i++) {
10424 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10425 if (!mono_error_ok (error)) {
10426 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10431 interface_count = 0;
10435 mono_image_lock (klass->image);
10437 if (!klass->interfaces_inited) {
10438 klass->interface_count = interface_count;
10439 klass->interfaces = interfaces;
10441 mono_memory_barrier ();
10443 klass->interfaces_inited = TRUE;
10446 mono_image_unlock (klass->image);
10450 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10452 MonoClass *class = field->parent;
10453 MonoImage *image = class->image;
10454 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10455 int field_idx = field - class->fields;
10457 mono_error_init (error);
10460 MonoClassField *gfield = >d->fields [field_idx];
10461 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10462 if (!mono_error_ok (error)) {
10463 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10464 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10468 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10469 if (!mono_error_ok (error)) {
10470 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10471 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10476 guint32 cols [MONO_FIELD_SIZE];
10477 MonoGenericContainer *container = NULL;
10478 int idx = class->field.first + field_idx;
10480 /*FIXME, in theory we do not lazy load SRE fields*/
10481 g_assert (!image_is_dynamic (image));
10483 if (class->generic_container) {
10484 container = class->generic_container;
10486 container = gtd->generic_container;
10487 g_assert (container);
10490 /* class->field.first and idx points into the fieldptr table */
10491 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10493 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10494 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10495 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10499 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10501 mono_metadata_decode_value (sig, &sig);
10502 /* FIELD signature == 0x06 */
10503 g_assert (*sig == 0x06);
10504 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10506 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10511 mono_field_resolve_flags (MonoClassField *field)
10513 MonoClass *class = field->parent;
10514 MonoImage *image = class->image;
10515 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10516 int field_idx = field - class->fields;
10520 MonoClassField *gfield = >d->fields [field_idx];
10521 return mono_field_get_flags (gfield);
10523 int idx = class->field.first + field_idx;
10525 /*FIXME, in theory we do not lazy load SRE fields*/
10526 g_assert (!image_is_dynamic (image));
10528 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10533 * mono_class_setup_basic_field_info:
10534 * @class: The class to initialize
10536 * Initializes the class->fields array of fields.
10537 * Aquires the loader lock.
10540 mono_class_setup_basic_field_info_locking (MonoClass *class)
10542 mono_loader_lock ();
10543 mono_class_setup_basic_field_info (class);
10544 mono_loader_unlock ();
10548 * mono_class_get_fields_lazy:
10549 * @klass: the MonoClass to act on
10551 * This routine is an iterator routine for retrieving the fields in a class.
10552 * Only minimal information about fields are loaded. Accessors must be used
10553 * for all MonoClassField returned.
10555 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10556 * iterate over all of the elements. When no more values are
10557 * available, the return value is NULL.
10559 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10562 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10564 MonoClassField* field;
10568 mono_class_setup_basic_field_info_locking (klass);
10569 if (!klass->fields)
10571 /* start from the first */
10572 if (klass->field.count) {
10573 return *iter = &klass->fields [0];
10581 if (field < &klass->fields [klass->field.count]) {
10582 return *iter = field;
10588 mono_class_full_name (MonoClass *klass)
10590 return mono_type_full_name (&klass->byval_arg);