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;
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))
2069 // Special static fields do not need a domain-level static slot
2070 if (mono_class_field_is_special_static (field))
2073 if (mono_type_has_exceptions (field->type)) {
2074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2078 has_static_fields = TRUE;
2080 size = mono_type_size (field->type, &align);
2081 field->offset = class->sizes.class_size;
2082 /*align is always non-zero here*/
2083 field->offset += align - 1;
2084 field->offset &= ~(align - 1);
2085 class->sizes.class_size = field->offset + size;
2088 if (has_static_fields && class->sizes.class_size == 0)
2089 /* Simplify code which depends on class_size != 0 if the class has static fields */
2090 class->sizes.class_size = 8;
2094 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2098 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2099 method->klass = class;
2100 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2101 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2102 method->signature = sig;
2103 method->name = name;
2106 if (name [0] == '.') {
2107 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2109 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2115 * mono_class_setup_methods:
2118 * Initializes the 'methods' array in CLASS.
2119 * Calling this method should be avoided if possible since it allocates a lot
2120 * of long-living MonoMethod structures.
2121 * Methods belonging to an interface are assigned a sequential slot starting
2124 * On failure this function sets class->exception_type
2127 mono_class_setup_methods (MonoClass *class)
2130 MonoMethod **methods;
2135 if (class->generic_class) {
2137 MonoClass *gklass = class->generic_class->container_class;
2139 mono_class_init (gklass);
2140 if (!gklass->exception_type)
2141 mono_class_setup_methods (gklass);
2142 if (gklass->exception_type) {
2143 /* FIXME make exception_data less opaque so it's possible to dup it here */
2144 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2148 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2149 count = gklass->method.count;
2150 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2152 for (i = 0; i < count; i++) {
2153 methods [i] = mono_class_inflate_generic_method_full_checked (
2154 gklass->methods [i], class, mono_class_get_context (class), &error);
2155 if (!mono_error_ok (&error)) {
2156 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2157 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)));
2160 mono_error_cleanup (&error);
2164 } else if (class->rank) {
2166 MonoMethod *amethod;
2167 MonoMethodSignature *sig;
2168 int count_generic = 0, first_generic = 0;
2170 gboolean jagged_ctor = FALSE;
2172 count = 3 + (class->rank > 1? 2: 1);
2174 mono_class_setup_interfaces (class, &error);
2175 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2177 if (class->rank == 1 && class->element_class->rank) {
2179 class->method.count ++;
2182 if (class->interface_count) {
2183 count_generic = generic_array_methods (class);
2184 first_generic = count;
2185 count += class->interface_count * count_generic;
2188 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2190 sig = mono_metadata_signature_alloc (class->image, class->rank);
2191 sig->ret = &mono_defaults.void_class->byval_arg;
2192 sig->pinvoke = TRUE;
2193 sig->hasthis = TRUE;
2194 for (i = 0; i < class->rank; ++i)
2195 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2197 amethod = create_array_method (class, ".ctor", sig);
2198 methods [method_num++] = amethod;
2199 if (class->rank > 1) {
2200 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2201 sig->ret = &mono_defaults.void_class->byval_arg;
2202 sig->pinvoke = TRUE;
2203 sig->hasthis = TRUE;
2204 for (i = 0; i < class->rank * 2; ++i)
2205 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2207 amethod = create_array_method (class, ".ctor", sig);
2208 methods [method_num++] = amethod;
2212 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2213 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2214 sig->ret = &mono_defaults.void_class->byval_arg;
2215 sig->pinvoke = TRUE;
2216 sig->hasthis = TRUE;
2217 for (i = 0; i < class->rank + 1; ++i)
2218 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2219 amethod = create_array_method (class, ".ctor", sig);
2220 methods [method_num++] = amethod;
2223 /* element Get (idx11, [idx2, ...]) */
2224 sig = mono_metadata_signature_alloc (class->image, class->rank);
2225 sig->ret = &class->element_class->byval_arg;
2226 sig->pinvoke = TRUE;
2227 sig->hasthis = TRUE;
2228 for (i = 0; i < class->rank; ++i)
2229 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2230 amethod = create_array_method (class, "Get", sig);
2231 methods [method_num++] = amethod;
2232 /* element& Address (idx11, [idx2, ...]) */
2233 sig = mono_metadata_signature_alloc (class->image, class->rank);
2234 sig->ret = &class->element_class->this_arg;
2235 sig->pinvoke = TRUE;
2236 sig->hasthis = TRUE;
2237 for (i = 0; i < class->rank; ++i)
2238 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2239 amethod = create_array_method (class, "Address", sig);
2240 methods [method_num++] = amethod;
2241 /* void Set (idx11, [idx2, ...], element) */
2242 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2243 sig->ret = &mono_defaults.void_class->byval_arg;
2244 sig->pinvoke = TRUE;
2245 sig->hasthis = TRUE;
2246 for (i = 0; i < class->rank; ++i)
2247 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2248 sig->params [i] = &class->element_class->byval_arg;
2249 amethod = create_array_method (class, "Set", sig);
2250 methods [method_num++] = amethod;
2252 for (i = 0; i < class->interface_count; i++)
2253 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2257 count = class->method.count;
2258 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2259 for (i = 0; i < count; ++i) {
2260 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2261 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2263 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)));
2264 mono_error_cleanup (&error);
2269 if (MONO_CLASS_IS_INTERFACE (class)) {
2271 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2272 for (i = 0; i < count; ++i) {
2273 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2274 methods [i]->slot = slot++;
2278 mono_image_lock (class->image);
2280 if (!class->methods) {
2281 class->method.count = count;
2283 /* Needed because of the double-checking locking pattern */
2284 mono_memory_barrier ();
2286 class->methods = methods;
2289 mono_image_unlock (class->image);
2293 * mono_class_get_method_by_index:
2295 * Returns class->methods [index], initializing class->methods if neccesary.
2297 * LOCKING: Acquires the loader lock.
2300 mono_class_get_method_by_index (MonoClass *class, int index)
2303 /* Avoid calling setup_methods () if possible */
2304 if (class->generic_class && !class->methods) {
2305 MonoClass *gklass = class->generic_class->container_class;
2308 m = mono_class_inflate_generic_method_full_checked (
2309 gklass->methods [index], class, mono_class_get_context (class), &error);
2310 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2312 * If setup_methods () is called later for this class, no duplicates are created,
2313 * since inflate_generic_method guarantees that only one instance of a method
2314 * is created for each context.
2317 mono_class_setup_methods (class);
2318 g_assert (m == class->methods [index]);
2322 mono_class_setup_methods (class);
2323 if (class->exception_type) /*FIXME do proper error handling*/
2325 g_assert (index >= 0 && index < class->method.count);
2326 return class->methods [index];
2331 * mono_class_get_inflated_method:
2333 * Given an inflated class CLASS and a method METHOD which should be a method of
2334 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2337 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2339 MonoClass *gklass = class->generic_class->container_class;
2342 g_assert (method->klass == gklass);
2344 mono_class_setup_methods (gklass);
2345 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2347 for (i = 0; i < gklass->method.count; ++i) {
2348 if (gklass->methods [i] == method) {
2349 if (class->methods) {
2350 return class->methods [i];
2353 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2354 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2364 * mono_class_get_vtable_entry:
2366 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2367 * LOCKING: Acquires the loader lock.
2370 mono_class_get_vtable_entry (MonoClass *class, int offset)
2374 if (class->rank == 1) {
2376 * szarrays do not overwrite any methods of Array, so we can avoid
2377 * initializing their vtables in some cases.
2379 mono_class_setup_vtable (class->parent);
2380 if (offset < class->parent->vtable_size)
2381 return class->parent->vtable [offset];
2384 if (class->generic_class) {
2386 MonoClass *gklass = class->generic_class->container_class;
2387 mono_class_setup_vtable (gklass);
2388 m = gklass->vtable [offset];
2390 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2391 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2393 mono_class_setup_vtable (class);
2394 if (class->exception_type)
2396 m = class->vtable [offset];
2403 * mono_class_get_vtable_size:
2405 * Return the vtable size for KLASS.
2408 mono_class_get_vtable_size (MonoClass *klass)
2410 mono_class_setup_vtable (klass);
2412 return klass->vtable_size;
2416 * mono_class_setup_properties:
2418 * Initialize class->ext.property and class->ext.properties.
2420 * This method can fail the class.
2423 mono_class_setup_properties (MonoClass *class)
2425 guint startm, endm, i, j;
2426 guint32 cols [MONO_PROPERTY_SIZE];
2427 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2428 MonoProperty *properties;
2432 if (class->ext && class->ext->properties)
2435 if (class->generic_class) {
2436 MonoClass *gklass = class->generic_class->container_class;
2438 mono_class_init (gklass);
2439 mono_class_setup_properties (gklass);
2440 if (gklass->exception_type) {
2441 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2445 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2447 for (i = 0; i < gklass->ext->property.count; i++) {
2449 MonoProperty *prop = &properties [i];
2451 *prop = gklass->ext->properties [i];
2454 prop->get = mono_class_inflate_generic_method_full_checked (
2455 prop->get, class, mono_class_get_context (class), &error);
2457 prop->set = mono_class_inflate_generic_method_full_checked (
2458 prop->set, class, mono_class_get_context (class), &error);
2460 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2461 prop->parent = class;
2464 first = gklass->ext->property.first;
2465 count = gklass->ext->property.count;
2467 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2468 count = last - first;
2471 mono_class_setup_methods (class);
2472 if (class->exception_type)
2476 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2477 for (i = first; i < last; ++i) {
2478 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2479 properties [i - first].parent = class;
2480 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2481 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2483 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2484 for (j = startm; j < endm; ++j) {
2487 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2489 if (class->image->uncompressed_metadata) {
2491 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2492 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2493 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2495 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2498 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2499 case METHOD_SEMANTIC_SETTER:
2500 properties [i - first].set = method;
2502 case METHOD_SEMANTIC_GETTER:
2503 properties [i - first].get = method;
2512 mono_class_alloc_ext (class);
2514 mono_image_lock (class->image);
2516 if (class->ext->properties) {
2517 /* We leak 'properties' which was allocated from the image mempool */
2518 mono_image_unlock (class->image);
2522 class->ext->property.first = first;
2523 class->ext->property.count = count;
2525 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2526 mono_memory_barrier ();
2528 /* Leave this assignment as the last op in the function */
2529 class->ext->properties = properties;
2531 mono_image_unlock (class->image);
2535 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2537 MonoMethod **om, **retval;
2540 for (om = methods, count = 0; *om; ++om, ++count)
2543 retval = g_new0 (MonoMethod*, count + 1);
2545 for (om = methods, count = 0; *om; ++om, ++count) {
2547 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2548 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2554 /*This method can fail the class.*/
2556 mono_class_setup_events (MonoClass *class)
2559 guint startm, endm, i, j;
2560 guint32 cols [MONO_EVENT_SIZE];
2561 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2565 if (class->ext && class->ext->events)
2568 if (class->generic_class) {
2569 MonoClass *gklass = class->generic_class->container_class;
2570 MonoGenericContext *context = NULL;
2572 mono_class_setup_events (gklass);
2573 if (gklass->exception_type) {
2574 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2578 first = gklass->ext->event.first;
2579 count = gklass->ext->event.count;
2581 events = mono_class_new0 (class, MonoEvent, count);
2584 context = mono_class_get_context (class);
2586 for (i = 0; i < count; i++) {
2588 MonoEvent *event = &events [i];
2589 MonoEvent *gevent = &gklass->ext->events [i];
2591 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2593 event->parent = class;
2594 event->name = gevent->name;
2595 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2596 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2597 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2598 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2599 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2600 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2602 #ifndef MONO_SMALL_CONFIG
2603 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2605 event->attrs = gevent->attrs;
2608 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2609 count = last - first;
2612 mono_class_setup_methods (class);
2613 if (class->exception_type) {
2614 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2619 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2620 for (i = first; i < last; ++i) {
2621 MonoEvent *event = &events [i - first];
2623 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2624 event->parent = class;
2625 event->attrs = cols [MONO_EVENT_FLAGS];
2626 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2628 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2629 for (j = startm; j < endm; ++j) {
2632 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2634 if (class->image->uncompressed_metadata) {
2636 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2637 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2638 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2640 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2643 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2644 case METHOD_SEMANTIC_ADD_ON:
2645 event->add = method;
2647 case METHOD_SEMANTIC_REMOVE_ON:
2648 event->remove = method;
2650 case METHOD_SEMANTIC_FIRE:
2651 event->raise = method;
2653 case METHOD_SEMANTIC_OTHER: {
2654 #ifndef MONO_SMALL_CONFIG
2657 if (event->other == NULL) {
2658 event->other = g_new0 (MonoMethod*, 2);
2660 while (event->other [n])
2662 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2664 event->other [n] = method;
2665 /* NULL terminated */
2666 event->other [n + 1] = NULL;
2677 mono_class_alloc_ext (class);
2679 mono_image_lock (class->image);
2681 if (class->ext->events) {
2682 mono_image_unlock (class->image);
2686 class->ext->event.first = first;
2687 class->ext->event.count = count;
2689 /* Flush any pending writes as we do double checked locking on class->ext.events */
2690 mono_memory_barrier ();
2692 /* Leave this assignment as the last op in the function */
2693 class->ext->events = events;
2695 mono_image_unlock (class->image);
2699 * Global pool of interface IDs, represented as a bitset.
2700 * LOCKING: Protected by the classes lock.
2702 static MonoBitSet *global_interface_bitset = NULL;
2705 * mono_unload_interface_ids:
2706 * @bitset: bit set of interface IDs
2708 * When an image is unloaded, the interface IDs associated with
2709 * the image are put back in the global pool of IDs so the numbers
2713 mono_unload_interface_ids (MonoBitSet *bitset)
2716 mono_bitset_sub (global_interface_bitset, bitset);
2721 mono_unload_interface_id (MonoClass *class)
2723 if (global_interface_bitset && class->interface_id) {
2725 mono_bitset_clear (global_interface_bitset, class->interface_id);
2731 * mono_get_unique_iid:
2734 * Assign a unique integer ID to the interface represented by @class.
2735 * The ID will positive and as small as possible.
2736 * LOCKING: Acquires the classes lock.
2737 * Returns: the new ID.
2740 mono_get_unique_iid (MonoClass *class)
2744 g_assert (MONO_CLASS_IS_INTERFACE (class));
2748 if (!global_interface_bitset) {
2749 global_interface_bitset = mono_bitset_new (128, 0);
2752 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2754 int old_size = mono_bitset_size (global_interface_bitset);
2755 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2756 mono_bitset_free (global_interface_bitset);
2757 global_interface_bitset = new_set;
2760 mono_bitset_set (global_interface_bitset, iid);
2761 /* set the bit also in the per-image set */
2762 if (!class->generic_class) {
2763 if (class->image->interface_bitset) {
2764 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2765 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2766 mono_bitset_free (class->image->interface_bitset);
2767 class->image->interface_bitset = new_set;
2770 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2772 mono_bitset_set (class->image->interface_bitset, iid);
2777 #ifndef MONO_SMALL_CONFIG
2778 if (mono_print_vtable) {
2780 char *type_name = mono_type_full_name (&class->byval_arg);
2781 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2782 generic_id = class->generic_class->context.class_inst->id;
2783 g_assert (generic_id != 0);
2787 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2792 g_assert (iid <= 65535);
2797 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2802 mono_class_setup_interfaces (klass, error);
2803 if (!mono_error_ok (error))
2806 for (i = 0; i < klass->interface_count; i++) {
2807 ic = klass->interfaces [i];
2810 *res = g_ptr_array_new ();
2811 g_ptr_array_add (*res, ic);
2812 mono_class_init (ic);
2813 if (ic->exception_type) {
2814 mono_error_set_type_load_class (error, ic, "Error Loading class");
2818 collect_implemented_interfaces_aux (ic, res, error);
2819 if (!mono_error_ok (error))
2825 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2827 GPtrArray *res = NULL;
2829 collect_implemented_interfaces_aux (klass, &res, error);
2830 if (!mono_error_ok (error)) {
2832 g_ptr_array_free (res, TRUE);
2839 compare_interface_ids (const void *p_key, const void *p_element) {
2840 const MonoClass *key = p_key;
2841 const MonoClass *element = *(MonoClass**) p_element;
2843 return (key->interface_id - element->interface_id);
2846 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2848 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2849 MonoClass **result = mono_binary_search (
2851 klass->interfaces_packed,
2852 klass->interface_offsets_count,
2853 sizeof (MonoClass *),
2854 compare_interface_ids);
2856 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2863 * mono_class_interface_offset_with_variance:
2865 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2866 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2868 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2870 * FIXME figure out MS disambiguation rules and fix this function.
2873 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2874 int i = mono_class_interface_offset (klass, itf);
2875 *non_exact_match = FALSE;
2879 if (!mono_class_has_variant_generic_params (itf))
2882 for (i = 0; i < klass->interface_offsets_count; i++) {
2883 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2884 *non_exact_match = TRUE;
2885 return klass->interface_offsets_packed [i];
2893 print_implemented_interfaces (MonoClass *klass) {
2896 GPtrArray *ifaces = NULL;
2898 int ancestor_level = 0;
2900 name = mono_type_get_full_name (klass);
2901 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2904 for (i = 0; i < klass->interface_offsets_count; i++)
2905 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2906 klass->interfaces_packed [i]->interface_id,
2907 klass->interface_offsets_packed [i],
2908 klass->interfaces_packed [i]->method.count,
2909 klass->interfaces_packed [i]->name_space,
2910 klass->interfaces_packed [i]->name );
2911 printf ("Interface flags: ");
2912 for (i = 0; i <= klass->max_interface_id; i++)
2913 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2914 printf ("(%d,T)", i);
2916 printf ("(%d,F)", i);
2918 printf ("Dump interface flags:");
2919 #ifdef COMPRESSED_INTERFACE_BITMAP
2921 const uint8_t* p = klass->interface_bitmap;
2922 i = klass->max_interface_id;
2924 printf (" %d x 00 %02X", p [0], p [1]);
2930 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2931 printf (" %02X", klass->interface_bitmap [i]);
2934 while (klass != NULL) {
2935 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2936 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2937 if (!mono_error_ok (&error)) {
2938 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2939 mono_error_cleanup (&error);
2940 } else if (ifaces) {
2941 for (i = 0; i < ifaces->len; i++) {
2942 MonoClass *ic = g_ptr_array_index (ifaces, i);
2943 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2944 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2946 mono_class_interface_offset (klass, ic),
2951 g_ptr_array_free (ifaces, TRUE);
2954 klass = klass->parent;
2959 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2962 args [0] = &arg0->byval_arg;
2964 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2968 array_class_get_if_rank (MonoClass *class, guint rank)
2970 return rank ? mono_array_class_get (class, rank) : class;
2974 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2976 valuetype_types [0] = eclass;
2977 if (eclass == mono_defaults.int16_class)
2978 valuetype_types [1] = mono_defaults.uint16_class;
2979 else if (eclass == mono_defaults.uint16_class)
2980 valuetype_types [1] = mono_defaults.int16_class;
2981 else if (eclass == mono_defaults.int32_class)
2982 valuetype_types [1] = mono_defaults.uint32_class;
2983 else if (eclass == mono_defaults.uint32_class)
2984 valuetype_types [1] = mono_defaults.int32_class;
2985 else if (eclass == mono_defaults.int64_class)
2986 valuetype_types [1] = mono_defaults.uint64_class;
2987 else if (eclass == mono_defaults.uint64_class)
2988 valuetype_types [1] = mono_defaults.int64_class;
2989 else if (eclass == mono_defaults.byte_class)
2990 valuetype_types [1] = mono_defaults.sbyte_class;
2991 else if (eclass == mono_defaults.sbyte_class)
2992 valuetype_types [1] = mono_defaults.byte_class;
2993 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2994 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2997 /* this won't be needed once bug #325495 is completely fixed
2998 * though we'll need something similar to know which interfaces to allow
2999 * in arrays when they'll be lazyly created
3001 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3002 * MS returns diferrent types based on which instance is called. For example:
3003 * object obj = new byte[10][];
3004 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3005 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3008 * Fixing this should kill quite some code, save some bits and improve compatibility.
3011 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3013 MonoClass *eclass = class->element_class;
3014 static MonoClass* generic_icollection_class = NULL;
3015 static MonoClass* generic_ienumerable_class = NULL;
3016 static MonoClass* generic_ienumerator_class = NULL;
3017 static MonoClass* generic_ireadonlylist_class = NULL;
3018 static MonoClass* generic_ireadonlycollection_class = NULL;
3019 MonoClass *valuetype_types[2] = { NULL, NULL };
3020 MonoClass **interfaces = NULL;
3021 int i, nifaces, interface_count, real_count, original_rank;
3023 gboolean internal_enumerator;
3024 gboolean eclass_is_valuetype;
3026 if (!mono_defaults.generic_ilist_class) {
3030 internal_enumerator = FALSE;
3031 eclass_is_valuetype = FALSE;
3032 original_rank = eclass->rank;
3033 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3034 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3036 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3038 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3039 original_rank = eclass->rank;
3041 eclass = eclass->element_class;
3042 internal_enumerator = TRUE;
3043 *is_enumerator = TRUE;
3051 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3052 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3054 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3056 if (!generic_icollection_class) {
3057 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3058 "System.Collections.Generic", "ICollection`1");
3059 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3060 "System.Collections.Generic", "IEnumerable`1");
3061 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3062 "System.Collections.Generic", "IEnumerator`1");
3063 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3064 "System.Collections.Generic", "IReadOnlyList`1");
3065 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3066 "System.Collections.Generic", "IReadOnlyCollection`1");
3069 mono_class_init (eclass);
3072 * Arrays in 2.0 need to implement a number of generic interfaces
3073 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3074 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3075 * We collect the types needed to build the
3076 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3077 * the generic interfaces needed to implement.
3079 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3080 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3082 if (eclass->valuetype) {
3083 nifaces = generic_ireadonlylist_class ? 5 : 3;
3084 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3086 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3087 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3088 if (internal_enumerator) {
3090 if (valuetype_types [1])
3094 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3095 interfaces [0] = valuetype_types [0];
3096 if (valuetype_types [1])
3097 interfaces [nifaces] = valuetype_types [1];
3099 eclass_is_valuetype = TRUE;
3102 int idepth = eclass->idepth;
3103 if (!internal_enumerator)
3105 nifaces = generic_ireadonlylist_class ? 2 : 3;
3107 // FIXME: This doesn't seem to work/required for generic params
3108 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3109 mono_class_setup_interface_offsets (eclass);
3111 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3112 /* we add object for interfaces and the supertypes for the other
3113 * types. The last of the supertypes is the element class itself which we
3114 * already created the explicit interfaces for (so we include it for IEnumerator
3115 * and exclude it for arrays).
3117 if (MONO_CLASS_IS_INTERFACE (eclass))
3120 interface_count += idepth;
3121 if (eclass->rank && eclass->element_class->valuetype) {
3122 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3123 if (valuetype_types [1])
3126 /* IList, ICollection, IEnumerable, IReadOnlyList */
3127 interface_count *= nifaces;
3128 real_count = interface_count;
3129 if (internal_enumerator) {
3130 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3131 if (valuetype_types [1])
3134 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3135 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3136 interfaces [0] = mono_defaults.object_class;
3140 for (i = 0; i < idepth; i++) {
3141 mono_class_init (eclass->supertypes [i]);
3142 interfaces [j] = eclass->supertypes [i];
3146 if (all_interfaces) {
3147 for (i = 0; i < eclass->interface_offsets_count; i++) {
3148 interfaces [j] = eclass->interfaces_packed [i];
3152 for (i = 0; i < eclass->interface_count; i++) {
3153 interfaces [j] = eclass->interfaces [i];
3157 if (valuetype_types [1]) {
3158 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3163 /* instantiate the generic interfaces */
3164 for (i = 0; i < interface_count; i += nifaces) {
3165 MonoClass *iface = interfaces [i];
3167 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3168 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3170 if (eclass->valuetype) {
3171 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3172 if (generic_ireadonlylist_class) {
3173 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3174 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3177 if (!generic_ireadonlylist_class)
3178 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3181 if (internal_enumerator) {
3183 /* instantiate IEnumerator<iface> */
3184 for (i = 0; i < interface_count; i++) {
3185 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3187 j = interface_count;
3188 if (!eclass_is_valuetype) {
3189 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3190 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3193 for (i = 0; i < eclass->idepth; i++) {
3194 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3198 for (i = 0; i < eclass->interface_offsets_count; i++) {
3199 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3203 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3205 if (valuetype_types [1])
3206 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3210 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3211 for (i = 0; i < real_count; ++i) {
3212 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3213 g_print ("%s implements %s\n", type_name, name);
3224 find_array_interface (MonoClass *klass, const char *name)
3227 for (i = 0; i < klass->interface_count; ++i) {
3228 if (strcmp (klass->interfaces [i]->name, name) == 0)
3235 * Return the number of virtual methods.
3236 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3237 * Return -1 on failure.
3238 * FIXME It would be nice if this information could be cached somewhere.
3241 count_virtual_methods (MonoClass *class)
3245 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3247 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3248 mono_class_setup_methods (class);
3249 if (class->exception_type)
3252 for (i = 0; i < class->method.count; ++i) {
3253 flags = class->methods [i]->flags;
3254 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3258 for (i = 0; i < class->method.count; ++i) {
3259 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3261 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3269 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3277 m = (l + num_ifaces) / 2;
3278 if (interfaces_full [m] == ic)
3280 if (l == num_ifaces)
3282 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3291 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3293 int i = find_interface (num_ifaces, interfaces_full, ic);
3295 return interface_offsets_full [i];
3300 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3302 int i = find_interface (num_ifaces, interfaces_full, ic);
3306 interface_offsets_full [i] = offset;
3309 for (i = 0; i < num_ifaces; ++i) {
3310 if (interfaces_full [i]) {
3312 if (interfaces_full [i]->interface_id < ic->interface_id)
3315 while (end < num_ifaces && interfaces_full [end]) end++;
3316 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3317 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3319 interfaces_full [i] = ic;
3320 interface_offsets_full [i] = offset;
3326 #ifdef COMPRESSED_INTERFACE_BITMAP
3329 * Compressed interface bitmap design.
3331 * Interface bitmaps take a large amount of memory, because their size is
3332 * linear with the maximum interface id assigned in the process (each interface
3333 * is assigned a unique id as it is loaded). The number of interface classes
3334 * is high because of the many implicit interfaces implemented by arrays (we'll
3335 * need to lazy-load them in the future).
3336 * Most classes implement a very small number of interfaces, so the bitmap is
3337 * sparse. This bitmap needs to be checked by interface casts, so access to the
3338 * needed bit must be fast and doable with few jit instructions.
3340 * The current compression format is as follows:
3341 * *) it is a sequence of one or more two-byte elements
3342 * *) the first byte in the element is the count of empty bitmap bytes
3343 * at the current bitmap position
3344 * *) the second byte in the element is an actual bitmap byte at the current
3347 * As an example, the following compressed bitmap bytes:
3348 * 0x07 0x01 0x00 0x7
3349 * correspond to the following bitmap:
3350 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3352 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3353 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3354 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3358 * mono_compress_bitmap:
3359 * @dest: destination buffer
3360 * @bitmap: bitmap buffer
3361 * @size: size of @bitmap in bytes
3363 * This is a mono internal function.
3364 * The @bitmap data is compressed into a format that is small but
3365 * still searchable in few instructions by the JIT and runtime.
3366 * The compressed data is stored in the buffer pointed to by the
3367 * @dest array. Passing a #NULL value for @dest allows to just compute
3368 * the size of the buffer.
3369 * This compression algorithm assumes the bits set in the bitmap are
3370 * few and far between, like in interface bitmaps.
3371 * Returns: the size of the compressed bitmap in bytes.
3374 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3378 const uint8_t *end = bitmap + size;
3379 while (bitmap < end) {
3380 if (*bitmap || numz == 255) {
3404 * mono_class_interface_match:
3405 * @bitmap: a compressed bitmap buffer
3406 * @id: the index to check in the bitmap
3408 * This is a mono internal function.
3409 * Checks if a bit is set in a compressed interface bitmap. @id must
3410 * be already checked for being smaller than the maximum id encoded in the
3413 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3417 mono_class_interface_match (const uint8_t *bitmap, int id)
3420 id -= bitmap [0] * 8;
3424 return bitmap [1] & (1 << id);
3433 * LOCKING: this is supposed to be called with the loader lock held.
3434 * Return -1 on failure and set exception_type
3437 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3441 int i, j, max_iid, num_ifaces;
3442 MonoClass **interfaces_full = NULL;
3443 int *interface_offsets_full = NULL;
3445 GPtrArray **ifaces_array = NULL;
3446 int interface_offsets_count;
3447 MonoClass **array_interfaces = NULL;
3448 int num_array_interfaces;
3449 int is_enumerator = FALSE;
3451 mono_class_setup_supertypes (class);
3453 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3454 * implicit interfaces have the property that they are assigned the same slot in the
3455 * vtables for compatible interfaces
3457 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3459 /* compute maximum number of slots and maximum interface id */
3461 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3462 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3463 for (j = 0; j < class->idepth; j++) {
3464 k = class->supertypes [j];
3465 num_ifaces += k->interface_count;
3466 for (i = 0; i < k->interface_count; i++) {
3467 ic = k->interfaces [i];
3470 mono_class_init (ic);
3472 if (max_iid < ic->interface_id)
3473 max_iid = ic->interface_id;
3475 ifaces = mono_class_get_implemented_interfaces (k, &error);
3476 if (!mono_error_ok (&error)) {
3477 char *name = mono_type_get_full_name (k);
3478 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)));
3480 mono_error_cleanup (&error);
3485 num_ifaces += ifaces->len;
3486 for (i = 0; i < ifaces->len; ++i) {
3487 ic = g_ptr_array_index (ifaces, i);
3488 if (max_iid < ic->interface_id)
3489 max_iid = ic->interface_id;
3491 ifaces_array [j] = ifaces;
3495 for (i = 0; i < num_array_interfaces; ++i) {
3496 ic = array_interfaces [i];
3497 mono_class_init (ic);
3498 if (max_iid < ic->interface_id)
3499 max_iid = ic->interface_id;
3502 if (MONO_CLASS_IS_INTERFACE (class)) {
3504 if (max_iid < class->interface_id)
3505 max_iid = class->interface_id;
3507 class->max_interface_id = max_iid;
3508 /* compute vtable offset for interfaces */
3509 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3510 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3512 for (i = 0; i < num_ifaces; i++) {
3513 interface_offsets_full [i] = -1;
3516 /* skip the current class */
3517 for (j = 0; j < class->idepth - 1; j++) {
3518 k = class->supertypes [j];
3519 ifaces = ifaces_array [j];
3522 for (i = 0; i < ifaces->len; ++i) {
3524 ic = g_ptr_array_index (ifaces, i);
3526 /*Force the sharing of interface offsets between parent and subtypes.*/
3527 io = mono_class_interface_offset (k, ic);
3529 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3534 g_assert (class == class->supertypes [class->idepth - 1]);
3535 ifaces = ifaces_array [class->idepth - 1];
3537 for (i = 0; i < ifaces->len; ++i) {
3539 ic = g_ptr_array_index (ifaces, i);
3540 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3542 count = count_virtual_methods (ic);
3544 char *name = mono_type_get_full_name (ic);
3545 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3554 if (MONO_CLASS_IS_INTERFACE (class))
3555 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3557 if (num_array_interfaces) {
3558 if (is_enumerator) {
3559 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3560 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3561 g_assert (ienumerator_offset >= 0);
3562 for (i = 0; i < num_array_interfaces; ++i) {
3563 ic = array_interfaces [i];
3564 if (strcmp (ic->name, "IEnumerator`1") == 0)
3565 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3567 g_assert_not_reached ();
3568 /*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);*/
3571 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3572 int ilist_iface_idx = find_array_interface (class, "IList`1");
3573 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3574 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3575 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3576 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3577 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3578 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3579 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3580 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3581 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3582 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3583 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3584 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3585 for (i = 0; i < num_array_interfaces; ++i) {
3587 ic = array_interfaces [i];
3588 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3589 offset = ilist_offset;
3590 else if (strcmp (ic->name, "ICollection`1") == 0)
3591 offset = icollection_offset;
3592 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3593 offset = ienumerable_offset;
3594 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3595 offset = ireadonlylist_offset;
3596 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3597 offset = ireadonlycollection_offset;
3599 g_assert_not_reached ();
3600 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3601 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3606 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3607 if (interface_offsets_full [i] != -1) {
3608 interface_offsets_count ++;
3613 * We might get called multiple times:
3614 * - mono_class_init ()
3615 * - mono_class_setup_vtable ().
3616 * - mono_class_setup_interface_offsets ().
3617 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3618 * means we have to overwrite those when called from other places (#4440).
3620 if (class->interfaces_packed) {
3622 g_assert (class->interface_offsets_count == interface_offsets_count);
3626 class->interface_offsets_count = interface_offsets_count;
3627 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3628 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3629 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3630 #ifdef COMPRESSED_INTERFACE_BITMAP
3631 bitmap = g_malloc0 (bsize);
3633 bitmap = mono_class_alloc0 (class, bsize);
3635 for (i = 0; i < interface_offsets_count; i++) {
3636 int id = interfaces_full [i]->interface_id;
3637 bitmap [id >> 3] |= (1 << (id & 7));
3638 class->interfaces_packed [i] = interfaces_full [i];
3639 class->interface_offsets_packed [i] = interface_offsets_full [i];
3640 /*if (num_array_interfaces)
3641 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]);*/
3643 #ifdef COMPRESSED_INTERFACE_BITMAP
3644 i = mono_compress_bitmap (NULL, bitmap, bsize);
3645 class->interface_bitmap = mono_class_alloc0 (class, i);
3646 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3649 class->interface_bitmap = bitmap;
3654 g_free (interfaces_full);
3655 g_free (interface_offsets_full);
3656 g_free (array_interfaces);
3657 for (i = 0; i < class->idepth; i++) {
3658 ifaces = ifaces_array [i];
3660 g_ptr_array_free (ifaces, TRUE);
3662 g_free (ifaces_array);
3664 //printf ("JUST DONE: ");
3665 //print_implemented_interfaces (class);
3671 * Setup interface offsets for interfaces.
3673 * - class->max_interface_id
3674 * - class->interface_offsets_count
3675 * - class->interfaces_packed
3676 * - class->interface_offsets_packed
3677 * - class->interface_bitmap
3679 * This function can fail @class.
3682 mono_class_setup_interface_offsets (MonoClass *class)
3684 mono_loader_lock ();
3686 setup_interface_offsets (class, 0, FALSE);
3688 mono_loader_unlock ();
3691 /*Checks if @klass has @parent as one of it's parents type gtd
3695 * Bar<T> : Foo<Bar<Bar<T>>>
3699 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3701 klass = mono_class_get_generic_type_definition (klass);
3702 parent = mono_class_get_generic_type_definition (parent);
3703 mono_class_setup_supertypes (klass);
3704 mono_class_setup_supertypes (parent);
3706 return klass->idepth >= parent->idepth &&
3707 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3711 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3713 MonoGenericInst *ginst;
3715 if (!class->generic_class) {
3716 mono_class_setup_vtable_full (class, in_setup);
3717 return class->exception_type == 0;
3720 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3721 if (class->generic_class->container_class->exception_type) {
3722 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3726 ginst = class->generic_class->context.class_inst;
3727 for (i = 0; i < ginst->type_argc; ++i) {
3729 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3731 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3732 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3733 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3735 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3736 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3744 * mono_class_setup_vtable:
3746 * Creates the generic vtable of CLASS.
3747 * Initializes the following fields in MonoClass:
3750 * Plus all the fields initialized by setup_interface_offsets ().
3751 * If there is an error during vtable construction, class->exception_type is set.
3753 * LOCKING: Acquires the loader lock.
3756 mono_class_setup_vtable (MonoClass *class)
3758 mono_class_setup_vtable_full (class, NULL);
3762 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3764 MonoMethod **overrides;
3765 MonoGenericContext *context;
3773 if (MONO_CLASS_IS_INTERFACE (class)) {
3774 /* This sets method->slot for all methods if this is an interface */
3775 mono_class_setup_methods (class);
3779 if (class->exception_type)
3782 if (g_list_find (in_setup, class))
3785 mono_loader_lock ();
3787 if (class->vtable) {
3788 mono_loader_unlock ();
3792 mono_stats.generic_vtable_count ++;
3793 in_setup = g_list_prepend (in_setup, class);
3795 if (class->generic_class) {
3796 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3797 mono_loader_unlock ();
3798 g_list_remove (in_setup, class);
3802 context = mono_class_get_context (class);
3803 type_token = class->generic_class->container_class->type_token;
3805 context = (MonoGenericContext *) class->generic_container;
3806 type_token = class->type_token;
3809 if (image_is_dynamic (class->image)) {
3810 /* Generic instances can have zero method overrides without causing any harm.
3811 * This is true since we don't do layout all over again for them, we simply inflate
3812 * the layout of the parent.
3814 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3816 /* The following call fails if there are missing methods in the type */
3817 /* FIXME it's probably a good idea to avoid this for generic instances. */
3818 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3822 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3824 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3828 mono_loader_unlock ();
3829 g_list_remove (in_setup, class);
3834 #define DEBUG_INTERFACE_VTABLE_CODE 0
3835 #define TRACE_INTERFACE_VTABLE_CODE 0
3836 #define VERIFY_INTERFACE_VTABLE_CODE 0
3837 #define VTABLE_SELECTOR (1)
3839 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3840 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3841 if (!(VTABLE_SELECTOR)) break; \
3845 #define DEBUG_INTERFACE_VTABLE(stmt)
3848 #if TRACE_INTERFACE_VTABLE_CODE
3849 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3850 if (!(VTABLE_SELECTOR)) break; \
3854 #define TRACE_INTERFACE_VTABLE(stmt)
3857 #if VERIFY_INTERFACE_VTABLE_CODE
3858 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3859 if (!(VTABLE_SELECTOR)) break; \
3863 #define VERIFY_INTERFACE_VTABLE(stmt)
3867 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3869 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3873 GString *res = g_string_new ("");
3875 g_string_append_c (res, '(');
3876 for (i = 0; i < sig->param_count; ++i) {
3878 g_string_append_c (res, ',');
3879 mono_type_get_desc (res, sig->params [i], include_namespace);
3881 g_string_append (res, ")=>");
3882 if (sig->ret != NULL) {
3883 mono_type_get_desc (res, sig->ret, include_namespace);
3885 g_string_append (res, "NULL");
3888 g_string_free (res, FALSE);
3892 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3893 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3894 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3895 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3903 is_wcf_hack_disabled (void)
3905 static gboolean disabled;
3906 static gboolean inited = FALSE;
3908 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3915 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3917 MonoMethodSignature *cmsig, *imsig;
3918 if (strcmp (im->name, cm->name) == 0) {
3919 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3920 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3923 if (! slot_is_empty) {
3924 if (require_newslot) {
3925 if (! interface_is_explicitly_implemented_by_class) {
3926 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3929 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3930 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3934 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3937 cmsig = mono_method_signature (cm);
3938 imsig = mono_method_signature (im);
3939 if (!cmsig || !imsig) {
3940 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3944 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3945 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3946 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3947 TRACE_INTERFACE_VTABLE (printf ("]"));
3950 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3951 if (mono_security_core_clr_enabled ())
3952 mono_security_core_clr_check_override (class, cm, im);
3954 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3955 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3956 char *body_name = mono_method_full_name (cm, TRUE);
3957 char *decl_name = mono_method_full_name (im, TRUE);
3958 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));
3966 MonoClass *ic = im->klass;
3967 const char *ic_name_space = ic->name_space;
3968 const char *ic_name = ic->name;
3971 if (! require_newslot) {
3972 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3975 if (cm->klass->rank == 0) {
3976 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3979 cmsig = mono_method_signature (cm);
3980 imsig = mono_method_signature (im);
3981 if (!cmsig || !imsig) {
3982 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3986 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3987 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3988 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3989 TRACE_INTERFACE_VTABLE (printf ("]"));
3992 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3993 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3996 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3997 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4000 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))) {
4001 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4005 subname = strstr (cm->name, ic_name_space);
4006 if (subname != cm->name) {
4007 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4010 subname += strlen (ic_name_space);
4011 if (subname [0] != '.') {
4012 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4016 if (strstr (subname, ic_name) != subname) {
4017 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4020 subname += strlen (ic_name);
4021 if (subname [0] != '.') {
4022 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4026 if (strcmp (subname, im->name) != 0) {
4027 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4031 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4032 if (mono_security_core_clr_enabled ())
4033 mono_security_core_clr_check_override (class, cm, im);
4035 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4036 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4037 char *body_name = mono_method_full_name (cm, TRUE);
4038 char *decl_name = mono_method_full_name (im, TRUE);
4039 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));
4049 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4051 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4052 MonoMethod *method = key;
4053 MonoMethod *override = value;
4054 MonoClass *method_class = mono_method_get_class (method);
4055 MonoClass *override_class = mono_method_get_class (override);
4057 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4058 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4059 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4062 print_overrides (GHashTable *override_map, const char *message) {
4064 printf ("Override map \"%s\" START:\n", message);
4065 g_hash_table_foreach (override_map, foreach_override, NULL);
4066 printf ("Override map \"%s\" END.\n", message);
4068 printf ("Override map \"%s\" EMPTY.\n", message);
4072 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4073 char *full_name = mono_type_full_name (&class->byval_arg);
4077 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4079 if (print_interfaces) {
4080 print_implemented_interfaces (class);
4081 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4084 if (class->parent) {
4085 parent_size = class->parent->vtable_size;
4089 for (i = 0; i < size; ++i) {
4090 MonoMethod *cm = vtable [i];
4091 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4092 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4094 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4102 #if VERIFY_INTERFACE_VTABLE_CODE
4104 mono_method_try_get_vtable_index (MonoMethod *method)
4106 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4107 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4108 if (imethod->declaring->is_generic)
4109 return imethod->declaring->slot;
4111 return method->slot;
4115 mono_class_verify_vtable (MonoClass *class)
4118 char *full_name = mono_type_full_name (&class->byval_arg);
4120 printf ("*** Verifying VTable of class '%s' \n", full_name);
4124 if (!class->methods)
4127 for (i = 0; i < class->method.count; ++i) {
4128 MonoMethod *cm = class->methods [i];
4131 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4135 full_name = mono_method_full_name (cm, TRUE);
4137 slot = mono_method_try_get_vtable_index (cm);
4139 if (slot >= class->vtable_size) {
4140 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4144 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4145 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4146 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4147 g_free (other_name);
4150 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4157 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4159 char *method_signature;
4162 for (index = 0; index < onum; ++index) {
4163 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4164 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4166 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4167 type_name = mono_type_full_name (&class->byval_arg);
4168 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4169 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4170 g_free (method_signature);
4172 mono_class_setup_methods (class);
4173 if (class->exception_type) {
4174 char *name = mono_type_get_full_name (class);
4175 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4179 for (index = 0; index < class->method.count; ++index) {
4180 MonoMethod *cm = class->methods [index];
4181 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4183 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4184 g_free (method_signature);
4189 mono_method_get_method_definition (MonoMethod *method)
4191 while (method->is_inflated)
4192 method = ((MonoMethodInflated*)method)->declaring;
4197 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4201 for (i = 0; i < onum; ++i) {
4202 MonoMethod *decl = overrides [i * 2];
4203 MonoMethod *body = overrides [i * 2 + 1];
4205 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4206 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4210 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4211 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4212 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4214 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4218 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4219 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4220 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4222 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4226 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4227 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4231 body = mono_method_get_method_definition (body);
4232 decl = mono_method_get_method_definition (decl);
4234 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4235 char *body_name = mono_method_full_name (body, TRUE);
4236 char *decl_name = mono_method_full_name (decl, TRUE);
4237 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));
4247 mono_class_need_stelemref_method (MonoClass *class)
4249 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4253 * LOCKING: this is supposed to be called with the loader lock held.
4256 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4260 MonoMethod **vtable;
4261 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4262 GPtrArray *ifaces = NULL;
4263 GHashTable *override_map = NULL;
4265 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4266 int first_non_interface_slot;
4268 GSList *virt_methods = NULL, *l;
4269 int stelemref_slot = 0;
4274 if (overrides && !verify_class_overrides (class, overrides, onum))
4277 ifaces = mono_class_get_implemented_interfaces (class, &error);
4278 if (!mono_error_ok (&error)) {
4279 char *name = mono_type_get_full_name (class);
4280 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)));
4282 mono_error_cleanup (&error);
4284 } else if (ifaces) {
4285 for (i = 0; i < ifaces->len; i++) {
4286 MonoClass *ic = g_ptr_array_index (ifaces, i);
4287 max_vtsize += ic->method.count;
4289 g_ptr_array_free (ifaces, TRUE);
4293 if (class->parent) {
4294 mono_class_init (class->parent);
4295 mono_class_setup_vtable_full (class->parent, in_setup);
4297 if (class->parent->exception_type) {
4298 char *name = mono_type_get_full_name (class->parent);
4299 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4304 max_vtsize += class->parent->vtable_size;
4305 cur_slot = class->parent->vtable_size;
4308 max_vtsize += class->method.count;
4310 /*Array have a slot for stelemref*/
4311 if (mono_class_need_stelemref_method (class)) {
4312 stelemref_slot = cur_slot;
4317 vtable = alloca (sizeof (gpointer) * max_vtsize);
4318 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4320 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4322 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4323 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4326 max_iid = class->max_interface_id;
4327 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4329 /* Optimized version for generic instances */
4330 if (class->generic_class) {
4332 MonoClass *gklass = class->generic_class->container_class;
4335 mono_class_setup_vtable_full (gklass, in_setup);
4336 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4337 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4341 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4342 class->vtable_size = gklass->vtable_size;
4343 for (i = 0; i < gklass->vtable_size; ++i)
4344 if (gklass->vtable [i]) {
4345 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4346 if (!mono_error_ok (&error)) {
4347 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4348 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4350 mono_error_cleanup (&error);
4354 tmp [i]->slot = gklass->vtable [i]->slot;
4356 mono_memory_barrier ();
4357 class->vtable = tmp;
4359 /* Have to set method->slot for abstract virtual methods */
4360 if (class->methods && gklass->methods) {
4361 for (i = 0; i < class->method.count; ++i)
4362 if (class->methods [i]->slot == -1)
4363 class->methods [i]->slot = gklass->methods [i]->slot;
4369 if (class->parent && class->parent->vtable_size) {
4370 MonoClass *parent = class->parent;
4373 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4375 // Also inherit parent interface vtables, just as a starting point.
4376 // This is needed otherwise bug-77127.exe fails when the property methods
4377 // have different names in the iterface and the class, because for child
4378 // classes the ".override" information is not used anymore.
4379 for (i = 0; i < parent->interface_offsets_count; i++) {
4380 MonoClass *parent_interface = parent->interfaces_packed [i];
4381 int interface_offset = mono_class_interface_offset (class, parent_interface);
4382 /*FIXME this is now dead code as this condition will never hold true.
4383 Since interface offsets are inherited then the offset of an interface implemented
4384 by a parent will never be the out of it's vtable boundary.
4386 if (interface_offset >= parent->vtable_size) {
4387 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4390 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4391 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4392 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4393 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4394 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4395 parent_interface_offset + j, parent_interface_offset, j,
4396 interface_offset + j, interface_offset, j));
4403 /*Array have a slot for stelemref*/
4404 if (mono_class_need_stelemref_method (class)) {
4405 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4407 method->slot = stelemref_slot;
4409 g_assert (method->slot == stelemref_slot);
4411 vtable [stelemref_slot] = method;
4414 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4415 /* override interface methods */
4416 for (i = 0; i < onum; i++) {
4417 MonoMethod *decl = overrides [i*2];
4418 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4420 dslot = mono_method_get_vtable_slot (decl);
4422 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4426 dslot += mono_class_interface_offset (class, decl->klass);
4427 vtable [dslot] = overrides [i*2 + 1];
4428 vtable [dslot]->slot = dslot;
4430 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4432 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4434 if (mono_security_core_clr_enabled ())
4435 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4438 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4439 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4442 * Create a list of virtual methods to avoid calling
4443 * mono_class_get_virtual_methods () which is slow because of the metadata
4447 gpointer iter = NULL;
4450 virt_methods = NULL;
4451 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4452 virt_methods = g_slist_prepend (virt_methods, cm);
4454 if (class->exception_type)
4458 // Loop on all implemented interfaces...
4459 for (i = 0; i < class->interface_offsets_count; i++) {
4460 MonoClass *parent = class->parent;
4462 gboolean interface_is_explicitly_implemented_by_class;
4465 ic = class->interfaces_packed [i];
4466 ic_offset = mono_class_interface_offset (class, ic);
4468 mono_class_setup_methods (ic);
4469 if (ic->exception_type)
4472 // Check if this interface is explicitly implemented (instead of just inherited)
4473 if (parent != NULL) {
4474 int implemented_interfaces_index;
4475 interface_is_explicitly_implemented_by_class = FALSE;
4476 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4477 if (ic == class->interfaces [implemented_interfaces_index]) {
4478 interface_is_explicitly_implemented_by_class = TRUE;
4483 interface_is_explicitly_implemented_by_class = TRUE;
4486 // Loop on all interface methods...
4487 for (im_index = 0; im_index < ic->method.count; im_index++) {
4488 MonoMethod *im = ic->methods [im_index];
4489 int im_slot = ic_offset + im->slot;
4490 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4492 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4495 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4497 // If there is an explicit implementation, just use it right away,
4498 // otherwise look for a matching method
4499 if (override_im == NULL) {
4503 // First look for a suitable method among the class methods
4504 for (l = virt_methods; l; l = l->next) {
4506 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)));
4507 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4508 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4509 vtable [im_slot] = cm;
4510 /* Why do we need this? */
4515 TRACE_INTERFACE_VTABLE (printf ("\n"));
4516 if (class->exception_type) /*Might be set by check_interface_method_override*/
4520 // If the slot is still empty, look in all the inherited virtual methods...
4521 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4522 MonoClass *parent = class->parent;
4523 // Reverse order, so that last added methods are preferred
4524 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4525 MonoMethod *cm = parent->vtable [cm_index];
4527 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));
4528 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE)) {
4529 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4530 vtable [im_slot] = cm;
4531 /* Why do we need this? */
4537 if (class->exception_type) /*Might be set by check_interface_method_override*/
4539 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4543 g_assert (vtable [im_slot] == override_im);
4548 // If the class is not abstract, check that all its interface slots are full.
4549 // The check is done here and not directly at the end of the loop above because
4550 // it can happen (for injected generic array interfaces) that the same slot is
4551 // processed multiple times (those interfaces have overlapping slots), and it
4552 // will not always be the first pass the one that fills the slot.
4553 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4554 for (i = 0; i < class->interface_offsets_count; i++) {
4558 ic = class->interfaces_packed [i];
4559 ic_offset = mono_class_interface_offset (class, ic);
4561 for (im_index = 0; im_index < ic->method.count; im_index++) {
4562 MonoMethod *im = ic->methods [im_index];
4563 int im_slot = ic_offset + im->slot;
4565 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4568 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4569 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4570 if (vtable [im_slot] == NULL) {
4571 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4578 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4579 for (l = virt_methods; l; l = l->next) {
4582 * If the method is REUSE_SLOT, we must check in the
4583 * base class for a method to override.
4585 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4587 for (k = class->parent; k ; k = k->parent) {
4592 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4593 MonoMethodSignature *cmsig, *m1sig;
4595 cmsig = mono_method_signature (cm);
4596 m1sig = mono_method_signature (m1);
4598 if (!cmsig || !m1sig) {
4599 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4603 if (!strcmp(cm->name, m1->name) &&
4604 mono_metadata_signature_equal (cmsig, m1sig)) {
4606 if (mono_security_core_clr_enabled ())
4607 mono_security_core_clr_check_override (class, cm, m1);
4609 slot = mono_method_get_vtable_slot (m1);
4613 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4614 char *body_name = mono_method_full_name (cm, TRUE);
4615 char *decl_name = mono_method_full_name (m1, TRUE);
4616 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));
4622 g_assert (cm->slot < max_vtsize);
4624 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4625 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4626 mono_method_full_name (m1, 1), m1,
4627 mono_method_full_name (cm, 1), cm));
4628 g_hash_table_insert (override_map, m1, cm);
4632 if (k->exception_type)
4642 /*Non final newslot methods must be given a non-interface vtable slot*/
4643 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4647 cm->slot = cur_slot++;
4649 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4650 vtable [cm->slot] = cm;
4653 /* override non interface methods */
4654 for (i = 0; i < onum; i++) {
4655 MonoMethod *decl = overrides [i*2];
4656 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4657 g_assert (decl->slot != -1);
4658 vtable [decl->slot] = overrides [i*2 + 1];
4659 overrides [i * 2 + 1]->slot = decl->slot;
4661 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4662 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4663 mono_method_full_name (decl, 1), decl,
4664 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4665 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4667 if (mono_security_core_clr_enabled ())
4668 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4673 * If a method occupies more than one place in the vtable, and it is
4674 * overriden, then change the other occurances too.
4679 for (i = 0; i < max_vtsize; ++i)
4681 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4683 cm = g_hash_table_lookup (override_map, vtable [i]);
4688 g_hash_table_destroy (override_map);
4689 override_map = NULL;
4692 g_slist_free (virt_methods);
4693 virt_methods = NULL;
4695 /* Ensure that all vtable slots are filled with concrete instance methods */
4696 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4697 for (i = 0; i < cur_slot; ++i) {
4698 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4699 char *type_name = mono_type_get_full_name (class);
4700 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4701 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));
4703 g_free (method_name);
4709 if (class->generic_class) {
4710 MonoClass *gklass = class->generic_class->container_class;
4712 mono_class_init (gklass);
4714 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4716 /* Check that the vtable_size value computed in mono_class_init () is correct */
4717 if (class->vtable_size)
4718 g_assert (cur_slot == class->vtable_size);
4719 class->vtable_size = cur_slot;
4722 /* Try to share the vtable with our parent. */
4723 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4724 mono_memory_barrier ();
4725 class->vtable = class->parent->vtable;
4727 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4728 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4729 mono_memory_barrier ();
4730 class->vtable = tmp;
4733 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4734 if (mono_print_vtable) {
4737 print_implemented_interfaces (class);
4739 for (i = 0; i <= max_iid; i++)
4740 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4743 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4744 class->vtable_size, icount);
4746 for (i = 0; i < cur_slot; ++i) {
4751 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4752 mono_method_full_name (cm, TRUE));
4758 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4759 class->name, max_iid);
4761 for (i = 0; i < class->interface_count; i++) {
4762 ic = class->interfaces [i];
4763 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4764 mono_class_interface_offset (class, ic),
4765 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4768 for (k = class->parent; k ; k = k->parent) {
4769 for (i = 0; i < k->interface_count; i++) {
4770 ic = k->interfaces [i];
4771 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4772 mono_class_interface_offset (class, ic),
4773 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4779 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4784 char *name = mono_type_get_full_name (class);
4785 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4788 g_hash_table_destroy (override_map);
4790 g_slist_free (virt_methods);
4795 * mono_method_get_vtable_slot:
4797 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4798 * LOCKING: Acquires the loader lock.
4800 * FIXME Use proper MonoError machinery here.
4803 mono_method_get_vtable_slot (MonoMethod *method)
4805 if (method->slot == -1) {
4806 mono_class_setup_vtable (method->klass);
4807 if (method->klass->exception_type)
4809 if (method->slot == -1) {
4813 if (!method->klass->generic_class) {
4814 g_assert (method->is_inflated);
4815 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4818 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4819 g_assert (method->klass->generic_class);
4820 gklass = method->klass->generic_class->container_class;
4821 mono_class_setup_methods (method->klass);
4822 g_assert (method->klass->methods);
4823 for (i = 0; i < method->klass->method.count; ++i) {
4824 if (method->klass->methods [i] == method)
4827 g_assert (i < method->klass->method.count);
4828 g_assert (gklass->methods);
4829 method->slot = gklass->methods [i]->slot;
4831 g_assert (method->slot != -1);
4833 return method->slot;
4837 * mono_method_get_vtable_index:
4840 * Returns the index into the runtime vtable to access the method or,
4841 * in the case of a virtual generic method, the virtual generic method
4842 * thunk. Returns -1 on failure.
4844 * FIXME Use proper MonoError machinery here.
4847 mono_method_get_vtable_index (MonoMethod *method)
4849 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4850 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4851 if (imethod->declaring->is_generic)
4852 return mono_method_get_vtable_slot (imethod->declaring);
4854 return mono_method_get_vtable_slot (method);
4857 static MonoMethod *default_ghc = NULL;
4858 static MonoMethod *default_finalize = NULL;
4859 static int finalize_slot = -1;
4860 static int ghc_slot = -1;
4863 initialize_object_slots (MonoClass *class)
4868 if (class == mono_defaults.object_class) {
4869 mono_class_setup_vtable (class);
4870 for (i = 0; i < class->vtable_size; ++i) {
4871 MonoMethod *cm = class->vtable [i];
4873 if (!strcmp (cm->name, "GetHashCode"))
4875 else if (!strcmp (cm->name, "Finalize"))
4879 g_assert (ghc_slot > 0);
4880 default_ghc = class->vtable [ghc_slot];
4882 g_assert (finalize_slot > 0);
4883 default_finalize = class->vtable [finalize_slot];
4888 MonoMethod *array_method;
4890 } GenericArrayMethodInfo;
4892 static int generic_array_method_num = 0;
4893 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4896 generic_array_methods (MonoClass *class)
4898 int i, count_generic = 0;
4899 GList *list = NULL, *tmp;
4900 if (generic_array_method_num)
4901 return generic_array_method_num;
4902 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4903 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4904 for (i = 0; i < class->parent->method.count; i++) {
4905 MonoMethod *m = class->parent->methods [i];
4906 if (!strncmp (m->name, "InternalArray__", 15)) {
4908 list = g_list_prepend (list, m);
4911 list = g_list_reverse (list);
4912 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4914 for (tmp = list; tmp; tmp = tmp->next) {
4915 const char *mname, *iname;
4917 MonoMethod *m = tmp->data;
4918 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4919 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4921 generic_array_method_info [i].array_method = m;
4922 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4923 iname = "System.Collections.Generic.ICollection`1.";
4924 mname = m->name + 27;
4925 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4926 iname = "System.Collections.Generic.IEnumerable`1.";
4927 mname = m->name + 27;
4928 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4929 iname = "System.Collections.Generic.IReadOnlyList`1.";
4930 mname = m->name + strlen (ireadonlylist_prefix);
4931 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4932 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4933 mname = m->name + strlen (ireadonlycollection_prefix);
4934 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4935 iname = "System.Collections.Generic.IList`1.";
4936 mname = m->name + 15;
4938 g_assert_not_reached ();
4941 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4942 strcpy (name, iname);
4943 strcpy (name + strlen (iname), mname);
4944 generic_array_method_info [i].name = name;
4947 /*g_print ("array generic methods: %d\n", count_generic);*/
4949 generic_array_method_num = count_generic;
4951 return generic_array_method_num;
4955 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4957 MonoGenericContext tmp_context;
4960 tmp_context.class_inst = NULL;
4961 tmp_context.method_inst = iface->generic_class->context.class_inst;
4962 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4964 for (i = 0; i < generic_array_method_num; i++) {
4966 MonoMethod *m = generic_array_method_info [i].array_method;
4967 MonoMethod *inflated;
4969 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4970 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4971 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4976 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4978 int null_length = strlen ("(null)");
4979 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4980 char *s = mono_image_alloc (image, len);
4983 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4984 g_assert (result == len - 1);
4990 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4992 gpointer exception_data = NULL;
4994 switch (error->exception_type) {
4995 case MONO_EXCEPTION_TYPE_LOAD:
4996 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4999 case MONO_EXCEPTION_MISSING_METHOD:
5000 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5003 case MONO_EXCEPTION_MISSING_FIELD: {
5004 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5005 const char *class_name;
5008 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5010 class_name = error->klass->name;
5012 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5015 g_free ((void*)class_name);
5019 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5022 if (error->ref_only)
5023 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.";
5025 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5027 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5031 case MONO_EXCEPTION_BAD_IMAGE:
5032 exception_data = error->msg;
5036 g_assert_not_reached ();
5039 mono_class_set_failure (class, error->exception_type, exception_data);
5044 * @class: the class to initialize
5046 * Compute the instance_size, class_size and other infos that cannot be
5047 * computed at mono_class_get() time. Also compute vtable_size if possible.
5048 * Returns TRUE on success or FALSE if there was a problem in loading
5049 * the type (incorrect assemblies, missing assemblies, methods, etc).
5051 * LOCKING: Acquires the loader lock.
5054 mono_class_init (MonoClass *class)
5057 MonoCachedClassInfo cached_info;
5058 gboolean has_cached_info;
5062 /* Double-checking locking pattern */
5063 if (class->inited || class->exception_type)
5064 return class->exception_type == MONO_EXCEPTION_NONE;
5066 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5068 /* We do everything inside the lock to prevent races */
5069 mono_loader_lock ();
5071 if (class->inited || class->exception_type) {
5072 mono_loader_unlock ();
5073 /* Somebody might have gotten in before us */
5074 return class->exception_type == MONO_EXCEPTION_NONE;
5077 if (class->init_pending) {
5078 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5082 class->init_pending = 1;
5084 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5085 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5090 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5091 MonoClass *element_class = class->element_class;
5092 if (!element_class->inited)
5093 mono_class_init (element_class);
5094 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5095 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5100 mono_stats.initialized_class_count++;
5102 if (class->generic_class && !class->generic_class->is_dynamic) {
5103 MonoClass *gklass = class->generic_class->container_class;
5105 mono_stats.generic_class_count++;
5107 class->method = gklass->method;
5108 class->field = gklass->field;
5110 mono_class_init (gklass);
5111 // FIXME: Why is this needed ?
5112 if (!gklass->exception_type)
5113 mono_class_setup_methods (gklass);
5114 if (gklass->exception_type) {
5115 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5119 if (MONO_CLASS_IS_INTERFACE (class))
5120 class->interface_id = mono_get_unique_iid (class);
5123 if (class->parent && !class->parent->inited)
5124 mono_class_init (class->parent);
5126 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5128 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5129 class->nested_classes_inited = TRUE;
5132 * Computes the size used by the fields, and their locations
5134 if (has_cached_info) {
5135 class->instance_size = cached_info.instance_size;
5136 class->sizes.class_size = cached_info.class_size;
5137 class->packing_size = cached_info.packing_size;
5138 class->min_align = cached_info.min_align;
5139 class->blittable = cached_info.blittable;
5140 class->has_references = cached_info.has_references;
5141 class->has_static_refs = cached_info.has_static_refs;
5142 class->no_special_static_fields = cached_info.no_special_static_fields;
5145 if (!class->size_inited){
5146 mono_class_setup_fields (class);
5147 if (class->exception_type || mono_loader_get_last_error ())
5151 /* Initialize arrays */
5153 class->method.count = 3 + (class->rank > 1? 2: 1);
5155 if (class->interface_count) {
5156 int count_generic = generic_array_methods (class);
5157 class->method.count += class->interface_count * count_generic;
5161 mono_class_setup_supertypes (class);
5164 initialize_object_slots (class);
5167 * Initialize the rest of the data without creating a generic vtable if possible.
5168 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5169 * also avoid computing a generic vtable.
5171 if (has_cached_info) {
5173 class->vtable_size = cached_info.vtable_size;
5174 class->has_finalize = cached_info.has_finalize;
5175 class->has_finalize_inited = TRUE;
5176 class->ghcimpl = cached_info.ghcimpl;
5177 class->has_cctor = cached_info.has_cctor;
5178 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5179 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5180 * The first slot if for array with.
5182 static int szarray_vtable_size[2] = { 0 };
5184 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5187 if (!szarray_vtable_size [slot]) {
5188 mono_class_setup_vtable (class);
5189 szarray_vtable_size [slot] = class->vtable_size;
5191 class->vtable_size = szarray_vtable_size[slot];
5193 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5194 MonoClass *gklass = class->generic_class->container_class;
5196 /* Generic instance case */
5197 class->ghcimpl = gklass->ghcimpl;
5198 class->has_cctor = gklass->has_cctor;
5200 mono_class_setup_vtable (gklass);
5201 if (gklass->exception_type) {
5202 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5206 class->vtable_size = gklass->vtable_size;
5210 /* ghcimpl is not currently used
5212 if (class->parent) {
5213 MonoMethod *cmethod = class->vtable [ghc_slot];
5214 if (cmethod->is_inflated)
5215 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5216 if (cmethod == default_ghc) {
5222 /* C# doesn't allow interfaces to have cctors */
5223 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5224 MonoMethod *cmethod = NULL;
5226 if (class->type_token) {
5227 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5228 /* The find_method function ignores the 'flags' argument */
5229 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5230 class->has_cctor = 1;
5232 mono_class_setup_methods (class);
5233 if (class->exception_type)
5236 for (i = 0; i < class->method.count; ++i) {
5237 MonoMethod *method = class->methods [i];
5238 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5239 (strcmp (".cctor", method->name) == 0)) {
5240 class->has_cctor = 1;
5248 if (class->parent) {
5249 int first_iface_slot;
5250 /* This will compute class->parent->vtable_size for some classes */
5251 mono_class_init (class->parent);
5252 if (class->parent->exception_type) {
5253 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5256 if (mono_loader_get_last_error ())
5258 if (!class->parent->vtable_size) {
5259 /* FIXME: Get rid of this somehow */
5260 mono_class_setup_vtable (class->parent);
5261 if (class->parent->exception_type) {
5262 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5265 if (mono_loader_get_last_error ())
5268 first_iface_slot = class->parent->vtable_size;
5269 if (mono_class_need_stelemref_method (class))
5271 setup_interface_offsets (class, first_iface_slot, TRUE);
5273 setup_interface_offsets (class, 0, TRUE);
5276 if (mono_security_core_clr_enabled ())
5277 mono_security_core_clr_check_inheritance (class);
5279 if (mono_loader_get_last_error ()) {
5280 if (class->exception_type == MONO_EXCEPTION_NONE) {
5281 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5283 mono_loader_clear_error ();
5286 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5287 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5292 /* Because of the double-checking locking pattern */
5293 mono_memory_barrier ();
5295 class->init_pending = 0;
5297 mono_loader_unlock ();
5299 return class->exception_type == MONO_EXCEPTION_NONE;
5303 * mono_class_has_finalizer:
5305 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5309 mono_class_has_finalizer (MonoClass *klass)
5311 MonoClass *class = klass;
5312 gboolean has_finalize = FALSE;
5314 if (klass->has_finalize_inited)
5315 return klass->has_finalize;
5317 /* Interfaces and valuetypes are not supposed to have finalizers */
5318 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5319 MonoMethod *cmethod = NULL;
5321 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5322 } else if (class->generic_class) {
5323 MonoClass *gklass = class->generic_class->container_class;
5325 has_finalize = mono_class_has_finalizer (gklass);
5326 } else if (class->parent && class->parent->has_finalize) {
5327 has_finalize = TRUE;
5329 if (class->parent) {
5331 * Can't search in metadata for a method named Finalize, because that
5332 * ignores overrides.
5334 mono_class_setup_vtable (class);
5335 if (class->exception_type || mono_loader_get_last_error ())
5338 cmethod = class->vtable [finalize_slot];
5342 g_assert (class->vtable_size > finalize_slot);
5344 if (class->parent) {
5345 if (cmethod->is_inflated)
5346 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5347 if (cmethod != default_finalize)
5348 has_finalize = TRUE;
5354 mono_image_lock (klass->image);
5356 if (!klass->has_finalize_inited) {
5357 klass->has_finalize = has_finalize ? 1 : 0;
5359 mono_memory_barrier ();
5360 klass->has_finalize_inited = TRUE;
5363 mono_image_unlock (klass->image);
5365 return klass->has_finalize;
5369 mono_is_corlib_image (MonoImage *image)
5371 /* FIXME: allow the dynamic case for our compilers and with full trust */
5372 if (image_is_dynamic (image))
5373 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5375 return image == mono_defaults.corlib;
5379 * LOCKING: this assumes the loader lock is held
5382 mono_class_setup_mono_type (MonoClass *class)
5384 const char *name = class->name;
5385 const char *nspace = class->name_space;
5386 gboolean is_corlib = mono_is_corlib_image (class->image);
5388 class->this_arg.byref = 1;
5389 class->this_arg.data.klass = class;
5390 class->this_arg.type = MONO_TYPE_CLASS;
5391 class->byval_arg.data.klass = class;
5392 class->byval_arg.type = MONO_TYPE_CLASS;
5394 if (is_corlib && !strcmp (nspace, "System")) {
5395 if (!strcmp (name, "ValueType")) {
5397 * do not set the valuetype bit for System.ValueType.
5398 * class->valuetype = 1;
5400 class->blittable = TRUE;
5401 } else if (!strcmp (name, "Enum")) {
5403 * do not set the valuetype bit for System.Enum.
5404 * class->valuetype = 1;
5406 class->valuetype = 0;
5407 class->enumtype = 0;
5408 } else if (!strcmp (name, "Object")) {
5409 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5410 } else if (!strcmp (name, "String")) {
5411 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5412 } else if (!strcmp (name, "TypedReference")) {
5413 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5417 if (class->valuetype) {
5418 int t = MONO_TYPE_VALUETYPE;
5420 if (is_corlib && !strcmp (nspace, "System")) {
5423 if (!strcmp (name, "Boolean")) {
5424 t = MONO_TYPE_BOOLEAN;
5425 } else if (!strcmp(name, "Byte")) {
5427 class->blittable = TRUE;
5431 if (!strcmp (name, "Char")) {
5436 if (!strcmp (name, "Double")) {
5438 class->blittable = TRUE;
5442 if (!strcmp (name, "Int32")) {
5444 class->blittable = TRUE;
5445 } else if (!strcmp(name, "Int16")) {
5447 class->blittable = TRUE;
5448 } else if (!strcmp(name, "Int64")) {
5450 class->blittable = TRUE;
5451 } else if (!strcmp(name, "IntPtr")) {
5453 class->blittable = TRUE;
5457 if (!strcmp (name, "Single")) {
5459 class->blittable = TRUE;
5460 } else if (!strcmp(name, "SByte")) {
5462 class->blittable = TRUE;
5466 if (!strcmp (name, "UInt32")) {
5468 class->blittable = TRUE;
5469 } else if (!strcmp(name, "UInt16")) {
5471 class->blittable = TRUE;
5472 } else if (!strcmp(name, "UInt64")) {
5474 class->blittable = TRUE;
5475 } else if (!strcmp(name, "UIntPtr")) {
5477 class->blittable = TRUE;
5481 if (!strcmp (name, "TypedReference")) {
5482 t = MONO_TYPE_TYPEDBYREF;
5483 class->blittable = TRUE;
5487 if (!strcmp (name, "Void")) {
5495 class->this_arg.type = class->byval_arg.type = t;
5498 if (MONO_CLASS_IS_INTERFACE (class))
5499 class->interface_id = mono_get_unique_iid (class);
5505 * COM initialization is delayed until needed.
5506 * However when a [ComImport] attribute is present on a type it will trigger
5507 * the initialization. This is not a problem unless the BCL being executed
5508 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5511 init_com_from_comimport (MonoClass *class)
5513 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5514 if (mono_security_core_clr_enabled ()) {
5515 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5516 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5517 /* but it can not be made available for application (i.e. user code) since all COM calls
5518 * are considered native calls. In this case we fail with a TypeLoadException (just like
5519 * Silverlight 2 does */
5520 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5525 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5527 #endif /*DISABLE_COM*/
5530 * LOCKING: this assumes the loader lock is held
5533 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5535 gboolean system_namespace;
5536 gboolean is_corlib = mono_is_corlib_image (class->image);
5538 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5540 /* if root of the hierarchy */
5541 if (system_namespace && !strcmp (class->name, "Object")) {
5542 class->parent = NULL;
5543 class->instance_size = sizeof (MonoObject);
5546 if (!strcmp (class->name, "<Module>")) {
5547 class->parent = NULL;
5548 class->instance_size = 0;
5552 if (!MONO_CLASS_IS_INTERFACE (class)) {
5553 /* Imported COM Objects always derive from __ComObject. */
5555 if (MONO_CLASS_IS_IMPORT (class)) {
5556 init_com_from_comimport (class);
5557 if (parent == mono_defaults.object_class)
5558 parent = mono_class_get_com_object_class ();
5562 /* set the parent to something useful and safe, but mark the type as broken */
5563 parent = mono_defaults.object_class;
5564 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5567 class->parent = parent;
5569 if (parent->generic_class && !parent->name) {
5571 * If the parent is a generic instance, we may get
5572 * called before it is fully initialized, especially
5573 * before it has its name.
5578 #ifndef DISABLE_REMOTING
5579 class->marshalbyref = parent->marshalbyref;
5580 class->contextbound = parent->contextbound;
5583 class->delegate = parent->delegate;
5585 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5586 mono_class_set_is_com_object (class);
5588 if (system_namespace) {
5589 #ifndef DISABLE_REMOTING
5590 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5591 class->marshalbyref = 1;
5593 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5594 class->contextbound = 1;
5596 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5597 class->delegate = 1;
5600 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5601 (strcmp (class->parent->name_space, "System") == 0)))
5602 class->valuetype = 1;
5603 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5604 class->valuetype = class->enumtype = 1;
5606 /*class->enumtype = class->parent->enumtype; */
5608 /* initialize com types if COM interfaces are present */
5610 if (MONO_CLASS_IS_IMPORT (class))
5611 init_com_from_comimport (class);
5613 class->parent = NULL;
5619 * mono_class_setup_supertypes:
5622 * Build the data structure needed to make fast type checks work.
5623 * This currently sets two fields in @class:
5624 * - idepth: distance between @class and System.Object in the type
5626 * - supertypes: array of classes: each element has a class in the hierarchy
5627 * starting from @class up to System.Object
5629 * LOCKING: This function is atomic, in case of contention we waste memory.
5632 mono_class_setup_supertypes (MonoClass *class)
5635 MonoClass **supertypes;
5637 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5641 if (class->parent && !class->parent->supertypes)
5642 mono_class_setup_supertypes (class->parent);
5644 class->idepth = class->parent->idepth + 1;
5648 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5649 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5651 if (class->parent) {
5652 supertypes [class->idepth - 1] = class;
5653 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5655 supertypes [0] = class;
5658 mono_atomic_store_release (&class->supertypes, supertypes);
5662 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5664 MonoClass *gtd = (MonoClass*)user_data;
5665 /* Only try to fix generic instances of @gtd */
5666 if (gclass->generic_class->container_class != gtd)
5669 /* Check if the generic instance has no parent. */
5670 if (gtd->parent && !gclass->parent)
5671 mono_generic_class_setup_parent (gclass, gtd);
5677 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5679 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5680 mono_error_set_type_load_class (error, class, msg);
5684 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5686 MonoLoaderError *lerror = mono_loader_get_last_error ();
5689 set_failure_from_loader_error (class, lerror);
5690 mono_error_set_from_loader_error (error);
5694 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5695 mono_error_set_type_load_class (error, class, msg);
5700 * mono_class_create_from_typedef:
5701 * @image: image where the token is valid
5702 * @type_token: typedef token
5703 * @error: used to return any error found while creating the type
5705 * Create the MonoClass* representing the specified type token.
5706 * @type_token must be a TypeDef token.
5708 * FIXME: don't return NULL on failure, just the the caller figure it out.
5711 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5713 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5714 MonoClass *class, *parent = NULL;
5715 guint32 cols [MONO_TYPEDEF_SIZE];
5716 guint32 cols_next [MONO_TYPEDEF_SIZE];
5717 guint tidx = mono_metadata_token_index (type_token);
5718 MonoGenericContext *context = NULL;
5719 const char *name, *nspace;
5721 MonoClass **interfaces;
5722 guint32 field_last, method_last;
5723 guint32 nesting_tokeen;
5725 mono_error_init (error);
5727 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5728 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5729 mono_loader_assert_no_error ();
5733 mono_loader_lock ();
5735 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5736 mono_loader_unlock ();
5737 mono_loader_assert_no_error ();
5741 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5743 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5744 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5746 class = mono_image_alloc0 (image, sizeof (MonoClass));
5749 class->name_space = nspace;
5751 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5753 class->image = image;
5754 class->type_token = type_token;
5755 class->flags = cols [MONO_TYPEDEF_FLAGS];
5757 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5759 classes_size += sizeof (MonoClass);
5762 * Check whether we're a generic type definition.
5764 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5765 if (class->generic_container) {
5766 class->is_generic = 1;
5767 class->generic_container->owner.klass = class;
5768 context = &class->generic_container->context;
5771 if (class->generic_container)
5772 enable_gclass_recording ();
5774 if (cols [MONO_TYPEDEF_EXTENDS]) {
5776 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5778 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5779 /*WARNING: this must satisfy mono_metadata_type_hash*/
5780 class->this_arg.byref = 1;
5781 class->this_arg.data.klass = class;
5782 class->this_arg.type = MONO_TYPE_CLASS;
5783 class->byval_arg.data.klass = class;
5784 class->byval_arg.type = MONO_TYPE_CLASS;
5786 parent = mono_class_get_checked (image, parent_token, error);
5787 if (parent && context) /* Always inflate */
5788 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5790 if (parent == NULL) {
5791 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5792 goto parent_failure;
5795 for (tmp = parent; tmp; tmp = tmp->parent) {
5797 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5798 goto parent_failure;
5800 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5801 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5802 goto parent_failure;
5807 mono_class_setup_parent (class, parent);
5809 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5810 mono_class_setup_mono_type (class);
5812 if (class->generic_container)
5813 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5816 * This might access class->byval_arg for recursion generated by generic constraints,
5817 * so it has to come after setup_mono_type ().
5819 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5820 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5821 if (!mono_error_ok (error)) {
5822 /*FIXME implement a mono_class_set_failure_from_mono_error */
5823 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5824 mono_loader_unlock ();
5825 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5826 mono_loader_assert_no_error ();
5831 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5835 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5839 class->cast_class = class->element_class = class;
5841 if (!class->enumtype) {
5842 if (!mono_metadata_interfaces_from_typedef_full (
5843 image, type_token, &interfaces, &icount, FALSE, context, error)){
5845 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5846 mono_loader_unlock ();
5847 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5851 class->interfaces = interfaces;
5852 class->interface_count = icount;
5853 class->interfaces_inited = 1;
5856 /*g_print ("Load class %s\n", name);*/
5859 * Compute the field and method lists
5861 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5862 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5864 if (tt->rows > tidx){
5865 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5866 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5867 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5869 field_last = image->tables [MONO_TABLE_FIELD].rows;
5870 method_last = image->tables [MONO_TABLE_METHOD].rows;
5873 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5874 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5875 class->field.count = field_last - class->field.first;
5877 class->field.count = 0;
5879 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5880 class->method.count = method_last - class->method.first;
5882 class->method.count = 0;
5884 /* reserve space to store vector pointer in arrays */
5885 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5886 class->instance_size += 2 * sizeof (gpointer);
5887 g_assert (class->field.count == 0);
5890 if (class->enumtype) {
5891 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5892 if (!enum_basetype) {
5893 /*set it to a default value as the whole runtime can't handle this to be null*/
5894 class->cast_class = class->element_class = mono_defaults.int32_class;
5895 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5896 mono_loader_unlock ();
5897 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5898 mono_loader_assert_no_error ();
5901 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5905 * If we're a generic type definition, load the constraints.
5906 * We must do this after the class has been constructed to make certain recursive scenarios
5909 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5910 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)));
5911 mono_loader_unlock ();
5912 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5913 mono_loader_assert_no_error ();
5917 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5918 if (!strncmp (name, "Vector", 6))
5919 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");
5922 mono_loader_unlock ();
5924 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5925 mono_loader_assert_no_error ();
5930 mono_class_setup_mono_type (class);
5931 mono_loader_unlock ();
5932 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5933 mono_loader_assert_no_error ();
5937 /** is klass Nullable<T>? */
5939 mono_class_is_nullable (MonoClass *klass)
5941 return klass->generic_class != NULL &&
5942 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5946 /** if klass is T? return T */
5948 mono_class_get_nullable_param (MonoClass *klass)
5950 g_assert (mono_class_is_nullable (klass));
5951 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5955 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5959 MonoGenericClass *gclass = klass->generic_class;
5961 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5962 if (!mono_error_ok (&error)) {
5963 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5964 klass->parent = mono_defaults.object_class;
5965 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5966 mono_error_cleanup (&error);
5970 mono_class_setup_parent (klass, klass->parent);
5972 if (klass->enumtype) {
5973 klass->cast_class = gtd->cast_class;
5974 klass->element_class = gtd->element_class;
5980 * Create the `MonoClass' for an instantiation of a generic type.
5981 * We only do this if we actually need it.
5984 mono_generic_class_get_class (MonoGenericClass *gclass)
5986 MonoClass *klass, *gklass;
5988 if (gclass->cached_class)
5989 return gclass->cached_class;
5991 mono_loader_lock ();
5992 if (gclass->cached_class) {
5993 mono_loader_unlock ();
5994 return gclass->cached_class;
5997 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5999 gklass = gclass->container_class;
6001 if (record_gclass_instantiation > 0)
6002 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6004 if (gklass->nested_in) {
6005 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6006 klass->nested_in = gklass->nested_in;
6009 klass->name = gklass->name;
6010 klass->name_space = gklass->name_space;
6012 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6014 klass->image = gklass->image;
6015 klass->flags = gklass->flags;
6016 klass->type_token = gklass->type_token;
6017 klass->field.count = gklass->field.count;
6019 klass->is_inflated = 1;
6020 klass->generic_class = gclass;
6022 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6023 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6024 klass->this_arg.byref = TRUE;
6025 klass->enumtype = gklass->enumtype;
6026 klass->valuetype = gklass->valuetype;
6028 klass->cast_class = klass->element_class = klass;
6030 if (mono_class_is_nullable (klass))
6031 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6034 * We're not interested in the nested classes of a generic instance.
6035 * We use the generic type definition to look for nested classes.
6038 mono_generic_class_setup_parent (klass, gklass);
6040 if (gclass->is_dynamic) {
6042 * 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.
6043 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6044 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6046 if (!gklass->wastypebuilder)
6049 mono_class_setup_supertypes (klass);
6051 if (klass->enumtype) {
6053 * For enums, gklass->fields might not been set, but instance_size etc. is
6054 * already set in mono_reflection_create_internal_class (). For non-enums,
6055 * these will be computed normally in mono_class_layout_fields ().
6057 klass->instance_size = gklass->instance_size;
6058 klass->sizes.class_size = gklass->sizes.class_size;
6059 mono_memory_barrier ();
6060 klass->size_inited = 1;
6064 mono_memory_barrier ();
6065 gclass->cached_class = klass;
6067 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6069 inflated_classes ++;
6070 inflated_classes_size += sizeof (MonoClass);
6072 mono_loader_unlock ();
6078 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6080 MonoClass *klass, **ptr;
6082 MonoGenericContainer *container = mono_generic_param_owner (param);
6086 image = mono_defaults.corlib;
6088 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6089 classes_size += sizeof (MonoClass);
6092 klass->name = pinfo->name;
6094 int n = mono_generic_param_num (param);
6095 klass->name = mono_image_alloc0 (image, 16);
6096 sprintf ((char*)klass->name, "%d", n);
6101 MonoMethod *omethod = container->owner.method;
6102 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6104 MonoClass *oklass = container->owner.klass;
6105 klass->name_space = oklass ? oklass->name_space : "";
6108 klass->name_space = "";
6111 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6115 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6119 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6120 klass->parent = pinfo->constraints [0];
6122 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6123 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6125 klass->parent = mono_defaults.object_class;
6128 if (count - pos > 0) {
6129 klass->interface_count = count - pos;
6130 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6131 klass->interfaces_inited = TRUE;
6132 for (i = pos; i < count; i++)
6133 klass->interfaces [i - pos] = pinfo->constraints [i];
6136 klass->image = image;
6138 klass->inited = TRUE;
6139 klass->cast_class = klass->element_class = klass;
6140 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6142 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6143 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6144 klass->this_arg.byref = TRUE;
6146 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6147 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6149 /*Init these fields to sane values*/
6150 klass->min_align = 1;
6152 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6153 * constrained to, the JIT depends on this.
6155 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6156 mono_memory_barrier ();
6157 klass->size_inited = 1;
6158 klass->setup_fields_called = 1;
6160 mono_class_setup_supertypes (klass);
6162 if (count - pos > 0) {
6163 mono_class_setup_vtable (klass->parent);
6164 if (klass->parent->exception_type)
6165 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6167 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6173 #define FAST_CACHE_SIZE 16
6176 * LOCKING: Takes the image lock depending on @take_lock.
6179 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6181 int n = mono_generic_param_num (param);
6182 MonoImage *image = param->image;
6183 MonoClass *klass = NULL;
6188 if (param->gshared_constraint) {
6189 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6192 mono_image_lock (image);
6193 klass = g_hash_table_lookup (ht, param);
6195 mono_image_unlock (image);
6200 if (n < FAST_CACHE_SIZE) {
6202 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6204 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6206 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6209 mono_image_lock (image);
6210 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6212 mono_image_unlock (image);
6219 * LOCKING: Image lock (param->image) must be held
6222 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6224 int n = mono_generic_param_num (param);
6225 MonoImage *image = param->image;
6229 if (param->gshared_constraint) {
6230 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6232 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6233 mono_memory_barrier ();
6235 image->mvar_cache_constrained = ht;
6237 image->var_cache_constrained = ht;
6239 g_hash_table_insert (ht, param, klass);
6240 } else if (n < FAST_CACHE_SIZE) {
6242 /* Requires locking to avoid droping an already published class */
6243 if (!image->mvar_cache_fast)
6244 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6245 image->mvar_cache_fast [n] = klass;
6247 if (!image->var_cache_fast)
6248 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6249 image->var_cache_fast [n] = klass;
6252 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6254 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6256 ht = g_hash_table_new (NULL, NULL);
6257 mono_memory_barrier ();
6259 image->mvar_cache_slow = ht;
6261 image->var_cache_slow = ht;
6264 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6269 * LOCKING: Acquires the image lock (@image).
6272 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6274 MonoGenericContainer *container = mono_generic_param_owner (param);
6275 MonoGenericParamInfo *pinfo = NULL;
6276 MonoClass *klass, *klass2;
6279 pinfo = mono_generic_param_info (param);
6280 klass = pinfo->pklass;
6283 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6288 if (!image && container) {
6290 MonoMethod *method = container->owner.method;
6291 image = (method && method->klass) ? method->klass->image : NULL;
6293 MonoClass *klass = container->owner.klass;
6294 // FIXME: 'klass' should not be null
6295 // But, monodis creates GenericContainers without associating a owner to it
6296 image = klass ? klass->image : NULL;
6300 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6302 mono_memory_barrier ();
6304 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6305 image = mono_defaults.corlib;
6307 mono_image_lock (image);
6309 klass2 = pinfo->pklass;
6311 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6317 pinfo->pklass = klass;
6319 set_anon_gparam_class (param, is_mvar, klass);
6321 mono_image_unlock (image);
6323 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6325 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6327 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6333 mono_ptr_class_get (MonoType *type)
6336 MonoClass *el_class;
6340 el_class = mono_class_from_mono_type (type);
6341 image = el_class->image;
6343 mono_image_lock (image);
6344 if (image->ptr_cache) {
6345 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6346 mono_image_unlock (image);
6350 mono_image_unlock (image);
6352 result = mono_image_alloc0 (image, sizeof (MonoClass));
6354 classes_size += sizeof (MonoClass);
6356 result->parent = NULL; /* no parent for PTR types */
6357 result->name_space = el_class->name_space;
6358 name = g_strdup_printf ("%s*", el_class->name);
6359 result->name = mono_image_strdup (image, name);
6362 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6364 result->image = el_class->image;
6365 result->inited = TRUE;
6366 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6367 /* Can pointers get boxed? */
6368 result->instance_size = sizeof (gpointer);
6369 result->cast_class = result->element_class = el_class;
6370 result->blittable = TRUE;
6372 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6373 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6374 result->this_arg.byref = TRUE;
6376 mono_class_setup_supertypes (result);
6378 mono_image_lock (image);
6379 if (image->ptr_cache) {
6381 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6382 mono_image_unlock (image);
6383 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6387 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6389 g_hash_table_insert (image->ptr_cache, el_class, result);
6390 mono_image_unlock (image);
6392 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6398 mono_fnptr_class_get (MonoMethodSignature *sig)
6401 static GHashTable *ptr_hash = NULL;
6403 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6405 mono_loader_lock ();
6408 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6410 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6411 mono_loader_unlock ();
6414 result = g_new0 (MonoClass, 1);
6416 result->parent = NULL; /* no parent for PTR types */
6417 result->name_space = "System";
6418 result->name = "MonoFNPtrFakeClass";
6420 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6422 result->image = mono_defaults.corlib; /* need to fix... */
6423 result->inited = TRUE;
6424 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6425 /* Can pointers get boxed? */
6426 result->instance_size = sizeof (gpointer);
6427 result->cast_class = result->element_class = result;
6428 result->blittable = TRUE;
6430 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6431 result->this_arg.data.method = result->byval_arg.data.method = sig;
6432 result->this_arg.byref = TRUE;
6433 result->blittable = TRUE;
6435 mono_class_setup_supertypes (result);
6437 g_hash_table_insert (ptr_hash, sig, result);
6439 mono_loader_unlock ();
6441 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6447 mono_class_from_mono_type (MonoType *type)
6449 switch (type->type) {
6450 case MONO_TYPE_OBJECT:
6451 return type->data.klass? type->data.klass: mono_defaults.object_class;
6452 case MONO_TYPE_VOID:
6453 return type->data.klass? type->data.klass: mono_defaults.void_class;
6454 case MONO_TYPE_BOOLEAN:
6455 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6456 case MONO_TYPE_CHAR:
6457 return type->data.klass? type->data.klass: mono_defaults.char_class;
6459 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6461 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6463 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6465 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6467 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6469 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6471 return type->data.klass? type->data.klass: mono_defaults.int_class;
6473 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6475 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6477 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6479 return type->data.klass? type->data.klass: mono_defaults.single_class;
6481 return type->data.klass? type->data.klass: mono_defaults.double_class;
6482 case MONO_TYPE_STRING:
6483 return type->data.klass? type->data.klass: mono_defaults.string_class;
6484 case MONO_TYPE_TYPEDBYREF:
6485 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6486 case MONO_TYPE_ARRAY:
6487 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6489 return mono_ptr_class_get (type->data.type);
6490 case MONO_TYPE_FNPTR:
6491 return mono_fnptr_class_get (type->data.method);
6492 case MONO_TYPE_SZARRAY:
6493 return mono_array_class_get (type->data.klass, 1);
6494 case MONO_TYPE_CLASS:
6495 case MONO_TYPE_VALUETYPE:
6496 return type->data.klass;
6497 case MONO_TYPE_GENERICINST:
6498 return mono_generic_class_get_class (type->data.generic_class);
6500 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6501 case MONO_TYPE_MVAR:
6502 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6504 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6505 g_assert_not_reached ();
6512 * mono_type_retrieve_from_typespec
6513 * @image: context where the image is created
6514 * @type_spec: typespec token
6515 * @context: the generic context used to evaluate generic instantiations in
6518 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6520 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6522 *did_inflate = FALSE;
6527 if (context && (context->class_inst || context->method_inst)) {
6528 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6530 if (!mono_error_ok (error)) {
6531 mono_loader_assert_no_error ();
6537 *did_inflate = TRUE;
6544 * mono_class_create_from_typespec
6545 * @image: context where the image is created
6546 * @type_spec: typespec token
6547 * @context: the generic context used to evaluate generic instantiations in
6550 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6553 gboolean inflated = FALSE;
6554 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6555 if (!mono_error_ok (error))
6557 ret = mono_class_from_mono_type (t);
6559 mono_metadata_free_type (t);
6564 * mono_bounded_array_class_get:
6565 * @element_class: element class
6566 * @rank: the dimension of the array class
6567 * @bounded: whenever the array has non-zero bounds
6569 * Returns: a class object describing the array with element type @element_type and
6573 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6577 MonoClass *parent = NULL;
6578 GSList *list, *rootlist = NULL;
6581 gboolean corlib_type = FALSE;
6583 g_assert (rank <= 255);
6586 /* bounded only matters for one-dimensional arrays */
6589 image = eclass->image;
6591 if (rank == 1 && !bounded) {
6593 * This case is very frequent not just during compilation because of calls
6594 * from mono_class_from_mono_type (), mono_array_new (),
6595 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6597 mono_mutex_lock (&image->szarray_cache_lock);
6598 if (!image->szarray_cache)
6599 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6600 class = g_hash_table_lookup (image->szarray_cache, eclass);
6601 mono_mutex_unlock (&image->szarray_cache_lock);
6605 mono_loader_lock ();
6607 mono_loader_lock ();
6609 if (!image->array_cache)
6610 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6612 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6613 for (; list; list = list->next) {
6615 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6616 mono_loader_unlock ();
6623 /* for the building corlib use System.Array from it */
6624 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6625 parent = mono_class_from_name (image, "System", "Array");
6628 parent = mono_defaults.array_class;
6629 if (!parent->inited)
6630 mono_class_init (parent);
6633 class = mono_image_alloc0 (image, sizeof (MonoClass));
6635 class->image = image;
6636 class->name_space = eclass->name_space;
6637 nsize = strlen (eclass->name);
6638 name = g_malloc (nsize + 2 + rank + 1);
6639 memcpy (name, eclass->name, nsize);
6642 memset (name + nsize + 1, ',', rank - 1);
6644 name [nsize + rank] = '*';
6645 name [nsize + rank + bounded] = ']';
6646 name [nsize + rank + bounded + 1] = 0;
6647 class->name = mono_image_strdup (image, name);
6650 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6652 classes_size += sizeof (MonoClass);
6654 class->type_token = 0;
6655 /* all arrays are marked serializable and sealed, bug #42779 */
6656 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6657 class->parent = parent;
6658 class->instance_size = mono_class_instance_size (class->parent);
6660 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6661 /*Arrays of those two types are invalid.*/
6662 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6663 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6664 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6665 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6666 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6668 /* element_size -1 is ok as this is not an instantitable type*/
6669 class->sizes.element_size = -1;
6671 class->sizes.element_size = mono_class_array_element_size (eclass);
6673 mono_class_setup_supertypes (class);
6675 if (eclass->generic_class)
6676 mono_class_init (eclass);
6677 if (!eclass->size_inited)
6678 mono_class_setup_fields (eclass);
6679 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6680 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6682 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6686 if (eclass->enumtype)
6687 class->cast_class = eclass->element_class;
6689 class->cast_class = eclass;
6691 switch (class->cast_class->byval_arg.type) {
6693 class->cast_class = mono_defaults.byte_class;
6696 class->cast_class = mono_defaults.int16_class;
6699 #if SIZEOF_VOID_P == 4
6703 class->cast_class = mono_defaults.int32_class;
6706 #if SIZEOF_VOID_P == 8
6710 class->cast_class = mono_defaults.int64_class;
6716 class->element_class = eclass;
6718 if ((rank > 1) || bounded) {
6719 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6720 class->byval_arg.type = MONO_TYPE_ARRAY;
6721 class->byval_arg.data.array = at;
6722 at->eklass = eclass;
6724 /* FIXME: complete.... */
6726 class->byval_arg.type = MONO_TYPE_SZARRAY;
6727 class->byval_arg.data.klass = eclass;
6729 class->this_arg = class->byval_arg;
6730 class->this_arg.byref = 1;
6735 class->generic_container = eclass->generic_container;
6737 if (rank == 1 && !bounded) {
6738 MonoClass *prev_class;
6740 mono_mutex_lock (&image->szarray_cache_lock);
6741 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6743 /* Someone got in before us */
6746 g_hash_table_insert (image->szarray_cache, eclass, class);
6747 mono_mutex_unlock (&image->szarray_cache_lock);
6749 list = g_slist_append (rootlist, class);
6750 g_hash_table_insert (image->array_cache, eclass, list);
6753 mono_loader_unlock ();
6755 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6761 * mono_array_class_get:
6762 * @element_class: element class
6763 * @rank: the dimension of the array class
6765 * Returns: a class object describing the array with element type @element_type and
6769 mono_array_class_get (MonoClass *eclass, guint32 rank)
6771 return mono_bounded_array_class_get (eclass, rank, FALSE);
6775 * mono_class_instance_size:
6778 * Returns: the size of an object instance
6781 mono_class_instance_size (MonoClass *klass)
6783 if (!klass->size_inited)
6784 mono_class_init (klass);
6786 return klass->instance_size;
6790 * mono_class_min_align:
6793 * Returns: minimm alignment requirements
6796 mono_class_min_align (MonoClass *klass)
6798 if (!klass->size_inited)
6799 mono_class_init (klass);
6801 return klass->min_align;
6805 * mono_class_value_size:
6808 * This function is used for value types, and return the
6809 * space and the alignment to store that kind of value object.
6811 * Returns: the size of a value of kind @klass
6814 mono_class_value_size (MonoClass *klass, guint32 *align)
6818 /* fixme: check disable, because we still have external revereces to
6819 * mscorlib and Dummy Objects
6821 /*g_assert (klass->valuetype);*/
6823 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6826 *align = klass->min_align;
6832 * mono_class_data_size:
6835 * Returns: the size of the static class data
6838 mono_class_data_size (MonoClass *klass)
6841 mono_class_init (klass);
6842 /* This can happen with dynamically created types */
6843 if (!klass->fields_inited)
6844 mono_class_setup_fields_locking (klass);
6846 /* in arrays, sizes.class_size is unioned with element_size
6847 * and arrays have no static fields
6851 return klass->sizes.class_size;
6855 * Auxiliary routine to mono_class_get_field
6857 * Takes a field index instead of a field token.
6859 static MonoClassField *
6860 mono_class_get_field_idx (MonoClass *class, int idx)
6862 mono_class_setup_fields_locking (class);
6863 if (class->exception_type)
6867 if (class->image->uncompressed_metadata) {
6869 * class->field.first points to the FieldPtr table, while idx points into the
6870 * Field table, so we have to do a search.
6872 /*FIXME this is broken for types with multiple fields with the same name.*/
6873 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6876 for (i = 0; i < class->field.count; ++i)
6877 if (mono_field_get_name (&class->fields [i]) == name)
6878 return &class->fields [i];
6879 g_assert_not_reached ();
6881 if (class->field.count) {
6882 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6883 return &class->fields [idx - class->field.first];
6887 class = class->parent;
6893 * mono_class_get_field:
6894 * @class: the class to lookup the field.
6895 * @field_token: the field token
6897 * Returns: A MonoClassField representing the type and offset of
6898 * the field, or a NULL value if the field does not belong to this
6902 mono_class_get_field (MonoClass *class, guint32 field_token)
6904 int idx = mono_metadata_token_index (field_token);
6906 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6908 return mono_class_get_field_idx (class, idx - 1);
6912 * mono_class_get_field_from_name:
6913 * @klass: the class to lookup the field.
6914 * @name: the field name
6916 * Search the class @klass and it's parents for a field with the name @name.
6918 * Returns: the MonoClassField pointer of the named field or NULL
6921 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6923 return mono_class_get_field_from_name_full (klass, name, NULL);
6927 * mono_class_get_field_from_name_full:
6928 * @klass: the class to lookup the field.
6929 * @name: the field name
6930 * @type: the type of the fields. This optional.
6932 * Search the class @klass and it's parents for a field with the name @name and type @type.
6934 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6935 * of its generic type definition.
6937 * Returns: the MonoClassField pointer of the named field or NULL
6940 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6944 mono_class_setup_fields_locking (klass);
6945 if (klass->exception_type)
6949 for (i = 0; i < klass->field.count; ++i) {
6950 MonoClassField *field = &klass->fields [i];
6952 if (strcmp (name, mono_field_get_name (field)) != 0)
6956 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6957 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6962 klass = klass->parent;
6968 * mono_class_get_field_token:
6969 * @field: the field we need the token of
6971 * Get the token of a field. Note that the tokesn is only valid for the image
6972 * the field was loaded from. Don't use this function for fields in dynamic types.
6974 * Returns: the token representing the field in the image it was loaded from.
6977 mono_class_get_field_token (MonoClassField *field)
6979 MonoClass *klass = field->parent;
6982 mono_class_setup_fields_locking (klass);
6987 for (i = 0; i < klass->field.count; ++i) {
6988 if (&klass->fields [i] == field) {
6989 int idx = klass->field.first + i + 1;
6991 if (klass->image->uncompressed_metadata)
6992 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6993 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6996 klass = klass->parent;
6999 g_assert_not_reached ();
7004 mono_field_get_index (MonoClassField *field)
7006 int index = field - field->parent->fields;
7008 g_assert (index >= 0 && index < field->parent->field.count);
7014 * mono_class_get_field_default_value:
7016 * Return the default value of the field as a pointer into the metadata blob.
7019 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7022 guint32 constant_cols [MONO_CONSTANT_SIZE];
7024 MonoClass *klass = field->parent;
7026 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7028 if (!klass->ext || !klass->ext->field_def_values) {
7029 MonoFieldDefaultValue *def_values;
7031 mono_class_alloc_ext (klass);
7033 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7035 mono_image_lock (klass->image);
7036 mono_memory_barrier ();
7037 if (!klass->ext->field_def_values)
7038 klass->ext->field_def_values = def_values;
7039 mono_image_unlock (klass->image);
7042 field_index = mono_field_get_index (field);
7044 if (!klass->ext->field_def_values [field_index].data) {
7045 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7049 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7051 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7052 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7053 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7056 *def_type = klass->ext->field_def_values [field_index].def_type;
7057 return klass->ext->field_def_values [field_index].data;
7061 mono_property_get_index (MonoProperty *prop)
7063 int index = prop - prop->parent->ext->properties;
7065 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7071 * mono_class_get_property_default_value:
7073 * Return the default value of the field as a pointer into the metadata blob.
7076 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7079 guint32 constant_cols [MONO_CONSTANT_SIZE];
7080 MonoClass *klass = property->parent;
7082 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7084 * We don't cache here because it is not used by C# so it's quite rare, but
7085 * we still do the lookup in klass->ext because that is where the data
7086 * is stored for dynamic assemblies.
7089 if (image_is_dynamic (klass->image)) {
7090 int prop_index = mono_property_get_index (property);
7091 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7092 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7093 return klass->ext->prop_def_values [prop_index].data;
7097 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7101 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7102 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7103 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7107 mono_class_get_event_token (MonoEvent *event)
7109 MonoClass *klass = event->parent;
7114 for (i = 0; i < klass->ext->event.count; ++i) {
7115 if (&klass->ext->events [i] == event)
7116 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7119 klass = klass->parent;
7122 g_assert_not_reached ();
7127 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7131 gpointer iter = NULL;
7132 while ((p = mono_class_get_properties (klass, &iter))) {
7133 if (! strcmp (name, p->name))
7136 klass = klass->parent;
7142 mono_class_get_property_token (MonoProperty *prop)
7144 MonoClass *klass = prop->parent;
7148 gpointer iter = NULL;
7149 while ((p = mono_class_get_properties (klass, &iter))) {
7150 if (&klass->ext->properties [i] == prop)
7151 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7155 klass = klass->parent;
7158 g_assert_not_reached ();
7163 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7165 const char *name, *nspace;
7166 if (image_is_dynamic (image))
7167 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7169 switch (type_token & 0xff000000){
7170 case MONO_TOKEN_TYPE_DEF: {
7171 guint32 cols [MONO_TYPEDEF_SIZE];
7172 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7173 guint tidx = mono_metadata_token_index (type_token);
7175 if (tidx > tt->rows)
7176 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7178 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7179 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7180 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7181 if (strlen (nspace) == 0)
7182 return g_strdup_printf ("%s", name);
7184 return g_strdup_printf ("%s.%s", nspace, name);
7187 case MONO_TOKEN_TYPE_REF: {
7189 guint32 cols [MONO_TYPEREF_SIZE];
7190 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7191 guint tidx = mono_metadata_token_index (type_token);
7194 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7196 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7197 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7198 mono_error_cleanup (&error);
7202 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7203 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7204 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7205 if (strlen (nspace) == 0)
7206 return g_strdup_printf ("%s", name);
7208 return g_strdup_printf ("%s.%s", nspace, name);
7211 case MONO_TOKEN_TYPE_SPEC:
7212 return g_strdup_printf ("Typespec 0x%08x", type_token);
7214 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7219 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7221 if (image_is_dynamic (image))
7222 return g_strdup_printf ("DynamicAssembly %s", image->name);
7224 switch (type_token & 0xff000000){
7225 case MONO_TOKEN_TYPE_DEF:
7226 if (image->assembly)
7227 return mono_stringify_assembly_name (&image->assembly->aname);
7228 else if (image->assembly_name)
7229 return g_strdup (image->assembly_name);
7230 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7231 case MONO_TOKEN_TYPE_REF: {
7233 MonoAssemblyName aname;
7234 guint32 cols [MONO_TYPEREF_SIZE];
7235 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7236 guint32 idx = mono_metadata_token_index (type_token);
7239 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7241 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7242 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7243 mono_error_cleanup (&error);
7246 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7248 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7249 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7250 case MONO_RESOLUTION_SCOPE_MODULE:
7252 return g_strdup ("");
7253 case MONO_RESOLUTION_SCOPE_MODULEREF:
7255 return g_strdup ("");
7256 case MONO_RESOLUTION_SCOPE_TYPEREF:
7258 return g_strdup ("");
7259 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7260 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7261 return mono_stringify_assembly_name (&aname);
7263 g_assert_not_reached ();
7267 case MONO_TOKEN_TYPE_SPEC:
7269 return g_strdup ("");
7271 g_assert_not_reached ();
7278 * mono_class_get_full:
7279 * @image: the image where the class resides
7280 * @type_token: the token for the class
7281 * @context: the generic context used to evaluate generic instantiations in
7282 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7284 * Returns: the MonoClass that represents @type_token in @image
7287 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7291 class = mono_class_get_checked (image, type_token, &error);
7293 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7294 class = mono_class_inflate_generic_class_checked (class, context, &error);
7296 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7302 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7306 mono_error_init (error);
7307 class = mono_class_get_checked (image, type_token, error);
7309 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7310 class = mono_class_inflate_generic_class_checked (class, context, error);
7315 * mono_class_get_checked:
7316 * @image: the image where the class resides
7317 * @type_token: the token for the class
7318 * @error: error object to return any error
7320 * Returns: the MonoClass that represents @type_token in @image
7323 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7325 MonoClass *class = NULL;
7327 mono_error_init (error);
7329 if (image_is_dynamic (image)) {
7330 int table = mono_metadata_token_table (type_token);
7332 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7333 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7336 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7340 switch (type_token & 0xff000000){
7341 case MONO_TOKEN_TYPE_DEF:
7342 class = mono_class_create_from_typedef (image, type_token, error);
7344 case MONO_TOKEN_TYPE_REF:
7345 class = mono_class_from_typeref_checked (image, type_token, error);
7347 case MONO_TOKEN_TYPE_SPEC:
7348 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7351 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7355 /* Generic case, should be avoided for when a better error is possible. */
7356 if (!class && mono_error_ok (error)) {
7357 char *name = mono_class_name_from_token (image, type_token);
7358 char *assembly = mono_assembly_name_from_token (image, type_token);
7359 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7367 * mono_type_get_checked:
7368 * @image: the image where the type resides
7369 * @type_token: the token for the type
7370 * @context: the generic context used to evaluate generic instantiations in
7371 * @error: Error handling context
7373 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7375 * Returns: the MonoType that represents @type_token in @image
7378 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7380 MonoType *type = NULL;
7381 gboolean inflated = FALSE;
7383 mono_error_init (error);
7385 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7386 if (image_is_dynamic (image))
7387 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7389 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7390 MonoClass *class = mono_class_get_checked (image, type_token, error);
7393 mono_loader_assert_no_error ();
7398 return mono_class_get_type (class);
7401 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7404 mono_loader_assert_no_error ();
7409 MonoType *tmp = type;
7410 type = mono_class_get_type (mono_class_from_mono_type (type));
7411 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7412 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7413 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7415 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7417 if (type->type != tmp->type)
7420 mono_metadata_free_type (tmp);
7427 mono_class_get (MonoImage *image, guint32 type_token)
7429 return mono_class_get_full (image, type_token, NULL);
7433 * mono_image_init_name_cache:
7435 * Initializes the class name cache stored in image->name_cache.
7437 * LOCKING: Acquires the corresponding image lock.
7440 mono_image_init_name_cache (MonoImage *image)
7442 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7443 guint32 cols [MONO_TYPEDEF_SIZE];
7446 guint32 i, visib, nspace_index;
7447 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7449 if (image->name_cache)
7452 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7454 if (image_is_dynamic (image)) {
7455 mono_image_lock (image);
7456 if (image->name_cache) {
7457 /* Somebody initialized it before us */
7458 g_hash_table_destroy (the_name_cache);
7460 mono_atomic_store_release (&image->name_cache, the_name_cache);
7462 mono_image_unlock (image);
7466 /* Temporary hash table to avoid lookups in the nspace_table */
7467 name_cache2 = g_hash_table_new (NULL, NULL);
7469 for (i = 1; i <= t->rows; ++i) {
7470 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7471 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7473 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7474 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7476 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7478 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7479 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7481 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7482 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7483 if (!nspace_table) {
7484 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7485 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7486 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7489 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7492 /* Load type names from EXPORTEDTYPES table */
7494 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7495 guint32 cols [MONO_EXP_TYPE_SIZE];
7498 for (i = 0; i < t->rows; ++i) {
7499 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7500 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7501 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7503 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7504 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7505 if (!nspace_table) {
7506 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7507 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7508 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7511 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7515 g_hash_table_destroy (name_cache2);
7517 mono_image_lock (image);
7518 if (image->name_cache) {
7519 /* Somebody initialized it before us */
7520 g_hash_table_destroy (the_name_cache);
7522 mono_atomic_store_release (&image->name_cache, the_name_cache);
7524 mono_image_unlock (image);
7527 /*FIXME Only dynamic assemblies should allow this operation.*/
7529 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7530 const char *name, guint32 index)
7532 GHashTable *nspace_table;
7533 GHashTable *name_cache;
7536 mono_image_init_name_cache (image);
7537 mono_image_lock (image);
7539 name_cache = image->name_cache;
7540 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7541 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7542 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7545 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7546 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7548 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7550 mono_image_unlock (image);
7559 find_nocase (gpointer key, gpointer value, gpointer user_data)
7561 char *name = (char*)key;
7562 FindUserData *data = (FindUserData*)user_data;
7564 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7565 data->value = value;
7569 * mono_class_from_name_case:
7570 * @image: The MonoImage where the type is looked up in
7571 * @name_space: the type namespace
7572 * @name: the type short name.
7573 * @deprecated: use the _checked variant
7575 * Obtains a MonoClass with a given namespace and a given name which
7576 * is located in the given MonoImage. The namespace and name
7577 * lookups are case insensitive.
7580 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7583 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7584 g_assert (!mono_error_ok (&error));
7589 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7591 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7592 guint32 cols [MONO_TYPEDEF_SIZE];
7597 mono_error_init (error);
7599 if (image_is_dynamic (image)) {
7601 FindUserData user_data;
7603 mono_image_init_name_cache (image);
7604 mono_image_lock (image);
7606 user_data.key = name_space;
7607 user_data.value = NULL;
7608 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7610 if (user_data.value) {
7611 GHashTable *nspace_table = (GHashTable*)user_data.value;
7613 user_data.key = name;
7614 user_data.value = NULL;
7616 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7618 if (user_data.value)
7619 token = GPOINTER_TO_UINT (user_data.value);
7622 mono_image_unlock (image);
7625 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7631 /* add a cache if needed */
7632 for (i = 1; i <= t->rows; ++i) {
7633 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7634 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7636 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7637 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7639 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7641 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7642 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7643 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7644 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7650 return_nested_in (MonoClass *class, char *nested)
7653 char *s = strchr (nested, '/');
7654 gpointer iter = NULL;
7661 while ((found = mono_class_get_nested_types (class, &iter))) {
7662 if (strcmp (found->name, nested) == 0) {
7664 return return_nested_in (found, s);
7672 search_modules (MonoImage *image, const char *name_space, const char *name)
7674 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7675 MonoImage *file_image;
7680 * The EXPORTEDTYPES table only contains public types, so have to search the
7682 * Note: image->modules contains the contents of the MODULEREF table, while
7683 * the real module list is in the FILE table.
7685 for (i = 0; i < file_table->rows; i++) {
7686 guint32 cols [MONO_FILE_SIZE];
7687 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7688 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7691 file_image = mono_image_load_file_for_image (image, i + 1);
7693 class = mono_class_from_name (file_image, name_space, name);
7703 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7705 GHashTable *nspace_table;
7706 MonoImage *loaded_image;
7713 mono_error_init (error);
7715 // Checking visited images avoids stack overflows when cyclic references exist.
7716 if (g_hash_table_lookup (visited_images, image))
7719 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7721 if ((nested = strchr (name, '/'))) {
7722 int pos = nested - name;
7723 int len = strlen (name);
7726 memcpy (buf, name, len + 1);
7728 nested = buf + pos + 1;
7732 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7733 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7734 gboolean res = get_class_from_name (image, name_space, name, &class);
7737 class = search_modules (image, name_space, name);
7739 return class ? return_nested_in (class, nested) : NULL;
7745 mono_image_init_name_cache (image);
7746 mono_image_lock (image);
7748 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7751 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7753 mono_image_unlock (image);
7755 if (!token && image_is_dynamic (image) && image->modules) {
7756 /* Search modules as well */
7757 for (i = 0; i < image->module_count; ++i) {
7758 MonoImage *module = image->modules [i];
7760 class = mono_class_from_name (module, name_space, name);
7767 class = search_modules (image, name_space, name);
7775 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7776 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7777 guint32 cols [MONO_EXP_TYPE_SIZE];
7780 idx = mono_metadata_token_index (token);
7782 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7784 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7785 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7786 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7789 class = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7791 return return_nested_in (class, nested);
7793 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7794 guint32 assembly_idx;
7796 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7798 mono_assembly_load_reference (image, assembly_idx - 1);
7799 g_assert (image->references [assembly_idx - 1]);
7800 if (image->references [assembly_idx - 1] == (gpointer)-1)
7803 return mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7805 g_error ("not yet implemented");
7809 token = MONO_TOKEN_TYPE_DEF | token;
7811 class = mono_class_get_checked (image, token, error);
7813 return return_nested_in (class, nested);
7818 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7821 GHashTable *visited_images;
7823 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7825 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
7827 g_hash_table_destroy (visited_images);
7833 * mono_class_from_name:
7834 * @image: The MonoImage where the type is looked up in
7835 * @name_space: the type namespace
7836 * @name: the type short name.
7838 * Obtains a MonoClass with a given namespace and a given name which
7839 * is located in the given MonoImage.
7841 * To reference nested classes, use the "/" character as a separator.
7842 * For example use "Foo/Bar" to reference the class Bar that is nested
7843 * inside Foo, like this: "class Foo { class Bar {} }".
7846 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7851 klass = mono_class_from_name_checked (image, name_space, name, &error);
7852 if (!mono_error_ok (&error)) {
7853 mono_loader_set_error_from_mono_error (&error);
7854 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7860 * mono_class_is_subclass_of:
7861 * @klass: class to probe if it is a subclass of another one
7862 * @klassc: the class we suspect is the base class
7863 * @check_interfaces: whether we should perform interface checks
7865 * This method determines whether @klass is a subclass of @klassc.
7867 * If the @check_interfaces flag is set, then if @klassc is an interface
7868 * this method return true if the @klass implements the interface or
7869 * if @klass is an interface, if one of its base classes is @klass.
7871 * If @check_interfaces is false then, then if @klass is not an interface
7872 * then it returns true if the @klass is a subclass of @klassc.
7874 * if @klass is an interface and @klassc is System.Object, then this function
7879 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7880 gboolean check_interfaces)
7882 /*FIXME test for interfaces with variant generic arguments*/
7884 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7885 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7887 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7890 for (i = 0; i < klass->interface_count; i ++) {
7891 MonoClass *ic = klass->interfaces [i];
7896 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7901 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7904 if (klassc == mono_defaults.object_class)
7911 mono_type_is_generic_argument (MonoType *type)
7913 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7917 mono_class_has_variant_generic_params (MonoClass *klass)
7920 MonoGenericContainer *container;
7922 if (!klass->generic_class)
7925 container = klass->generic_class->container_class->generic_container;
7927 for (i = 0; i < container->type_argc; ++i)
7928 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7935 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7937 if (target == candidate)
7940 if (check_for_reference_conv &&
7941 mono_type_is_generic_argument (&target->byval_arg) &&
7942 mono_type_is_generic_argument (&candidate->byval_arg)) {
7943 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7944 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7946 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7949 if (!mono_class_is_assignable_from (target, candidate))
7955 * @container the generic container from the GTD
7956 * @klass: the class to be assigned to
7957 * @oklass: the source class
7959 * Both klass and oklass must be instances of the same generic interface.
7960 * Return true if @klass can be assigned to a @klass variable
7963 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7966 MonoType **klass_argv, **oklass_argv;
7967 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7968 MonoGenericContainer *container = klass_gtd->generic_container;
7970 if (klass == oklass)
7973 /*Viable candidates are instances of the same generic interface*/
7974 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7977 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7978 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7980 for (j = 0; j < container->type_argc; ++j) {
7981 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7982 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7984 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7988 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7989 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7991 if (param1_class != param2_class) {
7992 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7993 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7995 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7996 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8006 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8008 MonoGenericParam *gparam, *ogparam;
8009 MonoGenericParamInfo *tinfo, *cinfo;
8010 MonoClass **candidate_class;
8011 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8014 if (target == candidate)
8016 if (target->byval_arg.type != candidate->byval_arg.type)
8019 gparam = target->byval_arg.data.generic_param;
8020 ogparam = candidate->byval_arg.data.generic_param;
8021 tinfo = mono_generic_param_info (gparam);
8022 cinfo = mono_generic_param_info (ogparam);
8024 class_constraint_satisfied = FALSE;
8025 valuetype_constraint_satisfied = FALSE;
8027 /*candidate must have a super set of target's special constraints*/
8028 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8029 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8031 if (cinfo->constraints) {
8032 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8033 MonoClass *cc = *candidate_class;
8035 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8036 class_constraint_satisfied = TRUE;
8037 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8038 valuetype_constraint_satisfied = TRUE;
8041 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8042 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8044 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8046 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8048 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8049 valuetype_constraint_satisfied)) {
8054 /*candidate type constraints must be a superset of target's*/
8055 if (tinfo->constraints) {
8056 MonoClass **target_class;
8057 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8058 MonoClass *tc = *target_class;
8061 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8062 * check it's constraints since it satisfy the constraint by itself.
8064 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8067 if (!cinfo->constraints)
8070 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8071 MonoClass *cc = *candidate_class;
8073 if (mono_class_is_assignable_from (tc, cc))
8077 * This happens when we have the following:
8079 * Bar<K> where K : IFace
8080 * Foo<T, U> where T : U where U : IFace
8082 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8085 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8086 if (mono_gparam_is_assignable_from (target, cc))
8090 if (!*candidate_class)
8095 /*candidate itself must have a constraint that satisfy target*/
8096 if (cinfo->constraints) {
8097 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8098 MonoClass *cc = *candidate_class;
8099 if (mono_class_is_assignable_from (target, cc))
8107 * mono_class_is_assignable_from:
8108 * @klass: the class to be assigned to
8109 * @oklass: the source class
8111 * Return: true if an instance of object oklass can be assigned to an
8112 * instance of object @klass
8115 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8117 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8119 mono_class_init (klass);
8121 if (!oklass->inited)
8122 mono_class_init (oklass);
8124 if (klass->exception_type || oklass->exception_type)
8127 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8128 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8130 return mono_gparam_is_assignable_from (klass, oklass);
8133 if (MONO_CLASS_IS_INTERFACE (klass)) {
8134 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8135 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8136 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8140 for (i = 0; constraints [i]; ++i) {
8141 if (mono_class_is_assignable_from (klass, constraints [i]))
8149 /* interface_offsets might not be set for dynamic classes */
8150 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8152 * oklass might be a generic type parameter but they have
8153 * interface_offsets set.
8155 return mono_reflection_call_is_assignable_to (oklass, klass);
8156 if (!oklass->interface_bitmap)
8157 /* Happens with generic instances of not-yet created dynamic types */
8159 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8162 if (mono_class_has_variant_generic_params (klass)) {
8165 mono_class_setup_interfaces (oklass, &error);
8166 if (!mono_error_ok (&error)) {
8167 mono_error_cleanup (&error);
8171 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8172 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8173 MonoClass *iface = oklass->interfaces_packed [i];
8175 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8180 } else if (klass->delegate) {
8181 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8183 }else if (klass->rank) {
8184 MonoClass *eclass, *eoclass;
8186 if (oklass->rank != klass->rank)
8189 /* vectors vs. one dimensional arrays */
8190 if (oklass->byval_arg.type != klass->byval_arg.type)
8193 eclass = klass->cast_class;
8194 eoclass = oklass->cast_class;
8197 * a is b does not imply a[] is b[] when a is a valuetype, and
8198 * b is a reference type.
8201 if (eoclass->valuetype) {
8202 if ((eclass == mono_defaults.enum_class) ||
8203 (eclass == mono_defaults.enum_class->parent) ||
8204 (eclass == mono_defaults.object_class))
8208 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8209 } else if (mono_class_is_nullable (klass)) {
8210 if (mono_class_is_nullable (oklass))
8211 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8213 return mono_class_is_assignable_from (klass->cast_class, oklass);
8214 } else if (klass == mono_defaults.object_class)
8217 return mono_class_has_parent (oklass, klass);
8220 /*Check if @oklass is variant compatible with @klass.*/
8222 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8225 MonoType **klass_argv, **oklass_argv;
8226 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8227 MonoGenericContainer *container = klass_gtd->generic_container;
8229 /*Viable candidates are instances of the same generic interface*/
8230 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8233 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8234 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8236 for (j = 0; j < container->type_argc; ++j) {
8237 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8238 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8240 if (param1_class->valuetype != param2_class->valuetype)
8244 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8245 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8247 if (param1_class != param2_class) {
8248 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8249 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8251 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8252 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8260 /*Check if @candidate implements the interface @target*/
8262 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8266 gboolean is_variant = mono_class_has_variant_generic_params (target);
8268 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8269 if (mono_class_is_variant_compatible_slow (target, candidate))
8274 if (candidate == target)
8277 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8278 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8279 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8281 if (tb && tb->interfaces) {
8282 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8283 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8284 MonoClass *iface_class;
8286 /* we can't realize the type here since it can do pretty much anything. */
8289 iface_class = mono_class_from_mono_type (iface->type);
8290 if (iface_class == target)
8292 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8294 if (mono_class_implement_interface_slow (target, iface_class))
8299 /*setup_interfaces don't mono_class_init anything*/
8300 /*FIXME this doesn't handle primitive type arrays.
8301 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8302 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8304 mono_class_setup_interfaces (candidate, &error);
8305 if (!mono_error_ok (&error)) {
8306 mono_error_cleanup (&error);
8310 for (i = 0; i < candidate->interface_count; ++i) {
8311 if (candidate->interfaces [i] == target)
8314 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8317 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8321 candidate = candidate->parent;
8322 } while (candidate);
8328 * Check if @oklass can be assigned to @klass.
8329 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8332 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8334 if (candidate == target)
8336 if (target == mono_defaults.object_class)
8339 if (mono_class_has_parent (candidate, target))
8342 /*If target is not an interface there is no need to check them.*/
8343 if (MONO_CLASS_IS_INTERFACE (target))
8344 return mono_class_implement_interface_slow (target, candidate);
8346 if (target->delegate && mono_class_has_variant_generic_params (target))
8347 return mono_class_is_variant_compatible (target, candidate, FALSE);
8350 MonoClass *eclass, *eoclass;
8352 if (target->rank != candidate->rank)
8355 /* vectors vs. one dimensional arrays */
8356 if (target->byval_arg.type != candidate->byval_arg.type)
8359 eclass = target->cast_class;
8360 eoclass = candidate->cast_class;
8363 * a is b does not imply a[] is b[] when a is a valuetype, and
8364 * b is a reference type.
8367 if (eoclass->valuetype) {
8368 if ((eclass == mono_defaults.enum_class) ||
8369 (eclass == mono_defaults.enum_class->parent) ||
8370 (eclass == mono_defaults.object_class))
8374 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8376 /*FIXME properly handle nullables */
8377 /*FIXME properly handle (M)VAR */
8382 * mono_class_get_cctor:
8383 * @klass: A MonoClass pointer
8385 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8388 mono_class_get_cctor (MonoClass *klass)
8390 MonoCachedClassInfo cached_info;
8392 if (image_is_dynamic (klass->image)) {
8394 * has_cctor is not set for these classes because mono_class_init () is
8397 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8400 if (!klass->has_cctor)
8403 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8405 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8406 if (!mono_error_ok (&error))
8407 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8411 if (klass->generic_class && !klass->methods)
8412 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8414 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8418 * mono_class_get_finalizer:
8419 * @klass: The MonoClass pointer
8421 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8424 mono_class_get_finalizer (MonoClass *klass)
8426 MonoCachedClassInfo cached_info;
8429 mono_class_init (klass);
8430 if (!mono_class_has_finalizer (klass))
8433 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8435 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8436 if (!mono_error_ok (&error))
8437 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8440 mono_class_setup_vtable (klass);
8441 return klass->vtable [finalize_slot];
8446 * mono_class_needs_cctor_run:
8447 * @klass: the MonoClass pointer
8448 * @caller: a MonoMethod describing the caller
8450 * Determines whenever the class has a static constructor and whenever it
8451 * needs to be called when executing CALLER.
8454 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8458 method = mono_class_get_cctor (klass);
8460 return (method == caller) ? FALSE : TRUE;
8466 * mono_class_array_element_size:
8469 * Returns: the number of bytes an element of type @klass
8470 * uses when stored into an array.
8473 mono_class_array_element_size (MonoClass *klass)
8475 MonoType *type = &klass->byval_arg;
8478 switch (type->type) {
8481 case MONO_TYPE_BOOLEAN:
8485 case MONO_TYPE_CHAR:
8494 case MONO_TYPE_CLASS:
8495 case MONO_TYPE_STRING:
8496 case MONO_TYPE_OBJECT:
8497 case MONO_TYPE_SZARRAY:
8498 case MONO_TYPE_ARRAY:
8499 return sizeof (gpointer);
8504 case MONO_TYPE_VALUETYPE:
8505 if (type->data.klass->enumtype) {
8506 type = mono_class_enum_basetype (type->data.klass);
8507 klass = klass->element_class;
8510 return mono_class_instance_size (klass) - sizeof (MonoObject);
8511 case MONO_TYPE_GENERICINST:
8512 type = &type->data.generic_class->container_class->byval_arg;
8515 case MONO_TYPE_MVAR: {
8518 return mono_type_size (type, &align);
8520 case MONO_TYPE_VOID:
8524 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8530 * mono_array_element_size:
8531 * @ac: pointer to a #MonoArrayClass
8533 * Returns: the size of single array element.
8536 mono_array_element_size (MonoClass *ac)
8538 g_assert (ac->rank);
8539 return ac->sizes.element_size;
8543 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8544 MonoGenericContext *context)
8547 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8548 g_assert (mono_error_ok (&error));
8553 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8554 MonoGenericContext *context, MonoError *error)
8556 mono_error_init (error);
8558 if (image_is_dynamic (image)) {
8559 MonoClass *tmp_handle_class;
8560 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8562 g_assert (tmp_handle_class);
8564 *handle_class = tmp_handle_class;
8566 if (tmp_handle_class == mono_defaults.typehandle_class)
8567 return &((MonoClass*)obj)->byval_arg;
8572 switch (token & 0xff000000) {
8573 case MONO_TOKEN_TYPE_DEF:
8574 case MONO_TOKEN_TYPE_REF:
8575 case MONO_TOKEN_TYPE_SPEC: {
8578 *handle_class = mono_defaults.typehandle_class;
8579 type = mono_type_get_checked (image, token, context, error);
8583 mono_class_init (mono_class_from_mono_type (type));
8584 /* We return a MonoType* as handle */
8587 case MONO_TOKEN_FIELD_DEF: {
8589 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8591 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8595 *handle_class = mono_defaults.fieldhandle_class;
8596 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8600 mono_class_init (class);
8601 return mono_class_get_field (class, token);
8603 case MONO_TOKEN_METHOD_DEF:
8604 case MONO_TOKEN_METHOD_SPEC: {
8606 meth = mono_get_method_checked (image, token, NULL, context, error);
8608 *handle_class = mono_defaults.methodhandle_class;
8614 case MONO_TOKEN_MEMBER_REF: {
8615 guint32 cols [MONO_MEMBERREF_SIZE];
8617 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8618 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8619 mono_metadata_decode_blob_size (sig, &sig);
8620 if (*sig == 0x6) { /* it's a field */
8622 MonoClassField *field;
8623 field = mono_field_from_token_checked (image, token, &klass, context, error);
8625 *handle_class = mono_defaults.fieldhandle_class;
8629 meth = mono_get_method_checked (image, token, NULL, context, error);
8631 *handle_class = mono_defaults.methodhandle_class;
8636 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8642 * This function might need to call runtime functions so it can't be part
8643 * of the metadata library.
8645 static MonoLookupDynamicToken lookup_dynamic = NULL;
8648 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8650 lookup_dynamic = func;
8654 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8656 MonoClass *handle_class;
8658 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8662 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8664 return lookup_dynamic (image, token, valid_token, handle_class, context);
8667 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8670 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8672 get_cached_class_info = func;
8676 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8678 if (!get_cached_class_info)
8681 return get_cached_class_info (klass, res);
8685 mono_install_get_class_from_name (MonoGetClassFromName func)
8687 get_class_from_name = func;
8691 mono_class_get_image (MonoClass *klass)
8693 return klass->image;
8697 * mono_class_get_element_class:
8698 * @klass: the MonoClass to act on
8700 * Returns: the element class of an array or an enumeration.
8703 mono_class_get_element_class (MonoClass *klass)
8705 return klass->element_class;
8709 * mono_class_is_valuetype:
8710 * @klass: the MonoClass to act on
8712 * Returns: true if the MonoClass represents a ValueType.
8715 mono_class_is_valuetype (MonoClass *klass)
8717 return klass->valuetype;
8721 * mono_class_is_enum:
8722 * @klass: the MonoClass to act on
8724 * Returns: true if the MonoClass represents an enumeration.
8727 mono_class_is_enum (MonoClass *klass)
8729 return klass->enumtype;
8733 * mono_class_enum_basetype:
8734 * @klass: the MonoClass to act on
8736 * Returns: the underlying type representation for an enumeration.
8739 mono_class_enum_basetype (MonoClass *klass)
8741 if (klass->element_class == klass)
8742 /* SRE or broken types */
8745 return &klass->element_class->byval_arg;
8749 * mono_class_get_parent
8750 * @klass: the MonoClass to act on
8752 * Returns: the parent class for this class.
8755 mono_class_get_parent (MonoClass *klass)
8757 return klass->parent;
8761 * mono_class_get_nesting_type;
8762 * @klass: the MonoClass to act on
8764 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8767 mono_class_get_nesting_type (MonoClass *klass)
8769 return klass->nested_in;
8773 * mono_class_get_rank:
8774 * @klass: the MonoClass to act on
8776 * Returns: the rank for the array (the number of dimensions).
8779 mono_class_get_rank (MonoClass *klass)
8785 * mono_class_get_flags:
8786 * @klass: the MonoClass to act on
8788 * The type flags from the TypeDef table from the metadata.
8789 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8792 * Returns: the flags from the TypeDef table.
8795 mono_class_get_flags (MonoClass *klass)
8797 return klass->flags;
8801 * mono_class_get_name
8802 * @klass: the MonoClass to act on
8804 * Returns: the name of the class.
8807 mono_class_get_name (MonoClass *klass)
8813 * mono_class_get_namespace:
8814 * @klass: the MonoClass to act on
8816 * Returns: the namespace of the class.
8819 mono_class_get_namespace (MonoClass *klass)
8821 return klass->name_space;
8825 * mono_class_get_type:
8826 * @klass: the MonoClass to act on
8828 * This method returns the internal Type representation for the class.
8830 * Returns: the MonoType from the class.
8833 mono_class_get_type (MonoClass *klass)
8835 return &klass->byval_arg;
8839 * mono_class_get_type_token
8840 * @klass: the MonoClass to act on
8842 * This method returns type token for the class.
8844 * Returns: the type token for the class.
8847 mono_class_get_type_token (MonoClass *klass)
8849 return klass->type_token;
8853 * mono_class_get_byref_type:
8854 * @klass: the MonoClass to act on
8859 mono_class_get_byref_type (MonoClass *klass)
8861 return &klass->this_arg;
8865 * mono_class_num_fields:
8866 * @klass: the MonoClass to act on
8868 * Returns: the number of static and instance fields in the class.
8871 mono_class_num_fields (MonoClass *klass)
8873 return klass->field.count;
8877 * mono_class_num_methods:
8878 * @klass: the MonoClass to act on
8880 * Returns: the number of methods in the class.
8883 mono_class_num_methods (MonoClass *klass)
8885 return klass->method.count;
8889 * mono_class_num_properties
8890 * @klass: the MonoClass to act on
8892 * Returns: the number of properties in the class.
8895 mono_class_num_properties (MonoClass *klass)
8897 mono_class_setup_properties (klass);
8899 return klass->ext->property.count;
8903 * mono_class_num_events:
8904 * @klass: the MonoClass to act on
8906 * Returns: the number of events in the class.
8909 mono_class_num_events (MonoClass *klass)
8911 mono_class_setup_events (klass);
8913 return klass->ext->event.count;
8917 * mono_class_get_fields:
8918 * @klass: the MonoClass to act on
8920 * This routine is an iterator routine for retrieving the fields in a class.
8922 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8923 * iterate over all of the elements. When no more values are
8924 * available, the return value is NULL.
8926 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8929 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8931 MonoClassField* field;
8935 mono_class_setup_fields_locking (klass);
8936 if (klass->exception_type)
8938 /* start from the first */
8939 if (klass->field.count) {
8940 return *iter = &klass->fields [0];
8948 if (field < &klass->fields [klass->field.count]) {
8949 return *iter = field;
8955 * mono_class_get_methods
8956 * @klass: the MonoClass to act on
8958 * This routine is an iterator routine for retrieving the fields in a class.
8960 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8961 * iterate over all of the elements. When no more values are
8962 * available, the return value is NULL.
8964 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8967 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8969 MonoMethod** method;
8973 mono_class_setup_methods (klass);
8976 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8977 * FIXME we should better report this error to the caller
8979 if (!klass->methods)
8981 /* start from the first */
8982 if (klass->method.count) {
8983 *iter = &klass->methods [0];
8984 return klass->methods [0];
8992 if (method < &klass->methods [klass->method.count]) {
9000 * mono_class_get_virtual_methods:
9002 * Iterate over the virtual methods of KLASS.
9004 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9007 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9009 MonoMethod** method;
9012 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9014 mono_class_setup_methods (klass);
9016 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9017 * FIXME we should better report this error to the caller
9019 if (!klass->methods)
9021 /* start from the first */
9022 method = &klass->methods [0];
9027 while (method < &klass->methods [klass->method.count]) {
9028 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9032 if (method < &klass->methods [klass->method.count]) {
9039 /* Search directly in metadata to avoid calling setup_methods () */
9040 MonoMethod *res = NULL;
9046 start_index = GPOINTER_TO_UINT (*iter);
9049 for (i = start_index; i < klass->method.count; ++i) {
9052 /* class->method.first points into the methodptr table */
9053 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9055 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9059 if (i < klass->method.count) {
9061 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9062 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9064 /* Add 1 here so the if (*iter) check fails */
9065 *iter = GUINT_TO_POINTER (i + 1);
9074 * mono_class_get_properties:
9075 * @klass: the MonoClass to act on
9077 * This routine is an iterator routine for retrieving the properties in a class.
9079 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9080 * iterate over all of the elements. When no more values are
9081 * available, the return value is NULL.
9083 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9086 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9088 MonoProperty* property;
9092 mono_class_setup_properties (klass);
9093 /* start from the first */
9094 if (klass->ext->property.count) {
9095 return *iter = &klass->ext->properties [0];
9103 if (property < &klass->ext->properties [klass->ext->property.count]) {
9104 return *iter = property;
9110 * mono_class_get_events:
9111 * @klass: the MonoClass to act on
9113 * This routine is an iterator routine for retrieving the properties in a class.
9115 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9116 * iterate over all of the elements. When no more values are
9117 * available, the return value is NULL.
9119 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9122 mono_class_get_events (MonoClass* klass, gpointer *iter)
9128 mono_class_setup_events (klass);
9129 /* start from the first */
9130 if (klass->ext->event.count) {
9131 return *iter = &klass->ext->events [0];
9139 if (event < &klass->ext->events [klass->ext->event.count]) {
9140 return *iter = event;
9146 * mono_class_get_interfaces
9147 * @klass: the MonoClass to act on
9149 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9151 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9152 * iterate over all of the elements. When no more values are
9153 * available, the return value is NULL.
9155 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9158 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9166 mono_class_init (klass);
9167 if (!klass->interfaces_inited) {
9168 mono_class_setup_interfaces (klass, &error);
9169 if (!mono_error_ok (&error)) {
9170 mono_error_cleanup (&error);
9174 /* start from the first */
9175 if (klass->interface_count) {
9176 *iter = &klass->interfaces [0];
9177 return klass->interfaces [0];
9185 if (iface < &klass->interfaces [klass->interface_count]) {
9193 setup_nested_types (MonoClass *klass)
9196 GList *classes, *nested_classes, *l;
9199 if (klass->nested_classes_inited)
9202 if (!klass->type_token)
9203 klass->nested_classes_inited = TRUE;
9205 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9209 guint32 cols [MONO_NESTED_CLASS_SIZE];
9210 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9211 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9212 if (!mono_error_ok (&error)) {
9213 /*FIXME don't swallow the error message*/
9214 mono_error_cleanup (&error);
9216 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9220 classes = g_list_prepend (classes, nclass);
9222 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9225 mono_class_alloc_ext (klass);
9227 nested_classes = NULL;
9228 for (l = classes; l; l = l->next)
9229 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9230 g_list_free (classes);
9232 mono_image_lock (klass->image);
9234 mono_memory_barrier ();
9235 if (!klass->nested_classes_inited) {
9236 klass->ext->nested_classes = nested_classes;
9237 mono_memory_barrier ();
9238 klass->nested_classes_inited = TRUE;
9241 mono_image_unlock (klass->image);
9245 * mono_class_get_nested_types
9246 * @klass: the MonoClass to act on
9248 * This routine is an iterator routine for retrieving the nested types of a class.
9249 * This works only if @klass is non-generic, or a generic type definition.
9251 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9252 * iterate over all of the elements. When no more values are
9253 * available, the return value is NULL.
9255 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9258 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9264 if (!klass->nested_classes_inited)
9265 setup_nested_types (klass);
9268 /* start from the first */
9269 if (klass->ext && klass->ext->nested_classes) {
9270 *iter = klass->ext->nested_classes;
9271 return klass->ext->nested_classes->data;
9273 /* no nested types */
9288 * mono_class_is_delegate
9289 * @klass: the MonoClass to act on
9291 * Returns: true if the MonoClass represents a System.Delegate.
9294 mono_class_is_delegate (MonoClass *klass)
9296 return klass->delegate;
9300 * mono_class_implements_interface
9301 * @klass: The MonoClass to act on
9302 * @interface: The interface to check if @klass implements.
9304 * Returns: true if @klass implements @interface.
9307 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9309 return mono_class_is_assignable_from (iface, klass);
9313 * mono_field_get_name:
9314 * @field: the MonoClassField to act on
9316 * Returns: the name of the field.
9319 mono_field_get_name (MonoClassField *field)
9325 * mono_field_get_type:
9326 * @field: the MonoClassField to act on
9328 * Returns: MonoType of the field.
9331 mono_field_get_type (MonoClassField *field)
9334 MonoType *type = mono_field_get_type_checked (field, &error);
9335 if (!mono_error_ok (&error)) {
9336 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9337 mono_error_cleanup (&error);
9344 * mono_field_get_type_checked:
9345 * @field: the MonoClassField to act on
9346 * @error: used to return any erro found while retrieving @field type
9348 * Returns: MonoType of the field.
9351 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9353 mono_error_init (error);
9355 mono_field_resolve_type (field, error);
9360 * mono_field_get_parent:
9361 * @field: the MonoClassField to act on
9363 * Returns: MonoClass where the field was defined.
9366 mono_field_get_parent (MonoClassField *field)
9368 return field->parent;
9372 * mono_field_get_flags;
9373 * @field: the MonoClassField to act on
9375 * The metadata flags for a field are encoded using the
9376 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9378 * Returns: the flags for the field.
9381 mono_field_get_flags (MonoClassField *field)
9384 return mono_field_resolve_flags (field);
9385 return field->type->attrs;
9389 * mono_field_get_offset;
9390 * @field: the MonoClassField to act on
9392 * Returns: the field offset.
9395 mono_field_get_offset (MonoClassField *field)
9397 return field->offset;
9401 mono_field_get_rva (MonoClassField *field)
9405 MonoClass *klass = field->parent;
9406 MonoFieldDefaultValue *field_def_values;
9408 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9410 if (!klass->ext || !klass->ext->field_def_values) {
9411 mono_class_alloc_ext (klass);
9413 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9415 mono_image_lock (klass->image);
9416 if (!klass->ext->field_def_values)
9417 klass->ext->field_def_values = field_def_values;
9418 mono_image_unlock (klass->image);
9421 field_index = mono_field_get_index (field);
9423 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9424 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9426 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9427 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9430 return klass->ext->field_def_values [field_index].data;
9434 * mono_field_get_data;
9435 * @field: the MonoClassField to act on
9437 * Returns: pointer to the metadata constant value or to the field
9438 * data if it has an RVA flag.
9441 mono_field_get_data (MonoClassField *field)
9443 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9444 MonoTypeEnum def_type;
9446 return mono_class_get_field_default_value (field, &def_type);
9447 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9448 return mono_field_get_rva (field);
9455 * mono_property_get_name:
9456 * @prop: the MonoProperty to act on
9458 * Returns: the name of the property
9461 mono_property_get_name (MonoProperty *prop)
9467 * mono_property_get_set_method
9468 * @prop: the MonoProperty to act on.
9470 * Returns: the setter method of the property (A MonoMethod)
9473 mono_property_get_set_method (MonoProperty *prop)
9479 * mono_property_get_get_method
9480 * @prop: the MonoProperty to act on.
9482 * Returns: the setter method of the property (A MonoMethod)
9485 mono_property_get_get_method (MonoProperty *prop)
9491 * mono_property_get_parent:
9492 * @prop: the MonoProperty to act on.
9494 * Returns: the MonoClass where the property was defined.
9497 mono_property_get_parent (MonoProperty *prop)
9499 return prop->parent;
9503 * mono_property_get_flags:
9504 * @prop: the MonoProperty to act on.
9506 * The metadata flags for a property are encoded using the
9507 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9509 * Returns: the flags for the property.
9512 mono_property_get_flags (MonoProperty *prop)
9518 * mono_event_get_name:
9519 * @event: the MonoEvent to act on
9521 * Returns: the name of the event.
9524 mono_event_get_name (MonoEvent *event)
9530 * mono_event_get_add_method:
9531 * @event: The MonoEvent to act on.
9533 * Returns: the @add' method for the event (a MonoMethod).
9536 mono_event_get_add_method (MonoEvent *event)
9542 * mono_event_get_remove_method:
9543 * @event: The MonoEvent to act on.
9545 * Returns: the @remove method for the event (a MonoMethod).
9548 mono_event_get_remove_method (MonoEvent *event)
9550 return event->remove;
9554 * mono_event_get_raise_method:
9555 * @event: The MonoEvent to act on.
9557 * Returns: the @raise method for the event (a MonoMethod).
9560 mono_event_get_raise_method (MonoEvent *event)
9562 return event->raise;
9566 * mono_event_get_parent:
9567 * @event: the MonoEvent to act on.
9569 * Returns: the MonoClass where the event is defined.
9572 mono_event_get_parent (MonoEvent *event)
9574 return event->parent;
9578 * mono_event_get_flags
9579 * @event: the MonoEvent to act on.
9581 * The metadata flags for an event are encoded using the
9582 * EVENT_* constants. See the tabledefs.h file for details.
9584 * Returns: the flags for the event.
9587 mono_event_get_flags (MonoEvent *event)
9589 return event->attrs;
9593 * mono_class_get_method_from_name:
9594 * @klass: where to look for the method
9595 * @name: name of the method
9596 * @param_count: number of parameters. -1 for any number.
9598 * Obtains a MonoMethod with a given name and number of parameters.
9599 * It only works if there are no multiple signatures for any given method name.
9602 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9604 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9608 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9610 MonoMethod *res = NULL;
9613 /* Search directly in the metadata to avoid calling setup_methods () */
9614 for (i = 0; i < klass->method.count; ++i) {
9616 guint32 cols [MONO_METHOD_SIZE];
9618 MonoMethodSignature *sig;
9620 /* class->method.first points into the methodptr table */
9621 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9623 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9624 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9626 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9629 if (param_count == -1) {
9633 sig = mono_method_signature_checked (method, &error);
9635 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9638 if (sig->param_count == param_count) {
9649 * mono_class_get_method_from_name_flags:
9650 * @klass: where to look for the method
9651 * @name_space: name of the method
9652 * @param_count: number of parameters. -1 for any number.
9653 * @flags: flags which must be set in the method
9655 * Obtains a MonoMethod with a given name and number of parameters.
9656 * It only works if there are no multiple signatures for any given method name.
9659 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9661 MonoMethod *res = NULL;
9664 mono_class_init (klass);
9666 if (klass->generic_class && !klass->methods) {
9667 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9670 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9671 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9676 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9677 mono_class_setup_methods (klass);
9679 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9680 See mono/tests/array_load_exception.il
9681 FIXME we should better report this error to the caller
9683 if (!klass->methods)
9685 for (i = 0; i < klass->method.count; ++i) {
9686 MonoMethod *method = klass->methods [i];
9688 if (method->name[0] == name [0] &&
9689 !strcmp (name, method->name) &&
9690 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9691 ((method->flags & flags) == flags)) {
9698 res = find_method_in_metadata (klass, name, param_count, flags);
9705 * mono_class_set_failure:
9706 * @klass: class in which the failure was detected
9707 * @ex_type: the kind of exception/error to be thrown (later)
9708 * @ex_data: exception data (specific to each type of exception/error)
9710 * Keep a detected failure informations in the class for later processing.
9711 * Note that only the first failure is kept.
9713 * LOCKING: Acquires the loader lock.
9716 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9718 if (klass->exception_type)
9721 mono_loader_lock ();
9722 klass->exception_type = ex_type;
9724 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9725 mono_loader_unlock ();
9731 * mono_class_get_exception_data:
9733 * Return the exception_data property of KLASS.
9735 * LOCKING: Acquires the loader lock.
9738 mono_class_get_exception_data (MonoClass *klass)
9740 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9744 * mono_classes_init:
9746 * Initialize the resources used by this module.
9749 mono_classes_init (void)
9751 mono_mutex_init (&classes_mutex);
9753 mono_counters_register ("Inflated methods size",
9754 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9755 mono_counters_register ("Inflated classes",
9756 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9757 mono_counters_register ("Inflated classes size",
9758 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9759 mono_counters_register ("MonoClass size",
9760 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9761 mono_counters_register ("MonoClassExt size",
9762 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9766 * mono_classes_cleanup:
9768 * Free the resources used by this module.
9771 mono_classes_cleanup (void)
9773 if (global_interface_bitset)
9774 mono_bitset_free (global_interface_bitset);
9775 global_interface_bitset = NULL;
9776 mono_mutex_destroy (&classes_mutex);
9780 * mono_class_get_exception_for_failure:
9781 * @klass: class in which the failure was detected
9783 * Return a constructed MonoException than the caller can then throw
9784 * using mono_raise_exception - or NULL if no failure is present (or
9785 * doesn't result in an exception).
9788 mono_class_get_exception_for_failure (MonoClass *klass)
9790 gpointer exception_data = mono_class_get_exception_data (klass);
9792 switch (klass->exception_type) {
9793 case MONO_EXCEPTION_TYPE_LOAD: {
9796 char *str = mono_type_get_full_name (klass);
9797 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9798 name = mono_string_new (mono_domain_get (), str);
9800 ex = mono_get_exception_type_load (name, astr);
9804 case MONO_EXCEPTION_MISSING_METHOD: {
9805 char *class_name = exception_data;
9806 char *assembly_name = class_name + strlen (class_name) + 1;
9808 return mono_get_exception_missing_method (class_name, assembly_name);
9810 case MONO_EXCEPTION_MISSING_FIELD: {
9811 char *class_name = exception_data;
9812 char *member_name = class_name + strlen (class_name) + 1;
9814 return mono_get_exception_missing_field (class_name, member_name);
9816 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9817 char *msg_format = exception_data;
9818 char *assembly_name = msg_format + strlen (msg_format) + 1;
9819 char *msg = g_strdup_printf (msg_format, assembly_name);
9822 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9828 case MONO_EXCEPTION_BAD_IMAGE: {
9829 return mono_get_exception_bad_image_format (exception_data);
9832 MonoLoaderError *error;
9835 error = mono_loader_get_last_error ();
9837 ex = mono_loader_error_prepare_exception (error);
9841 /* TODO - handle other class related failures */
9848 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9850 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9851 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9853 if (outer_klass == inner_klass)
9855 inner_klass = inner_klass->nested_in;
9856 } while (inner_klass);
9861 mono_class_get_generic_type_definition (MonoClass *klass)
9863 return klass->generic_class ? klass->generic_class->container_class : klass;
9867 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9869 * Generic instantiations are ignored for all super types of @klass.
9871 * Visibility checks ignoring generic instantiations.
9874 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9877 klass = mono_class_get_generic_type_definition (klass);
9878 parent = mono_class_get_generic_type_definition (parent);
9879 mono_class_setup_supertypes (klass);
9881 for (i = 0; i < klass->idepth; ++i) {
9882 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9888 * Subtype can only access parent members with family protection if the site object
9889 * is subclass of Subtype. For example:
9890 * class A { protected int x; }
9892 * void valid_access () {
9896 * void invalid_access () {
9903 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9905 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9908 if (context_klass == NULL)
9910 /*if access_klass is not member_klass context_klass must be type compat*/
9911 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9917 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9920 if (accessing == accessed)
9922 if (!accessed || !accessing)
9925 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9926 * anywhere so untrusted friends are not safe to access platform's code internals */
9927 if (mono_security_core_clr_enabled ()) {
9928 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9932 mono_assembly_load_friends (accessed);
9933 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9934 MonoAssemblyName *friend = tmp->data;
9935 /* Be conservative with checks */
9938 if (strcmp (accessing->aname.name, friend->name))
9940 if (friend->public_key_token [0]) {
9941 if (!accessing->aname.public_key_token [0])
9943 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9952 * If klass is a generic type or if it is derived from a generic type, return the
9953 * MonoClass of the generic definition
9954 * Returns NULL if not found
9957 get_generic_definition_class (MonoClass *klass)
9960 if (klass->generic_class && klass->generic_class->container_class)
9961 return klass->generic_class->container_class;
9962 klass = klass->parent;
9968 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9971 for (i = 0; i < ginst->type_argc; ++i) {
9972 MonoType *type = ginst->type_argv[i];
9973 switch (type->type) {
9974 case MONO_TYPE_SZARRAY:
9975 if (!can_access_type (access_klass, type->data.klass))
9978 case MONO_TYPE_ARRAY:
9979 if (!can_access_type (access_klass, type->data.array->eklass))
9983 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9986 case MONO_TYPE_CLASS:
9987 case MONO_TYPE_VALUETYPE:
9988 case MONO_TYPE_GENERICINST:
9989 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9999 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10003 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10006 if (access_klass->element_class && !access_klass->enumtype)
10007 access_klass = access_klass->element_class;
10009 if (member_klass->element_class && !member_klass->enumtype)
10010 member_klass = member_klass->element_class;
10012 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10014 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10017 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10020 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10023 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10026 /*Non nested type with nested visibility. We just fail it.*/
10027 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10030 switch (access_level) {
10031 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10032 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10034 case TYPE_ATTRIBUTE_PUBLIC:
10037 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10040 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10041 return is_nesting_type (member_klass, access_klass);
10043 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10044 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10046 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10047 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10049 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10050 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10051 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10053 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10054 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10055 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10060 /* FIXME: check visibility of type, too */
10062 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10064 MonoClass *member_generic_def;
10065 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10068 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10069 access_klass->generic_container) &&
10070 (member_generic_def = get_generic_definition_class (member_klass))) {
10071 MonoClass *access_container;
10073 if (access_klass->generic_container)
10074 access_container = access_klass;
10076 access_container = access_klass->generic_class->container_class;
10078 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10082 /* Partition I 8.5.3.2 */
10083 /* the access level values are the same for fields and methods */
10084 switch (access_level) {
10085 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10086 /* same compilation unit */
10087 return access_klass->image == member_klass->image;
10088 case FIELD_ATTRIBUTE_PRIVATE:
10089 return access_klass == member_klass;
10090 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10091 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10092 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10095 case FIELD_ATTRIBUTE_ASSEMBLY:
10096 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10097 case FIELD_ATTRIBUTE_FAMILY:
10098 if (is_valid_family_access (access_klass, member_klass, context_klass))
10101 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10102 if (is_valid_family_access (access_klass, member_klass, context_klass))
10104 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10105 case FIELD_ATTRIBUTE_PUBLIC:
10112 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10114 /* FIXME: check all overlapping fields */
10115 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10117 MonoClass *nested = method->klass->nested_in;
10119 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10122 nested = nested->nested_in;
10129 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10131 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10133 MonoClass *nested = method->klass->nested_in;
10135 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10138 nested = nested->nested_in;
10143 * with generics calls to explicit interface implementations can be expressed
10144 * directly: the method is private, but we must allow it. This may be opening
10145 * a hole or the generics code should handle this differently.
10146 * Maybe just ensure the interface type is public.
10148 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10154 * mono_method_can_access_method_full:
10155 * @method: The caller method
10156 * @called: The called method
10157 * @context_klass: The static type on stack of the owner @called object used
10159 * This function must be used with instance calls, as they have more strict family accessibility.
10160 * It can be used with static methods, but context_klass should be NULL.
10162 * Returns: TRUE if caller have proper visibility and acessibility to @called
10165 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10167 MonoClass *access_class = method->klass;
10168 MonoClass *member_class = called->klass;
10169 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10171 MonoClass *nested = access_class->nested_in;
10173 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10176 nested = nested->nested_in;
10183 can = can_access_type (access_class, member_class);
10185 MonoClass *nested = access_class->nested_in;
10187 can = can_access_type (nested, member_class);
10190 nested = nested->nested_in;
10197 if (called->is_inflated) {
10198 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10199 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10208 * mono_method_can_access_field_full:
10209 * @method: The caller method
10210 * @field: The accessed field
10211 * @context_klass: The static type on stack of the owner @field object used
10213 * This function must be used with instance fields, as they have more strict family accessibility.
10214 * It can be used with static fields, but context_klass should be NULL.
10216 * Returns: TRUE if caller have proper visibility and acessibility to @field
10219 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10221 MonoClass *access_class = method->klass;
10222 MonoClass *member_class = field->parent;
10223 /* FIXME: check all overlapping fields */
10224 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10226 MonoClass *nested = access_class->nested_in;
10228 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10231 nested = nested->nested_in;
10238 can = can_access_type (access_class, member_class);
10240 MonoClass *nested = access_class->nested_in;
10242 can = can_access_type (nested, member_class);
10245 nested = nested->nested_in;
10255 * mono_class_can_access_class:
10256 * @source_class: The source class
10257 * @target_class: The accessed class
10259 * This function returns is @target_class is visible to @source_class
10261 * Returns: TRUE if source have proper visibility and acessibility to target
10264 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10266 return can_access_type (source_class, target_class);
10270 * mono_type_is_valid_enum_basetype:
10271 * @type: The MonoType to check
10273 * Returns: TRUE if the type can be used as the basetype of an enum
10275 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10276 switch (type->type) {
10279 case MONO_TYPE_BOOLEAN:
10282 case MONO_TYPE_CHAR:
10296 * mono_class_is_valid_enum:
10297 * @klass: An enum class to be validated
10299 * This method verify the required properties an enum should have.
10301 * Returns: TRUE if the informed enum class is valid
10303 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10304 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10305 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10307 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10308 MonoClassField * field;
10309 gpointer iter = NULL;
10310 gboolean found_base_field = FALSE;
10312 g_assert (klass->enumtype);
10313 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10314 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10318 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10321 while ((field = mono_class_get_fields (klass, &iter))) {
10322 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10323 if (found_base_field)
10325 found_base_field = TRUE;
10326 if (!mono_type_is_valid_enum_basetype (field->type))
10331 if (!found_base_field)
10334 if (klass->method.count > 0)
10341 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10343 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10347 * mono_class_setup_interface_id:
10349 * Initializes MonoClass::interface_id if required.
10351 * LOCKING: Acquires the loader lock.
10354 mono_class_setup_interface_id (MonoClass *class)
10356 mono_loader_lock ();
10357 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10358 class->interface_id = mono_get_unique_iid (class);
10359 mono_loader_unlock ();
10363 * mono_class_alloc_ext:
10365 * Allocate klass->ext if not already done.
10368 mono_class_alloc_ext (MonoClass *klass)
10375 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10376 mono_image_lock (klass->image);
10377 mono_memory_barrier ();
10380 class_ext_size += sizeof (MonoClassExt);
10381 mono_image_unlock (klass->image);
10385 * mono_class_setup_interfaces:
10387 * Initialize class->interfaces/interfaces_count.
10388 * LOCKING: Acquires the loader lock.
10389 * This function can fail the type.
10392 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10394 int i, interface_count;
10395 MonoClass **interfaces;
10397 mono_error_init (error);
10399 if (klass->interfaces_inited)
10402 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10403 MonoType *args [1];
10405 /* generic IList, ICollection, IEnumerable */
10406 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10407 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10409 args [0] = &klass->element_class->byval_arg;
10410 interfaces [0] = mono_class_bind_generic_parameters (
10411 mono_defaults.generic_ilist_class, 1, args, FALSE);
10412 if (interface_count > 1)
10413 interfaces [1] = mono_class_bind_generic_parameters (
10414 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10415 } else if (klass->generic_class) {
10416 MonoClass *gklass = klass->generic_class->container_class;
10418 mono_class_setup_interfaces (gklass, error);
10419 if (!mono_error_ok (error)) {
10420 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10424 interface_count = gklass->interface_count;
10425 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10426 for (i = 0; i < interface_count; i++) {
10427 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10428 if (!mono_error_ok (error)) {
10429 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10434 interface_count = 0;
10438 mono_image_lock (klass->image);
10440 if (!klass->interfaces_inited) {
10441 klass->interface_count = interface_count;
10442 klass->interfaces = interfaces;
10444 mono_memory_barrier ();
10446 klass->interfaces_inited = TRUE;
10449 mono_image_unlock (klass->image);
10453 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10455 MonoClass *class = field->parent;
10456 MonoImage *image = class->image;
10457 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10458 int field_idx = field - class->fields;
10460 mono_error_init (error);
10463 MonoClassField *gfield = >d->fields [field_idx];
10464 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10465 if (!mono_error_ok (error)) {
10466 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10467 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10471 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10472 if (!mono_error_ok (error)) {
10473 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10474 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10479 guint32 cols [MONO_FIELD_SIZE];
10480 MonoGenericContainer *container = NULL;
10481 int idx = class->field.first + field_idx;
10483 /*FIXME, in theory we do not lazy load SRE fields*/
10484 g_assert (!image_is_dynamic (image));
10486 if (class->generic_container) {
10487 container = class->generic_container;
10489 container = gtd->generic_container;
10490 g_assert (container);
10493 /* class->field.first and idx points into the fieldptr table */
10494 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10496 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10497 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10498 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10502 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10504 mono_metadata_decode_value (sig, &sig);
10505 /* FIELD signature == 0x06 */
10506 g_assert (*sig == 0x06);
10507 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10509 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10514 mono_field_resolve_flags (MonoClassField *field)
10516 MonoClass *class = field->parent;
10517 MonoImage *image = class->image;
10518 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10519 int field_idx = field - class->fields;
10523 MonoClassField *gfield = >d->fields [field_idx];
10524 return mono_field_get_flags (gfield);
10526 int idx = class->field.first + field_idx;
10528 /*FIXME, in theory we do not lazy load SRE fields*/
10529 g_assert (!image_is_dynamic (image));
10531 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10536 * mono_class_setup_basic_field_info:
10537 * @class: The class to initialize
10539 * Initializes the class->fields array of fields.
10540 * Aquires the loader lock.
10543 mono_class_setup_basic_field_info_locking (MonoClass *class)
10545 mono_loader_lock ();
10546 mono_class_setup_basic_field_info (class);
10547 mono_loader_unlock ();
10551 * mono_class_get_fields_lazy:
10552 * @klass: the MonoClass to act on
10554 * This routine is an iterator routine for retrieving the fields in a class.
10555 * Only minimal information about fields are loaded. Accessors must be used
10556 * for all MonoClassField returned.
10558 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10559 * iterate over all of the elements. When no more values are
10560 * available, the return value is NULL.
10562 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10565 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10567 MonoClassField* field;
10571 mono_class_setup_basic_field_info_locking (klass);
10572 if (!klass->fields)
10574 /* start from the first */
10575 if (klass->field.count) {
10576 return *iter = &klass->fields [0];
10584 if (field < &klass->fields [klass->field.count]) {
10585 return *iter = field;
10591 mono_class_full_name (MonoClass *klass)
10593 return mono_type_full_name (&klass->byval_arg);