2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation;
99 static GSList *gclass_recorded_list;
100 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
105 mono_locks_acquire (&classes_mutex, ClassesLock);
109 classes_unlock (void)
111 mono_locks_release (&classes_mutex, ClassesLock);
115 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
118 enable_gclass_recording (void)
120 ++record_gclass_instantiation;
124 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
127 disable_gclass_recording (gclass_record_func func, void *user_data)
129 GSList **head = &gclass_recorded_list;
131 g_assert (record_gclass_instantiation > 0);
132 --record_gclass_instantiation;
135 GSList *node = *head;
136 if (func ((MonoClass*)node->data, user_data)) {
138 g_slist_free_1 (node);
144 /* We automatically discard all recorded gclasses when disabled. */
145 if (!record_gclass_instantiation && gclass_recorded_list) {
146 g_slist_free (gclass_recorded_list);
147 gclass_recorded_list = NULL;
152 * mono_class_from_typeref:
153 * @image: a MonoImage
154 * @type_token: a TypeRef token
156 * Creates the MonoClass* structure representing the type defined by
157 * the typeref token valid inside @image.
158 * Returns: the MonoClass* representing the typeref token, NULL ifcould
162 mono_class_from_typeref (MonoImage *image, guint32 type_token)
165 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
166 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
171 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
173 guint32 cols [MONO_TYPEREF_SIZE];
174 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
176 const char *name, *nspace;
177 MonoClass *res = NULL;
180 mono_error_init (error);
182 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
185 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
187 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
188 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
190 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
191 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
192 case MONO_RESOLUTION_SCOPE_MODULE:
194 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
195 This is not the observed behavior of existing implementations.
196 The defacto behavior is that it's just a typedef in disguise.
198 /* a typedef in disguise */
199 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
202 case MONO_RESOLUTION_SCOPE_MODULEREF:
203 module = mono_image_load_module (image, idx);
205 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
208 case MONO_RESOLUTION_SCOPE_TYPEREF: {
209 MonoClass *enclosing;
212 if (idx == mono_metadata_token_index (type_token)) {
213 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
217 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
218 if (!mono_error_ok (error))
221 if (enclosing->nested_classes_inited && enclosing->ext) {
222 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
223 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
225 if (strcmp (res->name, name) == 0)
229 /* Don't call mono_class_init as we might've been called by it recursively */
230 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
232 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
233 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
234 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
236 if (strcmp (nname, name) == 0)
237 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
239 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
242 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
245 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
249 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
250 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
254 if (!image->references || !image->references [idx - 1])
255 mono_assembly_load_reference (image, idx - 1);
256 g_assert (image->references [idx - 1]);
258 /* If the assembly did not load, register this as a type load exception */
259 if (image->references [idx - 1] == REFERENCE_MISSING){
260 MonoAssemblyName aname;
263 mono_assembly_get_assemblyref (image, idx - 1, &aname);
264 human_name = mono_stringify_assembly_name (&aname);
265 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
269 /* FIXME this leaks loader errors */
270 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
273 /* Generic case, should be avoided for when a better error is possible. */
274 if (!res && mono_error_ok (error)) {
275 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
276 mono_error_set_from_loader_error (error);
278 char *name = mono_class_name_from_token (image, type_token);
279 char *assembly = mono_assembly_name_from_token (image, type_token);
280 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
283 g_assert (!mono_loader_get_last_error ());
289 mono_image_memdup (MonoImage *image, void *data, guint size)
291 void *res = mono_image_alloc (image, size);
292 memcpy (res, data, size);
296 /* Copy everything mono_metadata_free_array free. */
298 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
301 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
303 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
307 a = g_memdup (a, sizeof (MonoArrayType));
309 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
311 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
316 /* Copy everything mono_metadata_free_method_signature free. */
318 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
322 sig = mono_metadata_signature_dup_full (image, sig);
324 sig->ret = mono_metadata_type_dup (image, sig->ret);
325 for (i = 0; i < sig->param_count; ++i)
326 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
332 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
334 MonoAssembly *ta = klass->image->assembly;
337 name = mono_stringify_assembly_name (&ta->aname);
338 g_string_append_printf (str, ", %s", name);
343 mono_type_name_check_byref (MonoType *type, GString *str)
346 g_string_append_c (str, '&');
350 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
351 MonoTypeNameFormat format)
355 switch (type->type) {
356 case MONO_TYPE_ARRAY: {
357 int i, rank = type->data.array->rank;
358 MonoTypeNameFormat nested_format;
360 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
361 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
363 mono_type_get_name_recurse (
364 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
365 g_string_append_c (str, '[');
367 g_string_append_c (str, '*');
368 for (i = 1; i < rank; i++)
369 g_string_append_c (str, ',');
370 g_string_append_c (str, ']');
372 mono_type_name_check_byref (type, str);
374 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
375 _mono_type_get_assembly_name (type->data.array->eklass, str);
378 case MONO_TYPE_SZARRAY: {
379 MonoTypeNameFormat nested_format;
381 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
382 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
384 mono_type_get_name_recurse (
385 &type->data.klass->byval_arg, str, FALSE, nested_format);
386 g_string_append (str, "[]");
388 mono_type_name_check_byref (type, str);
390 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
391 _mono_type_get_assembly_name (type->data.klass, str);
394 case MONO_TYPE_PTR: {
395 MonoTypeNameFormat nested_format;
397 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
398 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
400 mono_type_get_name_recurse (
401 type->data.type, str, FALSE, nested_format);
402 g_string_append_c (str, '*');
404 mono_type_name_check_byref (type, str);
406 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
407 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
412 if (!mono_generic_param_info (type->data.generic_param))
413 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
415 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
417 mono_type_name_check_byref (type, str);
421 klass = mono_class_from_mono_type (type);
422 if (klass->nested_in) {
423 mono_type_get_name_recurse (
424 &klass->nested_in->byval_arg, str, TRUE, format);
425 if (format == MONO_TYPE_NAME_FORMAT_IL)
426 g_string_append_c (str, '.');
428 g_string_append_c (str, '+');
429 } else if (*klass->name_space) {
430 g_string_append (str, klass->name_space);
431 g_string_append_c (str, '.');
433 if (format == MONO_TYPE_NAME_FORMAT_IL) {
434 char *s = strchr (klass->name, '`');
435 int len = s ? s - klass->name : strlen (klass->name);
437 g_string_append_len (str, klass->name, len);
439 g_string_append (str, klass->name);
442 if (klass->generic_class) {
443 MonoGenericClass *gclass = klass->generic_class;
444 MonoGenericInst *inst = gclass->context.class_inst;
445 MonoTypeNameFormat nested_format;
448 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
449 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
451 if (format == MONO_TYPE_NAME_FORMAT_IL)
452 g_string_append_c (str, '<');
454 g_string_append_c (str, '[');
455 for (i = 0; i < inst->type_argc; i++) {
456 MonoType *t = inst->type_argv [i];
459 g_string_append_c (str, ',');
460 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
461 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
462 g_string_append_c (str, '[');
463 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
464 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
465 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
466 g_string_append_c (str, ']');
468 if (format == MONO_TYPE_NAME_FORMAT_IL)
469 g_string_append_c (str, '>');
471 g_string_append_c (str, ']');
472 } else if (klass->generic_container &&
473 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
474 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
477 if (format == MONO_TYPE_NAME_FORMAT_IL)
478 g_string_append_c (str, '<');
480 g_string_append_c (str, '[');
481 for (i = 0; i < klass->generic_container->type_argc; i++) {
483 g_string_append_c (str, ',');
484 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
486 if (format == MONO_TYPE_NAME_FORMAT_IL)
487 g_string_append_c (str, '>');
489 g_string_append_c (str, ']');
492 mono_type_name_check_byref (type, str);
494 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
495 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
496 _mono_type_get_assembly_name (klass, str);
502 * mono_type_get_name_full:
504 * @format: the format for the return string.
507 * Returns: the string representation in a number of formats:
509 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
510 * returned in the formatrequired by System.Reflection, this is the
511 * inverse of mono_reflection_parse_type ().
513 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
514 * be used by the IL assembler.
516 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
518 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
521 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
525 result = g_string_new ("");
527 mono_type_get_name_recurse (type, result, FALSE, format);
529 return g_string_free (result, FALSE);
533 * mono_type_get_full_name:
536 * Returns: the string representation for type as required by System.Reflection.
537 * The inverse of mono_reflection_parse_type ().
540 mono_type_get_full_name (MonoClass *class)
542 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
546 * mono_type_get_name:
549 * Returns: the string representation for type as it would be represented in IL code.
552 mono_type_get_name (MonoType *type)
554 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
558 * mono_type_get_underlying_type:
561 * Returns: the MonoType for the underlying integer type if @type
562 * is an enum and byref is false, otherwise the type itself.
565 mono_type_get_underlying_type (MonoType *type)
567 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
568 return mono_class_enum_basetype (type->data.klass);
569 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
570 return mono_class_enum_basetype (type->data.generic_class->container_class);
575 * mono_class_is_open_constructed_type:
578 * Returns TRUE if type represents a generics open constructed type.
579 * IOW, not all type parameters required for the instantiation have
580 * been provided or it's a generic type definition.
582 * An open constructed type means it's a non realizable type. Not to
583 * be mixed up with an abstract type - we can't cast or dispatch to
584 * an open type, for example.
587 mono_class_is_open_constructed_type (MonoType *t)
593 case MONO_TYPE_SZARRAY:
594 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
595 case MONO_TYPE_ARRAY:
596 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
598 return mono_class_is_open_constructed_type (t->data.type);
599 case MONO_TYPE_GENERICINST:
600 return t->data.generic_class->context.class_inst->is_open;
601 case MONO_TYPE_CLASS:
602 case MONO_TYPE_VALUETYPE:
603 return t->data.klass->generic_container != NULL;
610 This is a simple function to catch the most common bad instances of generic types.
611 Specially those that might lead to further failures in the runtime.
614 is_valid_generic_argument (MonoType *type)
616 switch (type->type) {
618 //case MONO_TYPE_TYPEDBYREF:
626 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
628 mono_error_init (error);
630 switch (type->type) {
631 case MONO_TYPE_MVAR: {
633 int num = mono_type_get_generic_param_num (type);
634 MonoGenericInst *inst = context->method_inst;
635 if (!inst || !inst->type_argv)
637 if (num >= inst->type_argc) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
640 num, info ? info->name : "", inst->type_argc);
644 if (!is_valid_generic_argument (inst->type_argv [num])) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
647 num, info ? info->name : "", inst->type_argv [num]->type);
651 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
652 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
653 * ->byref and ->attrs from @type are propagated to the returned type.
655 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
656 nt->byref = type->byref;
657 nt->attrs = type->attrs;
660 case MONO_TYPE_VAR: {
662 int num = mono_type_get_generic_param_num (type);
663 MonoGenericInst *inst = context->class_inst;
666 if (num >= inst->type_argc) {
667 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
668 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
669 num, info ? info->name : "", inst->type_argc);
672 if (!is_valid_generic_argument (inst->type_argv [num])) {
673 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
674 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
675 num, info ? info->name : "", inst->type_argv [num]->type);
678 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
679 nt->byref = type->byref;
680 nt->attrs = type->attrs;
683 case MONO_TYPE_SZARRAY: {
684 MonoClass *eclass = type->data.klass;
685 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
686 if (!inflated || !mono_error_ok (error))
688 nt = mono_metadata_type_dup (image, type);
689 nt->data.klass = mono_class_from_mono_type (inflated);
690 mono_metadata_free_type (inflated);
693 case MONO_TYPE_ARRAY: {
694 MonoClass *eclass = type->data.array->eklass;
695 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
696 if (!inflated || !mono_error_ok (error))
698 nt = mono_metadata_type_dup (image, type);
699 nt->data.array->eklass = mono_class_from_mono_type (inflated);
700 mono_metadata_free_type (inflated);
703 case MONO_TYPE_GENERICINST: {
704 MonoGenericClass *gclass = type->data.generic_class;
705 MonoGenericInst *inst;
707 if (!gclass->context.class_inst->is_open)
710 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
711 if (!mono_error_ok (error))
713 if (inst != gclass->context.class_inst)
714 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
716 if (gclass == type->data.generic_class)
719 nt = mono_metadata_type_dup (image, type);
720 nt->data.generic_class = gclass;
723 case MONO_TYPE_CLASS:
724 case MONO_TYPE_VALUETYPE: {
725 MonoClass *klass = type->data.klass;
726 MonoGenericContainer *container = klass->generic_container;
727 MonoGenericInst *inst;
728 MonoGenericClass *gclass = NULL;
734 /* We can't use context->class_inst directly, since it can have more elements */
735 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
736 if (!mono_error_ok (error))
738 if (inst == container->context.class_inst)
741 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
743 nt = mono_metadata_type_dup (image, type);
744 nt->type = MONO_TYPE_GENERICINST;
745 nt->data.generic_class = gclass;
755 mono_generic_class_get_context (MonoGenericClass *gclass)
757 return &gclass->context;
761 mono_class_get_context (MonoClass *class)
763 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
767 * mono_class_get_generic_container:
769 * Return the generic container of KLASS which should be a generic type definition.
771 MonoGenericContainer*
772 mono_class_get_generic_container (MonoClass *klass)
774 g_assert (klass->is_generic);
776 return klass->generic_container;
780 * mono_class_get_generic_class:
782 * Return the MonoGenericClass of KLASS, which should be a generic instance.
785 mono_class_get_generic_class (MonoClass *klass)
787 g_assert (klass->is_inflated);
789 return klass->generic_class;
793 * mono_class_inflate_generic_type_with_mempool:
794 * @mempool: a mempool
796 * @context: a generics context
797 * @error: error context
799 * The same as mono_class_inflate_generic_type, but allocates the MonoType
800 * from mempool if it is non-NULL. If it is NULL, the MonoType is
801 * allocated on the heap and is owned by the caller.
802 * The returned type can potentially be the same as TYPE, so it should not be
803 * modified by the caller, and it should be freed using mono_metadata_free_type ().
806 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
808 MonoType *inflated = NULL;
809 mono_error_init (error);
812 inflated = inflate_generic_type (image, type, context, error);
813 if (!mono_error_ok (error))
817 MonoType *shared = mono_metadata_get_shared_type (type);
822 return mono_metadata_type_dup (image, type);
826 mono_stats.inflated_type_count++;
831 * mono_class_inflate_generic_type:
833 * @context: a generics context
835 * If @type is a generic type and @context is not NULL, instantiate it using the
836 * generics context @context.
838 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
839 * on the heap and is owned by the caller. Returns NULL on error.
841 * @deprecated Please use mono_class_inflate_generic_type_checked instead
844 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
848 result = mono_class_inflate_generic_type_checked (type, context, &error);
850 if (!mono_error_ok (&error)) {
851 mono_error_cleanup (&error);
858 * mono_class_inflate_generic_type:
860 * @context: a generics context
861 * @error: error context to use
863 * If @type is a generic type and @context is not NULL, instantiate it using the
864 * generics context @context.
866 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
867 * on the heap and is owned by the caller.
870 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
872 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
876 * mono_class_inflate_generic_type_no_copy:
878 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
882 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
884 MonoType *inflated = NULL;
886 mono_error_init (error);
888 inflated = inflate_generic_type (image, type, context, error);
889 if (!mono_error_ok (error))
896 mono_stats.inflated_type_count++;
901 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
906 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
907 if (!mono_error_ok (error))
910 res = mono_class_from_mono_type (inflated);
911 mono_metadata_free_type (inflated);
916 * mono_class_inflate_generic_class:
918 * Inflate the class GKLASS with CONTEXT.
921 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
926 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
927 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
934 static MonoGenericContext
935 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
937 MonoGenericInst *class_inst = NULL;
938 MonoGenericInst *method_inst = NULL;
939 MonoGenericContext res = { NULL, NULL };
941 mono_error_init (error);
943 if (context->class_inst) {
944 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
945 if (!mono_error_ok (error))
949 if (context->method_inst) {
950 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
951 if (!mono_error_ok (error))
955 res.class_inst = class_inst;
956 res.method_inst = method_inst;
962 * mono_class_inflate_generic_method:
963 * @method: a generic method
964 * @context: a generics context
966 * Instantiate the generic method @method using the generics context @context.
968 * Returns: the new instantiated method
971 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
973 return mono_class_inflate_generic_method_full (method, NULL, context);
977 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
979 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
983 * mono_class_inflate_generic_method_full:
985 * Instantiate method @method with the generic context @context.
986 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
987 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
990 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
993 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
994 if (!mono_error_ok (&error))
995 /*FIXME do proper error handling - on this case, kill this function. */
996 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1002 * mono_class_inflate_generic_method_full_checked:
1003 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1006 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1009 MonoMethodInflated *iresult, *cached;
1010 MonoMethodSignature *sig;
1011 MonoGenericContext tmp_context;
1012 gboolean is_mb_open = FALSE;
1014 mono_error_init (error);
1016 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1017 while (method->is_inflated) {
1018 MonoGenericContext *method_context = mono_method_get_context (method);
1019 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1021 tmp_context = inflate_generic_context (method_context, context, error);
1022 if (!mono_error_ok (error))
1024 context = &tmp_context;
1026 if (mono_metadata_generic_context_equal (method_context, context))
1029 method = imethod->declaring;
1033 * A method only needs to be inflated if the context has argument for which it is
1036 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1037 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1040 if (!((method->is_generic && context->method_inst) ||
1041 (method->klass->generic_container && context->class_inst)))
1045 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1046 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1047 * This is opposite to the way non-SRE MethodInfos behave.
1049 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1051 * void Example<T> () {
1055 * In Example, the method token must be encoded as: "void Example<!!0>()"
1057 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1058 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1060 * On the other hand, inflating a non-SRE generic method with its own arguments should
1061 * return itself. For example:
1063 * MethodInfo m = ... //m is a generic method definition
1064 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1067 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1068 * what happens with regular methods.
1070 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1071 * everything should behave like a regular type or method.
1074 is_mb_open = method->is_generic &&
1075 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1076 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1078 iresult = g_new0 (MonoMethodInflated, 1);
1079 iresult->context = *context;
1080 iresult->declaring = method;
1081 iresult->method.method.is_mb_open = is_mb_open;
1083 if (!context->method_inst && method->is_generic)
1084 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1086 if (!context->class_inst) {
1087 g_assert (!iresult->declaring->klass->generic_class);
1088 if (iresult->declaring->klass->generic_container)
1089 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1090 else if (iresult->declaring->klass->generic_class)
1091 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1093 /* This can happen with some callers like mono_object_get_virtual_method () */
1094 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1095 iresult->context.class_inst = NULL;
1097 cached = mono_method_inflated_lookup (iresult, FALSE);
1100 return (MonoMethod*)cached;
1103 mono_stats.inflated_method_count++;
1105 inflated_methods_size += sizeof (MonoMethodInflated);
1107 sig = mono_method_signature (method);
1109 char *name = mono_type_get_full_name (method->klass);
1110 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1116 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1118 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1121 result = (MonoMethod *) iresult;
1122 result->is_inflated = TRUE;
1123 result->is_generic = FALSE;
1124 result->sre_method = FALSE;
1125 result->signature = NULL;
1126 result->is_mb_open = is_mb_open;
1128 if (!context->method_inst) {
1129 /* Set the generic_container of the result to the generic_container of method */
1130 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1132 if (generic_container) {
1133 result->is_generic = 1;
1134 mono_method_set_generic_container (result, generic_container);
1138 if (!klass_hint || !klass_hint->generic_class ||
1139 klass_hint->generic_class->container_class != method->klass ||
1140 klass_hint->generic_class->context.class_inst != context->class_inst)
1143 if (method->klass->generic_container)
1144 result->klass = klass_hint;
1146 if (!result->klass) {
1147 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1148 if (!mono_error_ok (error))
1151 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1153 mono_metadata_free_type (inflated);
1157 * FIXME: This should hold, but it doesn't:
1159 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1160 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1161 * g_assert (result->is_generic);
1164 * Fixing this here causes other things to break, hence a very
1165 * ugly hack in mini-trampolines.c - see
1166 * is_generic_method_definition().
1169 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1177 * mono_get_inflated_method:
1179 * Obsolete. We keep it around since it's mentioned in the public API.
1182 mono_get_inflated_method (MonoMethod *method)
1188 * mono_method_get_context_general:
1190 * @uninflated: handle uninflated methods?
1192 * Returns the generic context of a method or NULL if it doesn't have
1193 * one. For an inflated method that's the context stored in the
1194 * method. Otherwise it's in the method's generic container or in the
1195 * generic container of the method's class.
1198 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1200 if (method->is_inflated) {
1201 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1202 return &imethod->context;
1206 if (method->is_generic)
1207 return &(mono_method_get_generic_container (method)->context);
1208 if (method->klass->generic_container)
1209 return &method->klass->generic_container->context;
1214 * mono_method_get_context:
1217 * Returns the generic context for method if it's inflated, otherwise
1221 mono_method_get_context (MonoMethod *method)
1223 return mono_method_get_context_general (method, FALSE);
1227 * mono_method_get_generic_container:
1229 * Returns the generic container of METHOD, which should be a generic method definition.
1230 * Returns NULL if METHOD is not a generic method definition.
1231 * LOCKING: Acquires the loader lock.
1233 MonoGenericContainer*
1234 mono_method_get_generic_container (MonoMethod *method)
1236 MonoGenericContainer *container;
1238 if (!method->is_generic)
1241 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1242 g_assert (container);
1248 * mono_method_set_generic_container:
1250 * Sets the generic container of METHOD to CONTAINER.
1251 * LOCKING: Acquires the image lock.
1254 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1256 g_assert (method->is_generic);
1258 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1262 * mono_class_find_enum_basetype:
1263 * @class: The enum class
1265 * Determine the basetype of an enum by iterating through its fields. We do this
1266 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1269 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1271 MonoGenericContainer *container = NULL;
1272 MonoImage *m = class->image;
1273 const int top = class->field.count;
1276 g_assert (class->enumtype);
1278 mono_error_init (error);
1280 if (class->generic_container)
1281 container = class->generic_container;
1282 else if (class->generic_class) {
1283 MonoClass *gklass = class->generic_class->container_class;
1285 container = gklass->generic_container;
1286 g_assert (container);
1290 * Fetch all the field information.
1292 for (i = 0; i < top; i++){
1294 guint32 cols [MONO_FIELD_SIZE];
1295 int idx = class->field.first + i;
1298 /* class->field.first and idx points into the fieldptr table */
1299 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1301 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1304 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1305 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1309 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1310 mono_metadata_decode_value (sig, &sig);
1311 /* FIELD signature == 0x06 */
1313 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1317 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1319 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1320 mono_error_set_from_loader_error (error);
1322 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1325 if (class->generic_class) {
1326 //FIXME do we leak here?
1327 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1328 if (!mono_error_ok (error))
1330 ftype->attrs = cols [MONO_FIELD_FLAGS];
1335 mono_error_set_type_load_class (error, class, "Could not find base type");
1338 g_assert (!mono_loader_get_last_error ());
1343 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1346 mono_type_has_exceptions (MonoType *type)
1348 switch (type->type) {
1349 case MONO_TYPE_CLASS:
1350 case MONO_TYPE_VALUETYPE:
1351 case MONO_TYPE_SZARRAY:
1352 return type->data.klass->exception_type;
1353 case MONO_TYPE_ARRAY:
1354 return type->data.array->eklass->exception_type;
1355 case MONO_TYPE_GENERICINST:
1356 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1365 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1369 mono_class_alloc (MonoClass *class, int size)
1371 if (class->generic_class)
1372 return mono_image_set_alloc (class->generic_class->owner, size);
1374 return mono_image_alloc (class->image, size);
1378 mono_class_alloc0 (MonoClass *class, int size)
1382 res = mono_class_alloc (class, size);
1383 memset (res, 0, size);
1387 #define mono_class_new0(class,struct_type, n_structs) \
1388 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1391 * mono_class_setup_basic_field_info:
1392 * @class: The class to initialize
1394 * Initializes the class->fields.
1395 * LOCKING: Assumes the loader lock is held.
1398 mono_class_setup_basic_field_info (MonoClass *class)
1400 MonoClassField *field;
1408 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1409 image = class->image;
1410 top = class->field.count;
1412 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1414 * This happens when a generic instance of an unfinished generic typebuilder
1415 * is used as an element type for creating an array type. We can't initialize
1416 * the fields of this class using the fields of gklass, since gklass is not
1417 * finished yet, fields could be added to it later.
1423 mono_class_setup_basic_field_info (gtd);
1425 top = gtd->field.count;
1426 class->field.first = gtd->field.first;
1427 class->field.count = gtd->field.count;
1430 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1433 * Fetch all the field information.
1435 for (i = 0; i < top; i++){
1436 field = &class->fields [i];
1437 field->parent = class;
1440 field->name = mono_field_get_name (>d->fields [i]);
1442 int idx = class->field.first + i;
1443 /* class->field.first and idx points into the fieldptr table */
1444 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1445 /* The name is needed for fieldrefs */
1446 field->name = mono_metadata_string_heap (image, name_idx);
1452 * mono_class_setup_fields:
1453 * @class: The class to initialize
1455 * Initializes the class->fields.
1456 * LOCKING: Assumes the loader lock is held.
1459 mono_class_setup_fields (MonoClass *class)
1462 MonoImage *m = class->image;
1464 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1465 int i, blittable = TRUE;
1466 guint32 real_size = 0;
1467 guint32 packing_size = 0;
1468 gboolean explicit_size;
1469 MonoClassField *field;
1470 MonoGenericContainer *container = NULL;
1471 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1474 * FIXME: We have a race condition here. It's possible that this function returns
1475 * to its caller with `instance_size` set to `0` instead of the actual size. This
1476 * is not a problem when the function is called recursively on the same class,
1477 * because the size will be initialized by the outer invocation. What follows is a
1478 * description of how it can occur in other cases, too. There it is a problem,
1479 * because it can lead to the GC being asked to allocate an object of size `0`,
1480 * which SGen chokes on. The race condition is triggered infrequently by
1481 * `tests/sgen-suspend.cs`.
1483 * This function is called for a class whenever one of its subclasses is inited.
1484 * For example, it's called for every subclass of Object. What it does is this:
1486 * if (class->setup_fields_called)
1489 * class->instance_size = 0;
1491 * class->setup_fields_called = 1;
1492 * ... critical point
1493 * class->instance_size = actual_instance_size;
1495 * The last two steps are sometimes reversed, but that only changes the way in which
1496 * the race condition works.
1498 * Assume thread A goes through this function and makes it to the critical point.
1499 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1500 * immediately, but `instance_size` is incorrect.
1502 * The other case looks like this:
1504 * if (class->setup_fields_called)
1506 * ... critical point X
1507 * class->instance_size = 0;
1508 * ... critical point Y
1509 * class->instance_size = actual_instance_size;
1511 * class->setup_fields_called = 1;
1513 * Assume thread A goes through the function and makes it to critical point X. Now
1514 * thread B runs through the whole of the function, returning, assuming
1515 * `instance_size` is set. At that point thread A gets to run and makes it to
1516 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1519 if (class->setup_fields_called)
1522 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1524 * This happens when a generic instance of an unfinished generic typebuilder
1525 * is used as an element type for creating an array type. We can't initialize
1526 * the fields of this class using the fields of gklass, since gklass is not
1527 * finished yet, fields could be added to it later.
1532 mono_class_setup_basic_field_info (class);
1533 top = class->field.count;
1536 mono_class_setup_fields (gtd);
1537 if (gtd->exception_type) {
1538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1543 class->instance_size = 0;
1545 class->sizes.class_size = 0;
1547 if (class->parent) {
1548 /* For generic instances, class->parent might not have been initialized */
1549 mono_class_init (class->parent);
1550 if (!class->parent->size_inited) {
1551 mono_class_setup_fields (class->parent);
1552 if (class->parent->exception_type) {
1553 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1557 class->instance_size += class->parent->instance_size;
1558 class->min_align = class->parent->min_align;
1559 /* we use |= since it may have been set already */
1560 class->has_references |= class->parent->has_references;
1561 blittable = class->parent->blittable;
1563 class->instance_size = sizeof (MonoObject);
1564 class->min_align = 1;
1567 /* We can't really enable 16 bytes alignment until the GC supports it.
1568 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1569 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1570 Bug #506144 is an example of this issue.
1572 if (class->simd_type)
1573 class->min_align = 16;
1575 /* Get the real size */
1576 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1578 if (explicit_size) {
1579 if ((packing_size & 0xffffff00) != 0) {
1580 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1581 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1584 class->packing_size = packing_size;
1585 real_size += class->instance_size;
1589 if (explicit_size && real_size) {
1590 class->instance_size = MAX (real_size, class->instance_size);
1592 class->blittable = blittable;
1593 mono_memory_barrier ();
1594 class->size_inited = 1;
1595 class->fields_inited = 1;
1596 class->setup_fields_called = 1;
1600 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1603 /* Prevent infinite loops if the class references itself */
1604 class->setup_fields_called = 1;
1606 if (class->generic_container) {
1607 container = class->generic_container;
1609 container = gtd->generic_container;
1610 g_assert (container);
1614 * Fetch all the field information.
1616 for (i = 0; i < top; i++){
1617 int idx = class->field.first + i;
1618 field = &class->fields [i];
1620 field->parent = class;
1623 mono_field_resolve_type (field, &error);
1624 if (!mono_error_ok (&error)) {
1625 /*mono_field_resolve_type already failed class*/
1626 mono_error_cleanup (&error);
1630 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1631 g_assert (field->type);
1634 if (mono_field_is_deleted (field))
1637 MonoClassField *gfield = >d->fields [i];
1638 field->offset = gfield->offset;
1640 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1642 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1643 field->offset = offset;
1645 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1646 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1649 if (field->offset < -1) { /*-1 is used to encode special static fields */
1650 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1653 if (class->generic_container) {
1654 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1660 /* Only do these checks if we still think this type is blittable */
1661 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1665 MonoClass *field_class = mono_class_from_mono_type (field->type);
1667 mono_class_setup_fields (field_class);
1668 if (field_class->exception_type) {
1669 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1673 if (!field_class || !field_class->blittable)
1678 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1679 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1680 blittable = class->element_class->blittable;
1683 if (mono_type_has_exceptions (field->type)) {
1684 char *class_name = mono_type_get_full_name (class);
1685 char *type_name = mono_type_full_name (field->type);
1687 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1689 g_free (class_name);
1693 /* The def_value of fields is compute lazily during vtable creation */
1696 if (class == mono_defaults.string_class)
1699 class->blittable = blittable;
1701 if (class->enumtype && !mono_class_enum_basetype (class)) {
1702 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1705 if (explicit_size && real_size) {
1706 class->instance_size = MAX (real_size, class->instance_size);
1709 if (class->exception_type)
1711 mono_class_layout_fields (class);
1713 /*valuetypes can't be neither bigger than 1Mb or empty. */
1714 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1715 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1717 mono_memory_barrier ();
1718 class->fields_inited = 1;
1722 * mono_class_setup_fields_locking:
1723 * @class: The class to initialize
1725 * Initializes the class->fields array of fields.
1726 * Aquires the loader lock.
1729 mono_class_setup_fields_locking (MonoClass *class)
1731 /* This can be checked without locks */
1732 if (class->fields_inited)
1734 mono_loader_lock ();
1735 mono_class_setup_fields (class);
1736 mono_loader_unlock ();
1740 * mono_class_has_references:
1742 * Returns whenever @klass->has_references is set, initializing it if needed.
1743 * Aquires the loader lock.
1746 mono_class_has_references (MonoClass *klass)
1748 if (klass->init_pending) {
1749 /* Be conservative */
1752 mono_class_init (klass);
1754 return klass->has_references;
1759 * mono_type_get_basic_type_from_generic:
1762 * Returns a closed type corresponding to the possibly open type
1766 mono_type_get_basic_type_from_generic (MonoType *type)
1768 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1769 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1770 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint == MONO_TYPE_OBJECT))
1771 return &mono_defaults.object_class->byval_arg;
1776 * mono_class_layout_fields:
1779 * Compute the placement of fields inside an object or struct, according to
1780 * the layout rules and set the following fields in @class:
1781 * - has_references (if the class contains instance references firled or structs that contain references)
1782 * - has_static_refs (same, but for static fields)
1783 * - instance_size (size of the object in memory)
1784 * - class_size (size needed for the static fields)
1785 * - size_inited (flag set when the instance_size is set)
1787 * LOCKING: this is supposed to be called with the loader lock held.
1790 mono_class_layout_fields (MonoClass *class)
1793 const int top = class->field.count;
1794 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1795 guint32 pass, passes, real_size;
1796 gboolean gc_aware_layout = FALSE;
1797 gboolean has_static_fields = FALSE;
1798 MonoClassField *field;
1801 * When we do generic sharing we need to have layout
1802 * information for open generic classes (either with a generic
1803 * context containing type variables or with a generic
1804 * container), so we don't return in that case anymore.
1808 * Enable GC aware auto layout: in this mode, reference
1809 * fields are grouped together inside objects, increasing collector
1811 * Requires that all classes whose layout is known to native code be annotated
1812 * with [StructLayout (LayoutKind.Sequential)]
1813 * Value types have gc_aware_layout disabled by default, as per
1814 * what the default is for other runtimes.
1816 /* corlib is missing [StructLayout] directives in many places */
1817 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1818 if (!class->valuetype)
1819 gc_aware_layout = TRUE;
1822 /* Compute klass->has_references */
1824 * Process non-static fields first, since static fields might recursively
1825 * refer to the class itself.
1827 for (i = 0; i < top; i++) {
1830 field = &class->fields [i];
1832 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1833 ftype = mono_type_get_underlying_type (field->type);
1834 ftype = mono_type_get_basic_type_from_generic (ftype);
1835 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1836 class->has_references = TRUE;
1840 for (i = 0; i < top; i++) {
1843 field = &class->fields [i];
1845 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1846 ftype = mono_type_get_underlying_type (field->type);
1847 ftype = mono_type_get_basic_type_from_generic (ftype);
1848 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1849 class->has_static_refs = TRUE;
1853 for (i = 0; i < top; i++) {
1856 field = &class->fields [i];
1858 ftype = mono_type_get_underlying_type (field->type);
1859 ftype = mono_type_get_basic_type_from_generic (ftype);
1860 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1861 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1862 class->has_static_refs = TRUE;
1864 class->has_references = TRUE;
1869 * Compute field layout and total size (not considering static fields)
1873 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1874 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1876 if (gc_aware_layout)
1881 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1884 if (class->parent) {
1885 mono_class_setup_fields (class->parent);
1886 if (class->parent->exception_type) {
1887 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1890 real_size = class->parent->instance_size;
1892 real_size = sizeof (MonoObject);
1895 for (pass = 0; pass < passes; ++pass) {
1896 for (i = 0; i < top; i++){
1901 field = &class->fields [i];
1903 if (mono_field_is_deleted (field))
1905 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1908 ftype = mono_type_get_underlying_type (field->type);
1909 ftype = mono_type_get_basic_type_from_generic (ftype);
1910 if (gc_aware_layout) {
1911 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1920 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1921 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1922 /* This field is a hack inserted by MCS to empty structures */
1926 size = mono_type_size (field->type, &align);
1928 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1929 align = class->packing_size ? MIN (class->packing_size, align): align;
1930 /* if the field has managed references, we need to force-align it
1933 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1934 align = MAX (align, sizeof (gpointer));
1936 class->min_align = MAX (align, class->min_align);
1937 field->offset = real_size;
1939 field->offset += align - 1;
1940 field->offset &= ~(align - 1);
1942 /*TypeBuilders produce all sort of weird things*/
1943 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1944 real_size = field->offset + size;
1947 class->instance_size = MAX (real_size, class->instance_size);
1949 if (class->instance_size & (class->min_align - 1)) {
1950 class->instance_size += class->min_align - 1;
1951 class->instance_size &= ~(class->min_align - 1);
1955 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1959 for (i = 0; i < top; i++) {
1964 field = &class->fields [i];
1967 * There must be info about all the fields in a type if it
1968 * uses explicit layout.
1970 if (mono_field_is_deleted (field))
1972 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1975 size = mono_type_size (field->type, &align);
1976 align = class->packing_size ? MIN (class->packing_size, align): align;
1977 class->min_align = MAX (align, class->min_align);
1980 * When we get here, field->offset is already set by the
1981 * loader (for either runtime fields or fields loaded from metadata).
1982 * The offset is from the start of the object: this works for both
1983 * classes and valuetypes.
1985 field->offset += sizeof (MonoObject);
1986 ftype = mono_type_get_underlying_type (field->type);
1987 ftype = mono_type_get_basic_type_from_generic (ftype);
1988 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1989 if (field->offset % sizeof (gpointer)) {
1990 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1997 real_size = MAX (real_size, size + field->offset);
2000 if (class->has_references) {
2001 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2003 /* Check for overlapping reference and non-reference fields */
2004 for (i = 0; i < top; i++) {
2007 field = &class->fields [i];
2009 if (mono_field_is_deleted (field))
2011 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2013 ftype = mono_type_get_underlying_type (field->type);
2014 if (MONO_TYPE_IS_REFERENCE (ftype))
2015 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2017 for (i = 0; i < top; i++) {
2018 field = &class->fields [i];
2020 if (mono_field_is_deleted (field))
2022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2025 // FIXME: Too much code does this
2027 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2028 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", class->name, field->offset);
2029 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2033 g_free (ref_bitmap);
2036 class->instance_size = MAX (real_size, class->instance_size);
2037 if (class->instance_size & (class->min_align - 1)) {
2038 class->instance_size += class->min_align - 1;
2039 class->instance_size &= ~(class->min_align - 1);
2045 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2047 * For small structs, set min_align to at least the struct size to improve
2048 * performance, and since the JIT memset/memcpy code assumes this and generates
2049 * unaligned accesses otherwise. See #78990 for a testcase.
2051 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2052 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2055 mono_memory_barrier ();
2056 class->size_inited = 1;
2059 * Compute static field layout and size
2061 for (i = 0; i < top; i++){
2065 field = &class->fields [i];
2067 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2069 if (mono_field_is_deleted (field))
2072 if (mono_type_has_exceptions (field->type)) {
2073 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2077 has_static_fields = TRUE;
2079 size = mono_type_size (field->type, &align);
2080 field->offset = class->sizes.class_size;
2081 /*align is always non-zero here*/
2082 field->offset += align - 1;
2083 field->offset &= ~(align - 1);
2084 class->sizes.class_size = field->offset + size;
2087 if (has_static_fields && class->sizes.class_size == 0)
2088 /* Simplify code which depends on class_size != 0 if the class has static fields */
2089 class->sizes.class_size = 8;
2093 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2097 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2098 method->klass = class;
2099 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2100 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2101 method->signature = sig;
2102 method->name = name;
2105 if (name [0] == '.') {
2106 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2108 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2114 * mono_class_setup_methods:
2117 * Initializes the 'methods' array in CLASS.
2118 * Calling this method should be avoided if possible since it allocates a lot
2119 * of long-living MonoMethod structures.
2120 * Methods belonging to an interface are assigned a sequential slot starting
2123 * On failure this function sets class->exception_type
2126 mono_class_setup_methods (MonoClass *class)
2129 MonoMethod **methods;
2134 if (class->generic_class) {
2136 MonoClass *gklass = class->generic_class->container_class;
2138 mono_class_init (gklass);
2139 if (!gklass->exception_type)
2140 mono_class_setup_methods (gklass);
2141 if (gklass->exception_type) {
2142 /* FIXME make exception_data less opaque so it's possible to dup it here */
2143 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2147 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2148 count = gklass->method.count;
2149 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2151 for (i = 0; i < count; i++) {
2152 methods [i] = mono_class_inflate_generic_method_full_checked (
2153 gklass->methods [i], class, mono_class_get_context (class), &error);
2154 if (!mono_error_ok (&error)) {
2155 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2156 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)));
2159 mono_error_cleanup (&error);
2163 } else if (class->rank) {
2165 MonoMethod *amethod;
2166 MonoMethodSignature *sig;
2167 int count_generic = 0, first_generic = 0;
2169 gboolean jagged_ctor = FALSE;
2171 count = 3 + (class->rank > 1? 2: 1);
2173 mono_class_setup_interfaces (class, &error);
2174 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2176 if (class->rank == 1 && class->element_class->rank) {
2178 class->method.count ++;
2181 if (class->interface_count) {
2182 count_generic = generic_array_methods (class);
2183 first_generic = count;
2184 count += class->interface_count * count_generic;
2187 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2189 sig = mono_metadata_signature_alloc (class->image, class->rank);
2190 sig->ret = &mono_defaults.void_class->byval_arg;
2191 sig->pinvoke = TRUE;
2192 sig->hasthis = TRUE;
2193 for (i = 0; i < class->rank; ++i)
2194 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2196 amethod = create_array_method (class, ".ctor", sig);
2197 methods [method_num++] = amethod;
2198 if (class->rank > 1) {
2199 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2200 sig->ret = &mono_defaults.void_class->byval_arg;
2201 sig->pinvoke = TRUE;
2202 sig->hasthis = TRUE;
2203 for (i = 0; i < class->rank * 2; ++i)
2204 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2206 amethod = create_array_method (class, ".ctor", sig);
2207 methods [method_num++] = amethod;
2211 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2212 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2213 sig->ret = &mono_defaults.void_class->byval_arg;
2214 sig->pinvoke = TRUE;
2215 sig->hasthis = TRUE;
2216 for (i = 0; i < class->rank + 1; ++i)
2217 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2218 amethod = create_array_method (class, ".ctor", sig);
2219 methods [method_num++] = amethod;
2222 /* element Get (idx11, [idx2, ...]) */
2223 sig = mono_metadata_signature_alloc (class->image, class->rank);
2224 sig->ret = &class->element_class->byval_arg;
2225 sig->pinvoke = TRUE;
2226 sig->hasthis = TRUE;
2227 for (i = 0; i < class->rank; ++i)
2228 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2229 amethod = create_array_method (class, "Get", sig);
2230 methods [method_num++] = amethod;
2231 /* element& Address (idx11, [idx2, ...]) */
2232 sig = mono_metadata_signature_alloc (class->image, class->rank);
2233 sig->ret = &class->element_class->this_arg;
2234 sig->pinvoke = TRUE;
2235 sig->hasthis = TRUE;
2236 for (i = 0; i < class->rank; ++i)
2237 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2238 amethod = create_array_method (class, "Address", sig);
2239 methods [method_num++] = amethod;
2240 /* void Set (idx11, [idx2, ...], element) */
2241 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2242 sig->ret = &mono_defaults.void_class->byval_arg;
2243 sig->pinvoke = TRUE;
2244 sig->hasthis = TRUE;
2245 for (i = 0; i < class->rank; ++i)
2246 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2247 sig->params [i] = &class->element_class->byval_arg;
2248 amethod = create_array_method (class, "Set", sig);
2249 methods [method_num++] = amethod;
2251 for (i = 0; i < class->interface_count; i++)
2252 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2256 count = class->method.count;
2257 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2258 for (i = 0; i < count; ++i) {
2259 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2260 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2262 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)));
2263 mono_error_cleanup (&error);
2268 if (MONO_CLASS_IS_INTERFACE (class)) {
2270 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2271 for (i = 0; i < count; ++i) {
2272 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2273 methods [i]->slot = slot++;
2277 mono_image_lock (class->image);
2279 if (!class->methods) {
2280 class->method.count = count;
2282 /* Needed because of the double-checking locking pattern */
2283 mono_memory_barrier ();
2285 class->methods = methods;
2288 mono_image_unlock (class->image);
2292 * mono_class_get_method_by_index:
2294 * Returns class->methods [index], initializing class->methods if neccesary.
2296 * LOCKING: Acquires the loader lock.
2299 mono_class_get_method_by_index (MonoClass *class, int index)
2302 /* Avoid calling setup_methods () if possible */
2303 if (class->generic_class && !class->methods) {
2304 MonoClass *gklass = class->generic_class->container_class;
2307 m = mono_class_inflate_generic_method_full_checked (
2308 gklass->methods [index], class, mono_class_get_context (class), &error);
2309 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2311 * If setup_methods () is called later for this class, no duplicates are created,
2312 * since inflate_generic_method guarantees that only one instance of a method
2313 * is created for each context.
2316 mono_class_setup_methods (class);
2317 g_assert (m == class->methods [index]);
2321 mono_class_setup_methods (class);
2322 if (class->exception_type) /*FIXME do proper error handling*/
2324 g_assert (index >= 0 && index < class->method.count);
2325 return class->methods [index];
2330 * mono_class_get_inflated_method:
2332 * Given an inflated class CLASS and a method METHOD which should be a method of
2333 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2336 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2338 MonoClass *gklass = class->generic_class->container_class;
2341 g_assert (method->klass == gklass);
2343 mono_class_setup_methods (gklass);
2344 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2346 for (i = 0; i < gklass->method.count; ++i) {
2347 if (gklass->methods [i] == method) {
2348 if (class->methods) {
2349 return class->methods [i];
2352 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2353 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2363 * mono_class_get_vtable_entry:
2365 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2366 * LOCKING: Acquires the loader lock.
2369 mono_class_get_vtable_entry (MonoClass *class, int offset)
2373 if (class->rank == 1) {
2375 * szarrays do not overwrite any methods of Array, so we can avoid
2376 * initializing their vtables in some cases.
2378 mono_class_setup_vtable (class->parent);
2379 if (offset < class->parent->vtable_size)
2380 return class->parent->vtable [offset];
2383 if (class->generic_class) {
2385 MonoClass *gklass = class->generic_class->container_class;
2386 mono_class_setup_vtable (gklass);
2387 m = gklass->vtable [offset];
2389 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2390 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2392 mono_class_setup_vtable (class);
2393 if (class->exception_type)
2395 m = class->vtable [offset];
2402 * mono_class_get_vtable_size:
2404 * Return the vtable size for KLASS.
2407 mono_class_get_vtable_size (MonoClass *klass)
2409 mono_class_setup_vtable (klass);
2411 return klass->vtable_size;
2415 * mono_class_setup_properties:
2417 * Initialize class->ext.property and class->ext.properties.
2419 * This method can fail the class.
2422 mono_class_setup_properties (MonoClass *class)
2424 guint startm, endm, i, j;
2425 guint32 cols [MONO_PROPERTY_SIZE];
2426 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2427 MonoProperty *properties;
2431 if (class->ext && class->ext->properties)
2434 if (class->generic_class) {
2435 MonoClass *gklass = class->generic_class->container_class;
2437 mono_class_init (gklass);
2438 mono_class_setup_properties (gklass);
2439 if (gklass->exception_type) {
2440 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2444 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2446 for (i = 0; i < gklass->ext->property.count; i++) {
2448 MonoProperty *prop = &properties [i];
2450 *prop = gklass->ext->properties [i];
2453 prop->get = mono_class_inflate_generic_method_full_checked (
2454 prop->get, class, mono_class_get_context (class), &error);
2456 prop->set = mono_class_inflate_generic_method_full_checked (
2457 prop->set, class, mono_class_get_context (class), &error);
2459 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2460 prop->parent = class;
2463 first = gklass->ext->property.first;
2464 count = gklass->ext->property.count;
2466 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2467 count = last - first;
2470 mono_class_setup_methods (class);
2471 if (class->exception_type)
2475 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2476 for (i = first; i < last; ++i) {
2477 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2478 properties [i - first].parent = class;
2479 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2480 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2482 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2483 for (j = startm; j < endm; ++j) {
2486 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2488 if (class->image->uncompressed_metadata) {
2490 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2491 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2492 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2494 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2497 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2498 case METHOD_SEMANTIC_SETTER:
2499 properties [i - first].set = method;
2501 case METHOD_SEMANTIC_GETTER:
2502 properties [i - first].get = method;
2511 mono_class_alloc_ext (class);
2513 mono_image_lock (class->image);
2515 if (class->ext->properties) {
2516 /* We leak 'properties' which was allocated from the image mempool */
2517 mono_image_unlock (class->image);
2521 class->ext->property.first = first;
2522 class->ext->property.count = count;
2524 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2525 mono_memory_barrier ();
2527 /* Leave this assignment as the last op in the function */
2528 class->ext->properties = properties;
2530 mono_image_unlock (class->image);
2534 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2536 MonoMethod **om, **retval;
2539 for (om = methods, count = 0; *om; ++om, ++count)
2542 retval = g_new0 (MonoMethod*, count + 1);
2544 for (om = methods, count = 0; *om; ++om, ++count) {
2546 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2547 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2553 /*This method can fail the class.*/
2555 mono_class_setup_events (MonoClass *class)
2558 guint startm, endm, i, j;
2559 guint32 cols [MONO_EVENT_SIZE];
2560 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2564 if (class->ext && class->ext->events)
2567 if (class->generic_class) {
2568 MonoClass *gklass = class->generic_class->container_class;
2569 MonoGenericContext *context = NULL;
2571 mono_class_setup_events (gklass);
2572 if (gklass->exception_type) {
2573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2577 first = gklass->ext->event.first;
2578 count = gklass->ext->event.count;
2580 events = mono_class_new0 (class, MonoEvent, count);
2583 context = mono_class_get_context (class);
2585 for (i = 0; i < count; i++) {
2587 MonoEvent *event = &events [i];
2588 MonoEvent *gevent = &gklass->ext->events [i];
2590 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2592 event->parent = class;
2593 event->name = gevent->name;
2594 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2595 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2596 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2597 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2598 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2599 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2601 #ifndef MONO_SMALL_CONFIG
2602 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2604 event->attrs = gevent->attrs;
2607 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2608 count = last - first;
2611 mono_class_setup_methods (class);
2612 if (class->exception_type) {
2613 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2618 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2619 for (i = first; i < last; ++i) {
2620 MonoEvent *event = &events [i - first];
2622 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2623 event->parent = class;
2624 event->attrs = cols [MONO_EVENT_FLAGS];
2625 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2627 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2628 for (j = startm; j < endm; ++j) {
2631 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2633 if (class->image->uncompressed_metadata) {
2635 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2636 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2637 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2639 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2642 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2643 case METHOD_SEMANTIC_ADD_ON:
2644 event->add = method;
2646 case METHOD_SEMANTIC_REMOVE_ON:
2647 event->remove = method;
2649 case METHOD_SEMANTIC_FIRE:
2650 event->raise = method;
2652 case METHOD_SEMANTIC_OTHER: {
2653 #ifndef MONO_SMALL_CONFIG
2656 if (event->other == NULL) {
2657 event->other = g_new0 (MonoMethod*, 2);
2659 while (event->other [n])
2661 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2663 event->other [n] = method;
2664 /* NULL terminated */
2665 event->other [n + 1] = NULL;
2676 mono_class_alloc_ext (class);
2678 mono_image_lock (class->image);
2680 if (class->ext->events) {
2681 mono_image_unlock (class->image);
2685 class->ext->event.first = first;
2686 class->ext->event.count = count;
2688 /* Flush any pending writes as we do double checked locking on class->ext.events */
2689 mono_memory_barrier ();
2691 /* Leave this assignment as the last op in the function */
2692 class->ext->events = events;
2694 mono_image_unlock (class->image);
2698 * Global pool of interface IDs, represented as a bitset.
2699 * LOCKING: Protected by the classes lock.
2701 static MonoBitSet *global_interface_bitset = NULL;
2704 * mono_unload_interface_ids:
2705 * @bitset: bit set of interface IDs
2707 * When an image is unloaded, the interface IDs associated with
2708 * the image are put back in the global pool of IDs so the numbers
2712 mono_unload_interface_ids (MonoBitSet *bitset)
2715 mono_bitset_sub (global_interface_bitset, bitset);
2720 mono_unload_interface_id (MonoClass *class)
2722 if (global_interface_bitset && class->interface_id) {
2724 mono_bitset_clear (global_interface_bitset, class->interface_id);
2730 * mono_get_unique_iid:
2733 * Assign a unique integer ID to the interface represented by @class.
2734 * The ID will positive and as small as possible.
2735 * LOCKING: Acquires the classes lock.
2736 * Returns: the new ID.
2739 mono_get_unique_iid (MonoClass *class)
2743 g_assert (MONO_CLASS_IS_INTERFACE (class));
2747 if (!global_interface_bitset) {
2748 global_interface_bitset = mono_bitset_new (128, 0);
2751 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2753 int old_size = mono_bitset_size (global_interface_bitset);
2754 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2755 mono_bitset_free (global_interface_bitset);
2756 global_interface_bitset = new_set;
2759 mono_bitset_set (global_interface_bitset, iid);
2760 /* set the bit also in the per-image set */
2761 if (!class->generic_class) {
2762 if (class->image->interface_bitset) {
2763 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2764 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2765 mono_bitset_free (class->image->interface_bitset);
2766 class->image->interface_bitset = new_set;
2769 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2771 mono_bitset_set (class->image->interface_bitset, iid);
2776 #ifndef MONO_SMALL_CONFIG
2777 if (mono_print_vtable) {
2779 char *type_name = mono_type_full_name (&class->byval_arg);
2780 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2781 generic_id = class->generic_class->context.class_inst->id;
2782 g_assert (generic_id != 0);
2786 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2791 g_assert (iid <= 65535);
2796 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2801 mono_class_setup_interfaces (klass, error);
2802 if (!mono_error_ok (error))
2805 for (i = 0; i < klass->interface_count; i++) {
2806 ic = klass->interfaces [i];
2809 *res = g_ptr_array_new ();
2810 g_ptr_array_add (*res, ic);
2811 mono_class_init (ic);
2812 if (ic->exception_type) {
2813 mono_error_set_type_load_class (error, ic, "Error Loading class");
2817 collect_implemented_interfaces_aux (ic, res, error);
2818 if (!mono_error_ok (error))
2824 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2826 GPtrArray *res = NULL;
2828 collect_implemented_interfaces_aux (klass, &res, error);
2829 if (!mono_error_ok (error)) {
2831 g_ptr_array_free (res, TRUE);
2838 compare_interface_ids (const void *p_key, const void *p_element) {
2839 const MonoClass *key = p_key;
2840 const MonoClass *element = *(MonoClass**) p_element;
2842 return (key->interface_id - element->interface_id);
2845 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2847 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2848 MonoClass **result = mono_binary_search (
2850 klass->interfaces_packed,
2851 klass->interface_offsets_count,
2852 sizeof (MonoClass *),
2853 compare_interface_ids);
2855 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2862 * mono_class_interface_offset_with_variance:
2864 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2865 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2867 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2869 * FIXME figure out MS disambiguation rules and fix this function.
2872 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2873 int i = mono_class_interface_offset (klass, itf);
2874 *non_exact_match = FALSE;
2878 if (!mono_class_has_variant_generic_params (itf))
2881 for (i = 0; i < klass->interface_offsets_count; i++) {
2882 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2883 *non_exact_match = TRUE;
2884 return klass->interface_offsets_packed [i];
2892 print_implemented_interfaces (MonoClass *klass) {
2895 GPtrArray *ifaces = NULL;
2897 int ancestor_level = 0;
2899 name = mono_type_get_full_name (klass);
2900 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2903 for (i = 0; i < klass->interface_offsets_count; i++)
2904 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2905 klass->interfaces_packed [i]->interface_id,
2906 klass->interface_offsets_packed [i],
2907 klass->interfaces_packed [i]->method.count,
2908 klass->interfaces_packed [i]->name_space,
2909 klass->interfaces_packed [i]->name );
2910 printf ("Interface flags: ");
2911 for (i = 0; i <= klass->max_interface_id; i++)
2912 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2913 printf ("(%d,T)", i);
2915 printf ("(%d,F)", i);
2917 printf ("Dump interface flags:");
2918 #ifdef COMPRESSED_INTERFACE_BITMAP
2920 const uint8_t* p = klass->interface_bitmap;
2921 i = klass->max_interface_id;
2923 printf (" %d x 00 %02X", p [0], p [1]);
2929 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2930 printf (" %02X", klass->interface_bitmap [i]);
2933 while (klass != NULL) {
2934 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2935 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2936 if (!mono_error_ok (&error)) {
2937 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2938 mono_error_cleanup (&error);
2939 } else if (ifaces) {
2940 for (i = 0; i < ifaces->len; i++) {
2941 MonoClass *ic = g_ptr_array_index (ifaces, i);
2942 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2943 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2945 mono_class_interface_offset (klass, ic),
2950 g_ptr_array_free (ifaces, TRUE);
2953 klass = klass->parent;
2958 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2961 args [0] = &arg0->byval_arg;
2963 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2967 array_class_get_if_rank (MonoClass *class, guint rank)
2969 return rank ? mono_array_class_get (class, rank) : class;
2973 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2975 valuetype_types [0] = eclass;
2976 if (eclass == mono_defaults.int16_class)
2977 valuetype_types [1] = mono_defaults.uint16_class;
2978 else if (eclass == mono_defaults.uint16_class)
2979 valuetype_types [1] = mono_defaults.int16_class;
2980 else if (eclass == mono_defaults.int32_class)
2981 valuetype_types [1] = mono_defaults.uint32_class;
2982 else if (eclass == mono_defaults.uint32_class)
2983 valuetype_types [1] = mono_defaults.int32_class;
2984 else if (eclass == mono_defaults.int64_class)
2985 valuetype_types [1] = mono_defaults.uint64_class;
2986 else if (eclass == mono_defaults.uint64_class)
2987 valuetype_types [1] = mono_defaults.int64_class;
2988 else if (eclass == mono_defaults.byte_class)
2989 valuetype_types [1] = mono_defaults.sbyte_class;
2990 else if (eclass == mono_defaults.sbyte_class)
2991 valuetype_types [1] = mono_defaults.byte_class;
2992 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2993 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2996 /* this won't be needed once bug #325495 is completely fixed
2997 * though we'll need something similar to know which interfaces to allow
2998 * in arrays when they'll be lazyly created
3000 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3001 * MS returns diferrent types based on which instance is called. For example:
3002 * object obj = new byte[10][];
3003 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3004 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3007 * Fixing this should kill quite some code, save some bits and improve compatibility.
3010 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3012 MonoClass *eclass = class->element_class;
3013 static MonoClass* generic_icollection_class = NULL;
3014 static MonoClass* generic_ienumerable_class = NULL;
3015 static MonoClass* generic_ienumerator_class = NULL;
3016 static MonoClass* generic_ireadonlylist_class = NULL;
3017 static MonoClass* generic_ireadonlycollection_class = NULL;
3018 MonoClass *valuetype_types[2] = { NULL, NULL };
3019 MonoClass **interfaces = NULL;
3020 int i, nifaces, interface_count, real_count, original_rank;
3022 gboolean internal_enumerator;
3023 gboolean eclass_is_valuetype;
3025 if (!mono_defaults.generic_ilist_class) {
3029 internal_enumerator = FALSE;
3030 eclass_is_valuetype = FALSE;
3031 original_rank = eclass->rank;
3032 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3033 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3035 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3037 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3038 original_rank = eclass->rank;
3040 eclass = eclass->element_class;
3041 internal_enumerator = TRUE;
3042 *is_enumerator = TRUE;
3050 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3051 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3053 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3055 if (!generic_icollection_class) {
3056 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3057 "System.Collections.Generic", "ICollection`1");
3058 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3059 "System.Collections.Generic", "IEnumerable`1");
3060 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3061 "System.Collections.Generic", "IEnumerator`1");
3062 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3063 "System.Collections.Generic", "IReadOnlyList`1");
3064 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3065 "System.Collections.Generic", "IReadOnlyCollection`1");
3068 mono_class_init (eclass);
3071 * Arrays in 2.0 need to implement a number of generic interfaces
3072 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3073 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3074 * We collect the types needed to build the
3075 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3076 * the generic interfaces needed to implement.
3078 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3079 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3081 if (eclass->valuetype) {
3082 nifaces = generic_ireadonlylist_class ? 5 : 3;
3083 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3085 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3086 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3087 if (internal_enumerator) {
3089 if (valuetype_types [1])
3093 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3094 interfaces [0] = valuetype_types [0];
3095 if (valuetype_types [1])
3096 interfaces [nifaces] = valuetype_types [1];
3098 eclass_is_valuetype = TRUE;
3101 int idepth = eclass->idepth;
3102 if (!internal_enumerator)
3104 nifaces = generic_ireadonlylist_class ? 2 : 3;
3106 // FIXME: This doesn't seem to work/required for generic params
3107 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3108 mono_class_setup_interface_offsets (eclass);
3110 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3111 /* we add object for interfaces and the supertypes for the other
3112 * types. The last of the supertypes is the element class itself which we
3113 * already created the explicit interfaces for (so we include it for IEnumerator
3114 * and exclude it for arrays).
3116 if (MONO_CLASS_IS_INTERFACE (eclass))
3119 interface_count += idepth;
3120 if (eclass->rank && eclass->element_class->valuetype) {
3121 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3122 if (valuetype_types [1])
3125 /* IList, ICollection, IEnumerable, IReadOnlyList */
3126 interface_count *= nifaces;
3127 real_count = interface_count;
3128 if (internal_enumerator) {
3129 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3130 if (valuetype_types [1])
3133 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3134 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3135 interfaces [0] = mono_defaults.object_class;
3139 for (i = 0; i < idepth; i++) {
3140 mono_class_init (eclass->supertypes [i]);
3141 interfaces [j] = eclass->supertypes [i];
3145 if (all_interfaces) {
3146 for (i = 0; i < eclass->interface_offsets_count; i++) {
3147 interfaces [j] = eclass->interfaces_packed [i];
3151 for (i = 0; i < eclass->interface_count; i++) {
3152 interfaces [j] = eclass->interfaces [i];
3156 if (valuetype_types [1]) {
3157 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3162 /* instantiate the generic interfaces */
3163 for (i = 0; i < interface_count; i += nifaces) {
3164 MonoClass *iface = interfaces [i];
3166 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3167 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3169 if (eclass->valuetype) {
3170 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3171 if (generic_ireadonlylist_class) {
3172 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3173 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3176 if (!generic_ireadonlylist_class)
3177 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3180 if (internal_enumerator) {
3182 /* instantiate IEnumerator<iface> */
3183 for (i = 0; i < interface_count; i++) {
3184 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3186 j = interface_count;
3187 if (!eclass_is_valuetype) {
3188 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3189 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3192 for (i = 0; i < eclass->idepth; i++) {
3193 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3197 for (i = 0; i < eclass->interface_offsets_count; i++) {
3198 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3202 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3204 if (valuetype_types [1])
3205 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3209 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3210 for (i = 0; i < real_count; ++i) {
3211 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3212 g_print ("%s implements %s\n", type_name, name);
3223 find_array_interface (MonoClass *klass, const char *name)
3226 for (i = 0; i < klass->interface_count; ++i) {
3227 if (strcmp (klass->interfaces [i]->name, name) == 0)
3234 * Return the number of virtual methods.
3235 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3236 * Return -1 on failure.
3237 * FIXME It would be nice if this information could be cached somewhere.
3240 count_virtual_methods (MonoClass *class)
3244 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3246 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3247 mono_class_setup_methods (class);
3248 if (class->exception_type)
3251 for (i = 0; i < class->method.count; ++i) {
3252 flags = class->methods [i]->flags;
3253 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3257 for (i = 0; i < class->method.count; ++i) {
3258 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3260 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3268 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3276 m = (l + num_ifaces) / 2;
3277 if (interfaces_full [m] == ic)
3279 if (l == num_ifaces)
3281 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3290 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3292 int i = find_interface (num_ifaces, interfaces_full, ic);
3294 return interface_offsets_full [i];
3299 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3301 int i = find_interface (num_ifaces, interfaces_full, ic);
3305 interface_offsets_full [i] = offset;
3308 for (i = 0; i < num_ifaces; ++i) {
3309 if (interfaces_full [i]) {
3311 if (interfaces_full [i]->interface_id < ic->interface_id)
3314 while (end < num_ifaces && interfaces_full [end]) end++;
3315 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3316 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3318 interfaces_full [i] = ic;
3319 interface_offsets_full [i] = offset;
3325 #ifdef COMPRESSED_INTERFACE_BITMAP
3328 * Compressed interface bitmap design.
3330 * Interface bitmaps take a large amount of memory, because their size is
3331 * linear with the maximum interface id assigned in the process (each interface
3332 * is assigned a unique id as it is loaded). The number of interface classes
3333 * is high because of the many implicit interfaces implemented by arrays (we'll
3334 * need to lazy-load them in the future).
3335 * Most classes implement a very small number of interfaces, so the bitmap is
3336 * sparse. This bitmap needs to be checked by interface casts, so access to the
3337 * needed bit must be fast and doable with few jit instructions.
3339 * The current compression format is as follows:
3340 * *) it is a sequence of one or more two-byte elements
3341 * *) the first byte in the element is the count of empty bitmap bytes
3342 * at the current bitmap position
3343 * *) the second byte in the element is an actual bitmap byte at the current
3346 * As an example, the following compressed bitmap bytes:
3347 * 0x07 0x01 0x00 0x7
3348 * correspond to the following bitmap:
3349 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3351 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3352 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3353 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3357 * mono_compress_bitmap:
3358 * @dest: destination buffer
3359 * @bitmap: bitmap buffer
3360 * @size: size of @bitmap in bytes
3362 * This is a mono internal function.
3363 * The @bitmap data is compressed into a format that is small but
3364 * still searchable in few instructions by the JIT and runtime.
3365 * The compressed data is stored in the buffer pointed to by the
3366 * @dest array. Passing a #NULL value for @dest allows to just compute
3367 * the size of the buffer.
3368 * This compression algorithm assumes the bits set in the bitmap are
3369 * few and far between, like in interface bitmaps.
3370 * Returns: the size of the compressed bitmap in bytes.
3373 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3377 const uint8_t *end = bitmap + size;
3378 while (bitmap < end) {
3379 if (*bitmap || numz == 255) {
3403 * mono_class_interface_match:
3404 * @bitmap: a compressed bitmap buffer
3405 * @id: the index to check in the bitmap
3407 * This is a mono internal function.
3408 * Checks if a bit is set in a compressed interface bitmap. @id must
3409 * be already checked for being smaller than the maximum id encoded in the
3412 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3416 mono_class_interface_match (const uint8_t *bitmap, int id)
3419 id -= bitmap [0] * 8;
3423 return bitmap [1] & (1 << id);
3432 * LOCKING: this is supposed to be called with the loader lock held.
3433 * Return -1 on failure and set exception_type
3436 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3440 int i, j, max_iid, num_ifaces;
3441 MonoClass **interfaces_full = NULL;
3442 int *interface_offsets_full = NULL;
3444 GPtrArray **ifaces_array = NULL;
3445 int interface_offsets_count;
3446 MonoClass **array_interfaces = NULL;
3447 int num_array_interfaces;
3448 int is_enumerator = FALSE;
3450 mono_class_setup_supertypes (class);
3452 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3453 * implicit interfaces have the property that they are assigned the same slot in the
3454 * vtables for compatible interfaces
3456 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3458 /* compute maximum number of slots and maximum interface id */
3460 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3461 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3462 for (j = 0; j < class->idepth; j++) {
3463 k = class->supertypes [j];
3464 num_ifaces += k->interface_count;
3465 for (i = 0; i < k->interface_count; i++) {
3466 ic = k->interfaces [i];
3469 mono_class_init (ic);
3471 if (max_iid < ic->interface_id)
3472 max_iid = ic->interface_id;
3474 ifaces = mono_class_get_implemented_interfaces (k, &error);
3475 if (!mono_error_ok (&error)) {
3476 char *name = mono_type_get_full_name (k);
3477 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)));
3479 mono_error_cleanup (&error);
3484 num_ifaces += ifaces->len;
3485 for (i = 0; i < ifaces->len; ++i) {
3486 ic = g_ptr_array_index (ifaces, i);
3487 if (max_iid < ic->interface_id)
3488 max_iid = ic->interface_id;
3490 ifaces_array [j] = ifaces;
3494 for (i = 0; i < num_array_interfaces; ++i) {
3495 ic = array_interfaces [i];
3496 mono_class_init (ic);
3497 if (max_iid < ic->interface_id)
3498 max_iid = ic->interface_id;
3501 if (MONO_CLASS_IS_INTERFACE (class)) {
3503 if (max_iid < class->interface_id)
3504 max_iid = class->interface_id;
3506 class->max_interface_id = max_iid;
3507 /* compute vtable offset for interfaces */
3508 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3509 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3511 for (i = 0; i < num_ifaces; i++) {
3512 interface_offsets_full [i] = -1;
3515 /* skip the current class */
3516 for (j = 0; j < class->idepth - 1; j++) {
3517 k = class->supertypes [j];
3518 ifaces = ifaces_array [j];
3521 for (i = 0; i < ifaces->len; ++i) {
3523 ic = g_ptr_array_index (ifaces, i);
3525 /*Force the sharing of interface offsets between parent and subtypes.*/
3526 io = mono_class_interface_offset (k, ic);
3528 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3533 g_assert (class == class->supertypes [class->idepth - 1]);
3534 ifaces = ifaces_array [class->idepth - 1];
3536 for (i = 0; i < ifaces->len; ++i) {
3538 ic = g_ptr_array_index (ifaces, i);
3539 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3541 count = count_virtual_methods (ic);
3543 char *name = mono_type_get_full_name (ic);
3544 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3553 if (MONO_CLASS_IS_INTERFACE (class))
3554 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3556 if (num_array_interfaces) {
3557 if (is_enumerator) {
3558 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3559 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3560 g_assert (ienumerator_offset >= 0);
3561 for (i = 0; i < num_array_interfaces; ++i) {
3562 ic = array_interfaces [i];
3563 if (strcmp (ic->name, "IEnumerator`1") == 0)
3564 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3566 g_assert_not_reached ();
3567 /*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);*/
3570 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3571 int ilist_iface_idx = find_array_interface (class, "IList`1");
3572 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3573 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3574 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3575 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3576 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3577 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3578 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3579 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3580 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3581 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3582 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3583 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3584 for (i = 0; i < num_array_interfaces; ++i) {
3586 ic = array_interfaces [i];
3587 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3588 offset = ilist_offset;
3589 else if (strcmp (ic->name, "ICollection`1") == 0)
3590 offset = icollection_offset;
3591 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3592 offset = ienumerable_offset;
3593 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3594 offset = ireadonlylist_offset;
3595 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3596 offset = ireadonlycollection_offset;
3598 g_assert_not_reached ();
3599 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3600 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3605 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3606 if (interface_offsets_full [i] != -1) {
3607 interface_offsets_count ++;
3612 * We might get called multiple times:
3613 * - mono_class_init ()
3614 * - mono_class_setup_vtable ().
3615 * - mono_class_setup_interface_offsets ().
3616 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3617 * means we have to overwrite those when called from other places (#4440).
3619 if (class->interfaces_packed && !overwrite) {
3620 g_assert (class->interface_offsets_count == interface_offsets_count);
3624 class->interface_offsets_count = interface_offsets_count;
3625 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3626 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3627 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3628 #ifdef COMPRESSED_INTERFACE_BITMAP
3629 bitmap = g_malloc0 (bsize);
3631 bitmap = mono_class_alloc0 (class, bsize);
3633 for (i = 0; i < interface_offsets_count; i++) {
3634 int id = interfaces_full [i]->interface_id;
3635 bitmap [id >> 3] |= (1 << (id & 7));
3636 class->interfaces_packed [i] = interfaces_full [i];
3637 class->interface_offsets_packed [i] = interface_offsets_full [i];
3638 /*if (num_array_interfaces)
3639 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]);*/
3641 #ifdef COMPRESSED_INTERFACE_BITMAP
3642 i = mono_compress_bitmap (NULL, bitmap, bsize);
3643 class->interface_bitmap = mono_class_alloc0 (class, i);
3644 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3647 class->interface_bitmap = bitmap;
3652 g_free (interfaces_full);
3653 g_free (interface_offsets_full);
3654 g_free (array_interfaces);
3655 for (i = 0; i < class->idepth; i++) {
3656 ifaces = ifaces_array [i];
3658 g_ptr_array_free (ifaces, TRUE);
3660 g_free (ifaces_array);
3662 //printf ("JUST DONE: ");
3663 //print_implemented_interfaces (class);
3669 * Setup interface offsets for interfaces.
3671 * - class->max_interface_id
3672 * - class->interface_offsets_count
3673 * - class->interfaces_packed
3674 * - class->interface_offsets_packed
3675 * - class->interface_bitmap
3677 * This function can fail @class.
3680 mono_class_setup_interface_offsets (MonoClass *class)
3682 mono_loader_lock ();
3684 setup_interface_offsets (class, 0, FALSE);
3686 mono_loader_unlock ();
3689 /*Checks if @klass has @parent as one of it's parents type gtd
3693 * Bar<T> : Foo<Bar<Bar<T>>>
3697 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3699 klass = mono_class_get_generic_type_definition (klass);
3700 parent = mono_class_get_generic_type_definition (parent);
3701 mono_class_setup_supertypes (klass);
3702 mono_class_setup_supertypes (parent);
3704 return klass->idepth >= parent->idepth &&
3705 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3709 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3711 MonoGenericInst *ginst;
3713 if (!class->generic_class) {
3714 mono_class_setup_vtable_full (class, in_setup);
3715 return class->exception_type == 0;
3718 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3719 if (class->generic_class->container_class->exception_type) {
3720 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3724 ginst = class->generic_class->context.class_inst;
3725 for (i = 0; i < ginst->type_argc; ++i) {
3727 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3729 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3730 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3731 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3733 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3734 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3742 * mono_class_setup_vtable:
3744 * Creates the generic vtable of CLASS.
3745 * Initializes the following fields in MonoClass:
3748 * Plus all the fields initialized by setup_interface_offsets ().
3749 * If there is an error during vtable construction, class->exception_type is set.
3751 * LOCKING: Acquires the loader lock.
3754 mono_class_setup_vtable (MonoClass *class)
3756 mono_class_setup_vtable_full (class, NULL);
3760 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3762 MonoMethod **overrides;
3763 MonoGenericContext *context;
3771 if (MONO_CLASS_IS_INTERFACE (class)) {
3772 /* This sets method->slot for all methods if this is an interface */
3773 mono_class_setup_methods (class);
3777 if (class->exception_type)
3780 if (g_list_find (in_setup, class))
3783 mono_loader_lock ();
3785 if (class->vtable) {
3786 mono_loader_unlock ();
3790 mono_stats.generic_vtable_count ++;
3791 in_setup = g_list_prepend (in_setup, class);
3793 if (class->generic_class) {
3794 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3795 mono_loader_unlock ();
3796 g_list_remove (in_setup, class);
3800 context = mono_class_get_context (class);
3801 type_token = class->generic_class->container_class->type_token;
3803 context = (MonoGenericContext *) class->generic_container;
3804 type_token = class->type_token;
3807 if (image_is_dynamic (class->image)) {
3808 /* Generic instances can have zero method overrides without causing any harm.
3809 * This is true since we don't do layout all over again for them, we simply inflate
3810 * the layout of the parent.
3812 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3814 /* The following call fails if there are missing methods in the type */
3815 /* FIXME it's probably a good idea to avoid this for generic instances. */
3816 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3820 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3822 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3826 mono_loader_unlock ();
3827 g_list_remove (in_setup, class);
3832 #define DEBUG_INTERFACE_VTABLE_CODE 0
3833 #define TRACE_INTERFACE_VTABLE_CODE 0
3834 #define VERIFY_INTERFACE_VTABLE_CODE 0
3835 #define VTABLE_SELECTOR (1)
3837 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3838 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3839 if (!(VTABLE_SELECTOR)) break; \
3843 #define DEBUG_INTERFACE_VTABLE(stmt)
3846 #if TRACE_INTERFACE_VTABLE_CODE
3847 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3848 if (!(VTABLE_SELECTOR)) break; \
3852 #define TRACE_INTERFACE_VTABLE(stmt)
3855 #if VERIFY_INTERFACE_VTABLE_CODE
3856 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3857 if (!(VTABLE_SELECTOR)) break; \
3861 #define VERIFY_INTERFACE_VTABLE(stmt)
3865 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3867 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3871 GString *res = g_string_new ("");
3873 g_string_append_c (res, '(');
3874 for (i = 0; i < sig->param_count; ++i) {
3876 g_string_append_c (res, ',');
3877 mono_type_get_desc (res, sig->params [i], include_namespace);
3879 g_string_append (res, ")=>");
3880 if (sig->ret != NULL) {
3881 mono_type_get_desc (res, sig->ret, include_namespace);
3883 g_string_append (res, "NULL");
3886 g_string_free (res, FALSE);
3890 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3891 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3892 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3893 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3901 is_wcf_hack_disabled (void)
3903 static gboolean disabled;
3904 static gboolean inited = FALSE;
3906 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3913 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
3914 MonoMethodSignature *cmsig, *imsig;
3915 if (strcmp (im->name, cm->name) == 0) {
3916 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3917 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3920 if (! slot_is_empty) {
3921 if (require_newslot) {
3922 if (! interface_is_explicitly_implemented_by_class) {
3923 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3926 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3927 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3931 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3934 cmsig = mono_method_signature (cm);
3935 imsig = mono_method_signature (im);
3936 if (!cmsig || !imsig) {
3937 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3941 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3942 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3943 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3944 TRACE_INTERFACE_VTABLE (printf ("]"));
3947 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3948 /* CAS - SecurityAction.InheritanceDemand on interface */
3949 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3950 mono_secman_inheritancedemand_method (cm, im);
3953 if (mono_security_core_clr_enabled ())
3954 mono_security_core_clr_check_override (class, cm, im);
3956 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3957 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3958 char *body_name = mono_method_full_name (cm, TRUE);
3959 char *decl_name = mono_method_full_name (im, TRUE);
3960 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));
3968 MonoClass *ic = im->klass;
3969 const char *ic_name_space = ic->name_space;
3970 const char *ic_name = ic->name;
3973 if (! require_newslot) {
3974 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3977 if (cm->klass->rank == 0) {
3978 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3981 cmsig = mono_method_signature (cm);
3982 imsig = mono_method_signature (im);
3983 if (!cmsig || !imsig) {
3984 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3988 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3989 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3990 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3991 TRACE_INTERFACE_VTABLE (printf ("]"));
3994 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3995 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3998 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3999 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4002 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))) {
4003 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4007 subname = strstr (cm->name, ic_name_space);
4008 if (subname != cm->name) {
4009 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4012 subname += strlen (ic_name_space);
4013 if (subname [0] != '.') {
4014 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4018 if (strstr (subname, ic_name) != subname) {
4019 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4022 subname += strlen (ic_name);
4023 if (subname [0] != '.') {
4024 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4028 if (strcmp (subname, im->name) != 0) {
4029 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4033 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4034 /* CAS - SecurityAction.InheritanceDemand on interface */
4035 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4036 mono_secman_inheritancedemand_method (cm, im);
4039 if (mono_security_core_clr_enabled ())
4040 mono_security_core_clr_check_override (class, cm, im);
4042 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4043 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4044 char *body_name = mono_method_full_name (cm, TRUE);
4045 char *decl_name = mono_method_full_name (im, TRUE);
4046 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));
4056 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4058 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4059 MonoMethod *method = key;
4060 MonoMethod *override = value;
4061 MonoClass *method_class = mono_method_get_class (method);
4062 MonoClass *override_class = mono_method_get_class (override);
4064 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4065 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4066 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4069 print_overrides (GHashTable *override_map, const char *message) {
4071 printf ("Override map \"%s\" START:\n", message);
4072 g_hash_table_foreach (override_map, foreach_override, NULL);
4073 printf ("Override map \"%s\" END.\n", message);
4075 printf ("Override map \"%s\" EMPTY.\n", message);
4079 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4080 char *full_name = mono_type_full_name (&class->byval_arg);
4084 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4086 if (print_interfaces) {
4087 print_implemented_interfaces (class);
4088 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4091 if (class->parent) {
4092 parent_size = class->parent->vtable_size;
4096 for (i = 0; i < size; ++i) {
4097 MonoMethod *cm = vtable [i];
4098 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4099 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4101 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4109 #if VERIFY_INTERFACE_VTABLE_CODE
4111 mono_method_try_get_vtable_index (MonoMethod *method)
4113 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4114 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4115 if (imethod->declaring->is_generic)
4116 return imethod->declaring->slot;
4118 return method->slot;
4122 mono_class_verify_vtable (MonoClass *class)
4125 char *full_name = mono_type_full_name (&class->byval_arg);
4127 printf ("*** Verifying VTable of class '%s' \n", full_name);
4131 if (!class->methods)
4134 for (i = 0; i < class->method.count; ++i) {
4135 MonoMethod *cm = class->methods [i];
4138 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4142 full_name = mono_method_full_name (cm, TRUE);
4144 slot = mono_method_try_get_vtable_index (cm);
4146 if (slot >= class->vtable_size) {
4147 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4151 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4152 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4153 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4154 g_free (other_name);
4157 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4164 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4166 char *method_signature;
4169 for (index = 0; index < onum; ++index) {
4170 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4171 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4173 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4174 type_name = mono_type_full_name (&class->byval_arg);
4175 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4176 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4177 g_free (method_signature);
4179 mono_class_setup_methods (class);
4180 if (class->exception_type) {
4181 char *name = mono_type_get_full_name (class);
4182 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4186 for (index = 0; index < class->method.count; ++index) {
4187 MonoMethod *cm = class->methods [index];
4188 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4190 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4191 g_free (method_signature);
4196 mono_method_get_method_definition (MonoMethod *method)
4198 while (method->is_inflated)
4199 method = ((MonoMethodInflated*)method)->declaring;
4204 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4208 for (i = 0; i < onum; ++i) {
4209 MonoMethod *decl = overrides [i * 2];
4210 MonoMethod *body = overrides [i * 2 + 1];
4212 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4213 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4217 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4218 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4219 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4221 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4225 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4226 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4227 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4229 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4233 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4234 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4238 body = mono_method_get_method_definition (body);
4239 decl = mono_method_get_method_definition (decl);
4241 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4242 char *body_name = mono_method_full_name (body, TRUE);
4243 char *decl_name = mono_method_full_name (decl, TRUE);
4244 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));
4254 mono_class_need_stelemref_method (MonoClass *class)
4256 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4260 * LOCKING: this is supposed to be called with the loader lock held.
4263 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4267 MonoMethod **vtable;
4268 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4269 GPtrArray *ifaces = NULL;
4270 GHashTable *override_map = NULL;
4271 gboolean security_enabled = mono_security_enabled ();
4273 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4274 int first_non_interface_slot;
4276 GSList *virt_methods = NULL, *l;
4277 int stelemref_slot = 0;
4282 if (overrides && !verify_class_overrides (class, overrides, onum))
4285 ifaces = mono_class_get_implemented_interfaces (class, &error);
4286 if (!mono_error_ok (&error)) {
4287 char *name = mono_type_get_full_name (class);
4288 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)));
4290 mono_error_cleanup (&error);
4292 } else if (ifaces) {
4293 for (i = 0; i < ifaces->len; i++) {
4294 MonoClass *ic = g_ptr_array_index (ifaces, i);
4295 max_vtsize += ic->method.count;
4297 g_ptr_array_free (ifaces, TRUE);
4301 if (class->parent) {
4302 mono_class_init (class->parent);
4303 mono_class_setup_vtable_full (class->parent, in_setup);
4305 if (class->parent->exception_type) {
4306 char *name = mono_type_get_full_name (class->parent);
4307 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4312 max_vtsize += class->parent->vtable_size;
4313 cur_slot = class->parent->vtable_size;
4316 max_vtsize += class->method.count;
4318 /*Array have a slot for stelemref*/
4319 if (mono_class_need_stelemref_method (class)) {
4320 stelemref_slot = cur_slot;
4325 vtable = alloca (sizeof (gpointer) * max_vtsize);
4326 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4328 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4330 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4331 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4334 max_iid = class->max_interface_id;
4335 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4337 /* Optimized version for generic instances */
4338 if (class->generic_class) {
4340 MonoClass *gklass = class->generic_class->container_class;
4343 mono_class_setup_vtable_full (gklass, in_setup);
4344 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4345 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4349 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4350 class->vtable_size = gklass->vtable_size;
4351 for (i = 0; i < gklass->vtable_size; ++i)
4352 if (gklass->vtable [i]) {
4353 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4354 if (!mono_error_ok (&error)) {
4355 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4356 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4358 mono_error_cleanup (&error);
4362 tmp [i]->slot = gklass->vtable [i]->slot;
4364 mono_memory_barrier ();
4365 class->vtable = tmp;
4367 /* Have to set method->slot for abstract virtual methods */
4368 if (class->methods && gklass->methods) {
4369 for (i = 0; i < class->method.count; ++i)
4370 if (class->methods [i]->slot == -1)
4371 class->methods [i]->slot = gklass->methods [i]->slot;
4377 if (class->parent && class->parent->vtable_size) {
4378 MonoClass *parent = class->parent;
4381 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4383 // Also inherit parent interface vtables, just as a starting point.
4384 // This is needed otherwise bug-77127.exe fails when the property methods
4385 // have different names in the iterface and the class, because for child
4386 // classes the ".override" information is not used anymore.
4387 for (i = 0; i < parent->interface_offsets_count; i++) {
4388 MonoClass *parent_interface = parent->interfaces_packed [i];
4389 int interface_offset = mono_class_interface_offset (class, parent_interface);
4390 /*FIXME this is now dead code as this condition will never hold true.
4391 Since interface offsets are inherited then the offset of an interface implemented
4392 by a parent will never be the out of it's vtable boundary.
4394 if (interface_offset >= parent->vtable_size) {
4395 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4398 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4399 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4400 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4401 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4402 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4403 parent_interface_offset + j, parent_interface_offset, j,
4404 interface_offset + j, interface_offset, j));
4411 /*Array have a slot for stelemref*/
4412 if (mono_class_need_stelemref_method (class)) {
4413 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4415 method->slot = stelemref_slot;
4417 g_assert (method->slot == stelemref_slot);
4419 vtable [stelemref_slot] = method;
4422 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4423 /* override interface methods */
4424 for (i = 0; i < onum; i++) {
4425 MonoMethod *decl = overrides [i*2];
4426 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4428 dslot = mono_method_get_vtable_slot (decl);
4430 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4434 dslot += mono_class_interface_offset (class, decl->klass);
4435 vtable [dslot] = overrides [i*2 + 1];
4436 vtable [dslot]->slot = dslot;
4438 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4440 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4442 if (mono_security_core_clr_enabled ())
4443 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4446 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4447 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4450 * Create a list of virtual methods to avoid calling
4451 * mono_class_get_virtual_methods () which is slow because of the metadata
4455 gpointer iter = NULL;
4458 virt_methods = NULL;
4459 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4460 virt_methods = g_slist_prepend (virt_methods, cm);
4462 if (class->exception_type)
4466 // Loop on all implemented interfaces...
4467 for (i = 0; i < class->interface_offsets_count; i++) {
4468 MonoClass *parent = class->parent;
4470 gboolean interface_is_explicitly_implemented_by_class;
4473 ic = class->interfaces_packed [i];
4474 ic_offset = mono_class_interface_offset (class, ic);
4476 mono_class_setup_methods (ic);
4477 if (ic->exception_type)
4480 // Check if this interface is explicitly implemented (instead of just inherited)
4481 if (parent != NULL) {
4482 int implemented_interfaces_index;
4483 interface_is_explicitly_implemented_by_class = FALSE;
4484 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4485 if (ic == class->interfaces [implemented_interfaces_index]) {
4486 interface_is_explicitly_implemented_by_class = TRUE;
4491 interface_is_explicitly_implemented_by_class = TRUE;
4494 // Loop on all interface methods...
4495 for (im_index = 0; im_index < ic->method.count; im_index++) {
4496 MonoMethod *im = ic->methods [im_index];
4497 int im_slot = ic_offset + im->slot;
4498 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4500 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4503 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4505 // If there is an explicit implementation, just use it right away,
4506 // otherwise look for a matching method
4507 if (override_im == NULL) {
4511 // First look for a suitable method among the class methods
4512 for (l = virt_methods; l; l = l->next) {
4514 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)));
4515 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4516 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4517 vtable [im_slot] = cm;
4518 /* Why do we need this? */
4523 TRACE_INTERFACE_VTABLE (printf ("\n"));
4524 if (class->exception_type) /*Might be set by check_interface_method_override*/
4528 // If the slot is still empty, look in all the inherited virtual methods...
4529 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4530 MonoClass *parent = class->parent;
4531 // Reverse order, so that last added methods are preferred
4532 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4533 MonoMethod *cm = parent->vtable [cm_index];
4535 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));
4536 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4537 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4538 vtable [im_slot] = cm;
4539 /* Why do we need this? */
4545 if (class->exception_type) /*Might be set by check_interface_method_override*/
4547 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4551 g_assert (vtable [im_slot] == override_im);
4556 // If the class is not abstract, check that all its interface slots are full.
4557 // The check is done here and not directly at the end of the loop above because
4558 // it can happen (for injected generic array interfaces) that the same slot is
4559 // processed multiple times (those interfaces have overlapping slots), and it
4560 // will not always be the first pass the one that fills the slot.
4561 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4562 for (i = 0; i < class->interface_offsets_count; i++) {
4566 ic = class->interfaces_packed [i];
4567 ic_offset = mono_class_interface_offset (class, ic);
4569 for (im_index = 0; im_index < ic->method.count; im_index++) {
4570 MonoMethod *im = ic->methods [im_index];
4571 int im_slot = ic_offset + im->slot;
4573 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4576 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4577 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4578 if (vtable [im_slot] == NULL) {
4579 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4586 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4587 for (l = virt_methods; l; l = l->next) {
4590 * If the method is REUSE_SLOT, we must check in the
4591 * base class for a method to override.
4593 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4595 for (k = class->parent; k ; k = k->parent) {
4600 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4601 MonoMethodSignature *cmsig, *m1sig;
4603 cmsig = mono_method_signature (cm);
4604 m1sig = mono_method_signature (m1);
4606 if (!cmsig || !m1sig) {
4607 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4611 if (!strcmp(cm->name, m1->name) &&
4612 mono_metadata_signature_equal (cmsig, m1sig)) {
4614 /* CAS - SecurityAction.InheritanceDemand */
4615 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4616 mono_secman_inheritancedemand_method (cm, m1);
4619 if (mono_security_core_clr_enabled ())
4620 mono_security_core_clr_check_override (class, cm, m1);
4622 slot = mono_method_get_vtable_slot (m1);
4626 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4627 char *body_name = mono_method_full_name (cm, TRUE);
4628 char *decl_name = mono_method_full_name (m1, TRUE);
4629 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));
4635 g_assert (cm->slot < max_vtsize);
4637 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4638 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4639 mono_method_full_name (m1, 1), m1,
4640 mono_method_full_name (cm, 1), cm));
4641 g_hash_table_insert (override_map, m1, cm);
4645 if (k->exception_type)
4655 /*Non final newslot methods must be given a non-interface vtable slot*/
4656 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4660 cm->slot = cur_slot++;
4662 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4663 vtable [cm->slot] = cm;
4666 /* override non interface methods */
4667 for (i = 0; i < onum; i++) {
4668 MonoMethod *decl = overrides [i*2];
4669 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4670 g_assert (decl->slot != -1);
4671 vtable [decl->slot] = overrides [i*2 + 1];
4672 overrides [i * 2 + 1]->slot = decl->slot;
4674 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4675 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4676 mono_method_full_name (decl, 1), decl,
4677 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4678 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4680 if (mono_security_core_clr_enabled ())
4681 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4686 * If a method occupies more than one place in the vtable, and it is
4687 * overriden, then change the other occurances too.
4692 for (i = 0; i < max_vtsize; ++i)
4694 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4696 cm = g_hash_table_lookup (override_map, vtable [i]);
4701 g_hash_table_destroy (override_map);
4702 override_map = NULL;
4705 g_slist_free (virt_methods);
4706 virt_methods = NULL;
4708 /* Ensure that all vtable slots are filled with concrete instance methods */
4709 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4710 for (i = 0; i < cur_slot; ++i) {
4711 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4712 char *type_name = mono_type_get_full_name (class);
4713 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4714 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));
4716 g_free (method_name);
4722 if (class->generic_class) {
4723 MonoClass *gklass = class->generic_class->container_class;
4725 mono_class_init (gklass);
4727 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4729 /* Check that the vtable_size value computed in mono_class_init () is correct */
4730 if (class->vtable_size)
4731 g_assert (cur_slot == class->vtable_size);
4732 class->vtable_size = cur_slot;
4735 /* Try to share the vtable with our parent. */
4736 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4737 mono_memory_barrier ();
4738 class->vtable = class->parent->vtable;
4740 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4741 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4742 mono_memory_barrier ();
4743 class->vtable = tmp;
4746 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4747 if (mono_print_vtable) {
4750 print_implemented_interfaces (class);
4752 for (i = 0; i <= max_iid; i++)
4753 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4756 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4757 class->vtable_size, icount);
4759 for (i = 0; i < cur_slot; ++i) {
4764 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4765 mono_method_full_name (cm, TRUE));
4771 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4772 class->name, max_iid);
4774 for (i = 0; i < class->interface_count; i++) {
4775 ic = class->interfaces [i];
4776 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4777 mono_class_interface_offset (class, ic),
4778 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4781 for (k = class->parent; k ; k = k->parent) {
4782 for (i = 0; i < k->interface_count; i++) {
4783 ic = k->interfaces [i];
4784 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4785 mono_class_interface_offset (class, ic),
4786 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4792 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4797 char *name = mono_type_get_full_name (class);
4798 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4801 g_hash_table_destroy (override_map);
4803 g_slist_free (virt_methods);
4808 * mono_method_get_vtable_slot:
4810 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4811 * LOCKING: Acquires the loader lock.
4813 * FIXME Use proper MonoError machinery here.
4816 mono_method_get_vtable_slot (MonoMethod *method)
4818 if (method->slot == -1) {
4819 mono_class_setup_vtable (method->klass);
4820 if (method->klass->exception_type)
4822 if (method->slot == -1) {
4826 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4827 g_assert (method->klass->generic_class);
4828 gklass = method->klass->generic_class->container_class;
4829 mono_class_setup_methods (method->klass);
4830 g_assert (method->klass->methods);
4831 for (i = 0; i < method->klass->method.count; ++i) {
4832 if (method->klass->methods [i] == method)
4835 g_assert (i < method->klass->method.count);
4836 g_assert (gklass->methods);
4837 method->slot = gklass->methods [i]->slot;
4839 g_assert (method->slot != -1);
4841 return method->slot;
4845 * mono_method_get_vtable_index:
4848 * Returns the index into the runtime vtable to access the method or,
4849 * in the case of a virtual generic method, the virtual generic method
4850 * thunk. Returns -1 on failure.
4852 * FIXME Use proper MonoError machinery here.
4855 mono_method_get_vtable_index (MonoMethod *method)
4857 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4858 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4859 if (imethod->declaring->is_generic)
4860 return mono_method_get_vtable_slot (imethod->declaring);
4862 return mono_method_get_vtable_slot (method);
4865 static MonoMethod *default_ghc = NULL;
4866 static MonoMethod *default_finalize = NULL;
4867 static int finalize_slot = -1;
4868 static int ghc_slot = -1;
4871 initialize_object_slots (MonoClass *class)
4876 if (class == mono_defaults.object_class) {
4877 mono_class_setup_vtable (class);
4878 for (i = 0; i < class->vtable_size; ++i) {
4879 MonoMethod *cm = class->vtable [i];
4881 if (!strcmp (cm->name, "GetHashCode"))
4883 else if (!strcmp (cm->name, "Finalize"))
4887 g_assert (ghc_slot > 0);
4888 default_ghc = class->vtable [ghc_slot];
4890 g_assert (finalize_slot > 0);
4891 default_finalize = class->vtable [finalize_slot];
4896 MonoMethod *array_method;
4898 } GenericArrayMethodInfo;
4900 static int generic_array_method_num = 0;
4901 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4904 generic_array_methods (MonoClass *class)
4906 int i, count_generic = 0;
4907 GList *list = NULL, *tmp;
4908 if (generic_array_method_num)
4909 return generic_array_method_num;
4910 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4911 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4912 for (i = 0; i < class->parent->method.count; i++) {
4913 MonoMethod *m = class->parent->methods [i];
4914 if (!strncmp (m->name, "InternalArray__", 15)) {
4916 list = g_list_prepend (list, m);
4919 list = g_list_reverse (list);
4920 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4922 for (tmp = list; tmp; tmp = tmp->next) {
4923 const char *mname, *iname;
4925 MonoMethod *m = tmp->data;
4926 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4927 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4929 generic_array_method_info [i].array_method = m;
4930 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4931 iname = "System.Collections.Generic.ICollection`1.";
4932 mname = m->name + 27;
4933 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4934 iname = "System.Collections.Generic.IEnumerable`1.";
4935 mname = m->name + 27;
4936 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4937 iname = "System.Collections.Generic.IReadOnlyList`1.";
4938 mname = m->name + strlen (ireadonlylist_prefix);
4939 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4940 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4941 mname = m->name + strlen (ireadonlycollection_prefix);
4942 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4943 iname = "System.Collections.Generic.IList`1.";
4944 mname = m->name + 15;
4946 g_assert_not_reached ();
4949 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4950 strcpy (name, iname);
4951 strcpy (name + strlen (iname), mname);
4952 generic_array_method_info [i].name = name;
4955 /*g_print ("array generic methods: %d\n", count_generic);*/
4957 generic_array_method_num = count_generic;
4959 return generic_array_method_num;
4963 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4965 MonoGenericContext tmp_context;
4968 tmp_context.class_inst = NULL;
4969 tmp_context.method_inst = iface->generic_class->context.class_inst;
4970 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4972 for (i = 0; i < generic_array_method_num; i++) {
4974 MonoMethod *m = generic_array_method_info [i].array_method;
4975 MonoMethod *inflated;
4977 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4978 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4979 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4984 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4986 int null_length = strlen ("(null)");
4987 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4988 char *s = mono_image_alloc (image, len);
4991 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4992 g_assert (result == len - 1);
4998 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
5000 gpointer exception_data = NULL;
5002 switch (error->exception_type) {
5003 case MONO_EXCEPTION_TYPE_LOAD:
5004 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5007 case MONO_EXCEPTION_MISSING_METHOD:
5008 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5011 case MONO_EXCEPTION_MISSING_FIELD: {
5012 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5013 const char *class_name;
5016 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5018 class_name = error->klass->name;
5020 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5023 g_free ((void*)class_name);
5027 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5030 if (error->ref_only)
5031 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.";
5033 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5035 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5039 case MONO_EXCEPTION_BAD_IMAGE:
5040 exception_data = error->msg;
5044 g_assert_not_reached ();
5047 mono_class_set_failure (class, error->exception_type, exception_data);
5052 * @class: the class to initialize
5054 * Compute the instance_size, class_size and other infos that cannot be
5055 * computed at mono_class_get() time. Also compute vtable_size if possible.
5056 * Returns TRUE on success or FALSE if there was a problem in loading
5057 * the type (incorrect assemblies, missing assemblies, methods, etc).
5059 * LOCKING: Acquires the loader lock.
5062 mono_class_init (MonoClass *class)
5065 MonoCachedClassInfo cached_info;
5066 gboolean has_cached_info;
5070 /* Double-checking locking pattern */
5071 if (class->inited || class->exception_type)
5072 return class->exception_type == MONO_EXCEPTION_NONE;
5074 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5076 /* We do everything inside the lock to prevent races */
5077 mono_loader_lock ();
5079 if (class->inited || class->exception_type) {
5080 mono_loader_unlock ();
5081 /* Somebody might have gotten in before us */
5082 return class->exception_type == MONO_EXCEPTION_NONE;
5085 if (class->init_pending) {
5086 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5090 class->init_pending = 1;
5092 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5093 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5098 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5099 MonoClass *element_class = class->element_class;
5100 if (!element_class->inited)
5101 mono_class_init (element_class);
5102 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5103 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5108 /* CAS - SecurityAction.InheritanceDemand */
5109 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5110 mono_secman_inheritancedemand_class (class, class->parent);
5113 mono_stats.initialized_class_count++;
5115 if (class->generic_class && !class->generic_class->is_dynamic) {
5116 MonoClass *gklass = class->generic_class->container_class;
5118 mono_stats.generic_class_count++;
5120 class->method = gklass->method;
5121 class->field = gklass->field;
5123 mono_class_init (gklass);
5124 // FIXME: Why is this needed ?
5125 if (!gklass->exception_type)
5126 mono_class_setup_methods (gklass);
5127 if (gklass->exception_type) {
5128 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5132 if (MONO_CLASS_IS_INTERFACE (class))
5133 class->interface_id = mono_get_unique_iid (class);
5136 if (class->parent && !class->parent->inited)
5137 mono_class_init (class->parent);
5139 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5141 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5142 class->nested_classes_inited = TRUE;
5145 * Computes the size used by the fields, and their locations
5147 if (has_cached_info) {
5148 class->instance_size = cached_info.instance_size;
5149 class->sizes.class_size = cached_info.class_size;
5150 class->packing_size = cached_info.packing_size;
5151 class->min_align = cached_info.min_align;
5152 class->blittable = cached_info.blittable;
5153 class->has_references = cached_info.has_references;
5154 class->has_static_refs = cached_info.has_static_refs;
5155 class->no_special_static_fields = cached_info.no_special_static_fields;
5158 if (!class->size_inited){
5159 mono_class_setup_fields (class);
5160 if (class->exception_type || mono_loader_get_last_error ())
5164 /* Initialize arrays */
5166 class->method.count = 3 + (class->rank > 1? 2: 1);
5168 if (class->interface_count) {
5169 int count_generic = generic_array_methods (class);
5170 class->method.count += class->interface_count * count_generic;
5174 mono_class_setup_supertypes (class);
5177 initialize_object_slots (class);
5180 * Initialize the rest of the data without creating a generic vtable if possible.
5181 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5182 * also avoid computing a generic vtable.
5184 if (has_cached_info) {
5186 class->vtable_size = cached_info.vtable_size;
5187 class->has_finalize = cached_info.has_finalize;
5188 class->has_finalize_inited = TRUE;
5189 class->ghcimpl = cached_info.ghcimpl;
5190 class->has_cctor = cached_info.has_cctor;
5191 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5192 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5193 * The first slot if for array with.
5195 static int szarray_vtable_size[2] = { 0 };
5197 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5200 if (!szarray_vtable_size [slot]) {
5201 mono_class_setup_vtable (class);
5202 szarray_vtable_size [slot] = class->vtable_size;
5204 class->vtable_size = szarray_vtable_size[slot];
5206 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5207 MonoClass *gklass = class->generic_class->container_class;
5209 /* Generic instance case */
5210 class->ghcimpl = gklass->ghcimpl;
5211 class->has_cctor = gklass->has_cctor;
5213 mono_class_setup_vtable (gklass);
5214 if (gklass->exception_type) {
5215 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5219 class->vtable_size = gklass->vtable_size;
5223 /* ghcimpl is not currently used
5225 if (class->parent) {
5226 MonoMethod *cmethod = class->vtable [ghc_slot];
5227 if (cmethod->is_inflated)
5228 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5229 if (cmethod == default_ghc) {
5235 /* C# doesn't allow interfaces to have cctors */
5236 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5237 MonoMethod *cmethod = NULL;
5239 if (class->type_token) {
5240 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5241 /* The find_method function ignores the 'flags' argument */
5242 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5243 class->has_cctor = 1;
5245 mono_class_setup_methods (class);
5246 if (class->exception_type)
5249 for (i = 0; i < class->method.count; ++i) {
5250 MonoMethod *method = class->methods [i];
5251 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5252 (strcmp (".cctor", method->name) == 0)) {
5253 class->has_cctor = 1;
5261 if (class->parent) {
5262 int first_iface_slot;
5263 /* This will compute class->parent->vtable_size for some classes */
5264 mono_class_init (class->parent);
5265 if (class->parent->exception_type) {
5266 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5269 if (mono_loader_get_last_error ())
5271 if (!class->parent->vtable_size) {
5272 /* FIXME: Get rid of this somehow */
5273 mono_class_setup_vtable (class->parent);
5274 if (class->parent->exception_type) {
5275 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5278 if (mono_loader_get_last_error ())
5281 first_iface_slot = class->parent->vtable_size;
5282 if (mono_class_need_stelemref_method (class))
5284 setup_interface_offsets (class, first_iface_slot, TRUE);
5286 setup_interface_offsets (class, 0, TRUE);
5289 if (mono_security_core_clr_enabled ())
5290 mono_security_core_clr_check_inheritance (class);
5292 if (mono_loader_get_last_error ()) {
5293 if (class->exception_type == MONO_EXCEPTION_NONE) {
5294 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5296 mono_loader_clear_error ();
5299 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5300 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5305 /* Because of the double-checking locking pattern */
5306 mono_memory_barrier ();
5308 class->init_pending = 0;
5310 mono_loader_unlock ();
5312 return class->exception_type == MONO_EXCEPTION_NONE;
5316 * mono_class_has_finalizer:
5318 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5322 mono_class_has_finalizer (MonoClass *klass)
5324 MonoClass *class = klass;
5325 gboolean has_finalize = FALSE;
5327 if (klass->has_finalize_inited)
5328 return klass->has_finalize;
5330 /* Interfaces and valuetypes are not supposed to have finalizers */
5331 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5332 MonoMethod *cmethod = NULL;
5334 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5335 } else if (class->generic_class) {
5336 MonoClass *gklass = class->generic_class->container_class;
5338 has_finalize = mono_class_has_finalizer (gklass);
5339 } else if (class->parent && class->parent->has_finalize) {
5340 has_finalize = TRUE;
5342 if (class->parent) {
5344 * Can't search in metadata for a method named Finalize, because that
5345 * ignores overrides.
5347 mono_class_setup_vtable (class);
5348 if (class->exception_type || mono_loader_get_last_error ())
5351 cmethod = class->vtable [finalize_slot];
5355 g_assert (class->vtable_size > finalize_slot);
5357 if (class->parent) {
5358 if (cmethod->is_inflated)
5359 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5360 if (cmethod != default_finalize)
5361 has_finalize = TRUE;
5367 mono_image_lock (klass->image);
5369 if (!klass->has_finalize_inited) {
5370 klass->has_finalize = has_finalize ? 1 : 0;
5372 mono_memory_barrier ();
5373 klass->has_finalize_inited = TRUE;
5376 mono_image_unlock (klass->image);
5378 return klass->has_finalize;
5382 mono_is_corlib_image (MonoImage *image)
5384 /* FIXME: allow the dynamic case for our compilers and with full trust */
5385 if (image_is_dynamic (image))
5386 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5388 return image == mono_defaults.corlib;
5392 * LOCKING: this assumes the loader lock is held
5395 mono_class_setup_mono_type (MonoClass *class)
5397 const char *name = class->name;
5398 const char *nspace = class->name_space;
5399 gboolean is_corlib = mono_is_corlib_image (class->image);
5401 class->this_arg.byref = 1;
5402 class->this_arg.data.klass = class;
5403 class->this_arg.type = MONO_TYPE_CLASS;
5404 class->byval_arg.data.klass = class;
5405 class->byval_arg.type = MONO_TYPE_CLASS;
5407 if (is_corlib && !strcmp (nspace, "System")) {
5408 if (!strcmp (name, "ValueType")) {
5410 * do not set the valuetype bit for System.ValueType.
5411 * class->valuetype = 1;
5413 class->blittable = TRUE;
5414 } else if (!strcmp (name, "Enum")) {
5416 * do not set the valuetype bit for System.Enum.
5417 * class->valuetype = 1;
5419 class->valuetype = 0;
5420 class->enumtype = 0;
5421 } else if (!strcmp (name, "Object")) {
5422 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5423 } else if (!strcmp (name, "String")) {
5424 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5425 } else if (!strcmp (name, "TypedReference")) {
5426 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5430 if (class->valuetype) {
5431 int t = MONO_TYPE_VALUETYPE;
5433 if (is_corlib && !strcmp (nspace, "System")) {
5436 if (!strcmp (name, "Boolean")) {
5437 t = MONO_TYPE_BOOLEAN;
5438 } else if (!strcmp(name, "Byte")) {
5440 class->blittable = TRUE;
5444 if (!strcmp (name, "Char")) {
5449 if (!strcmp (name, "Double")) {
5451 class->blittable = TRUE;
5455 if (!strcmp (name, "Int32")) {
5457 class->blittable = TRUE;
5458 } else if (!strcmp(name, "Int16")) {
5460 class->blittable = TRUE;
5461 } else if (!strcmp(name, "Int64")) {
5463 class->blittable = TRUE;
5464 } else if (!strcmp(name, "IntPtr")) {
5466 class->blittable = TRUE;
5470 if (!strcmp (name, "Single")) {
5472 class->blittable = TRUE;
5473 } else if (!strcmp(name, "SByte")) {
5475 class->blittable = TRUE;
5479 if (!strcmp (name, "UInt32")) {
5481 class->blittable = TRUE;
5482 } else if (!strcmp(name, "UInt16")) {
5484 class->blittable = TRUE;
5485 } else if (!strcmp(name, "UInt64")) {
5487 class->blittable = TRUE;
5488 } else if (!strcmp(name, "UIntPtr")) {
5490 class->blittable = TRUE;
5494 if (!strcmp (name, "TypedReference")) {
5495 t = MONO_TYPE_TYPEDBYREF;
5496 class->blittable = TRUE;
5500 if (!strcmp (name, "Void")) {
5508 class->this_arg.type = class->byval_arg.type = t;
5511 if (MONO_CLASS_IS_INTERFACE (class))
5512 class->interface_id = mono_get_unique_iid (class);
5518 * COM initialization is delayed until needed.
5519 * However when a [ComImport] attribute is present on a type it will trigger
5520 * the initialization. This is not a problem unless the BCL being executed
5521 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5524 init_com_from_comimport (MonoClass *class)
5526 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5527 if (mono_security_core_clr_enabled ()) {
5528 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5529 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5530 /* but it can not be made available for application (i.e. user code) since all COM calls
5531 * are considered native calls. In this case we fail with a TypeLoadException (just like
5532 * Silverlight 2 does */
5533 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5538 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5540 #endif /*DISABLE_COM*/
5543 * LOCKING: this assumes the loader lock is held
5546 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5548 gboolean system_namespace;
5549 gboolean is_corlib = mono_is_corlib_image (class->image);
5551 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5553 /* if root of the hierarchy */
5554 if (system_namespace && !strcmp (class->name, "Object")) {
5555 class->parent = NULL;
5556 class->instance_size = sizeof (MonoObject);
5559 if (!strcmp (class->name, "<Module>")) {
5560 class->parent = NULL;
5561 class->instance_size = 0;
5565 if (!MONO_CLASS_IS_INTERFACE (class)) {
5566 /* Imported COM Objects always derive from __ComObject. */
5568 if (MONO_CLASS_IS_IMPORT (class)) {
5569 init_com_from_comimport (class);
5570 if (parent == mono_defaults.object_class)
5571 parent = mono_class_get_com_object_class ();
5575 /* set the parent to something useful and safe, but mark the type as broken */
5576 parent = mono_defaults.object_class;
5577 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5580 class->parent = parent;
5582 if (parent->generic_class && !parent->name) {
5584 * If the parent is a generic instance, we may get
5585 * called before it is fully initialized, especially
5586 * before it has its name.
5591 #ifndef DISABLE_REMOTING
5592 class->marshalbyref = parent->marshalbyref;
5593 class->contextbound = parent->contextbound;
5596 class->delegate = parent->delegate;
5598 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5599 mono_class_set_is_com_object (class);
5601 if (system_namespace) {
5602 #ifndef DISABLE_REMOTING
5603 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5604 class->marshalbyref = 1;
5606 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5607 class->contextbound = 1;
5609 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5610 class->delegate = 1;
5613 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5614 (strcmp (class->parent->name_space, "System") == 0)))
5615 class->valuetype = 1;
5616 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5617 class->valuetype = class->enumtype = 1;
5619 /*class->enumtype = class->parent->enumtype; */
5621 /* initialize com types if COM interfaces are present */
5623 if (MONO_CLASS_IS_IMPORT (class))
5624 init_com_from_comimport (class);
5626 class->parent = NULL;
5632 * mono_class_setup_supertypes:
5635 * Build the data structure needed to make fast type checks work.
5636 * This currently sets two fields in @class:
5637 * - idepth: distance between @class and System.Object in the type
5639 * - supertypes: array of classes: each element has a class in the hierarchy
5640 * starting from @class up to System.Object
5642 * LOCKING: This function is atomic, in case of contention we waste memory.
5645 mono_class_setup_supertypes (MonoClass *class)
5648 MonoClass **supertypes;
5650 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5654 if (class->parent && !class->parent->supertypes)
5655 mono_class_setup_supertypes (class->parent);
5657 class->idepth = class->parent->idepth + 1;
5661 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5662 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5664 if (class->parent) {
5665 supertypes [class->idepth - 1] = class;
5666 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5668 supertypes [0] = class;
5671 mono_atomic_store_release (&class->supertypes, supertypes);
5675 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5677 MonoClass *gtd = (MonoClass*)user_data;
5678 /* Only try to fix generic instances of @gtd */
5679 if (gclass->generic_class->container_class != gtd)
5682 /* Check if the generic instance has no parent. */
5683 if (gtd->parent && !gclass->parent)
5684 mono_generic_class_setup_parent (gclass, gtd);
5690 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5692 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5693 mono_error_set_type_load_class (error, class, msg);
5697 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5699 MonoLoaderError *lerror = mono_loader_get_last_error ();
5702 set_failure_from_loader_error (class, lerror);
5703 mono_error_set_from_loader_error (error);
5707 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5708 mono_error_set_type_load_class (error, class, msg);
5713 * mono_class_create_from_typedef:
5714 * @image: image where the token is valid
5715 * @type_token: typedef token
5716 * @error: used to return any error found while creating the type
5718 * Create the MonoClass* representing the specified type token.
5719 * @type_token must be a TypeDef token.
5721 * FIXME: don't return NULL on failure, just the the caller figure it out.
5724 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5726 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5727 MonoClass *class, *parent = NULL;
5728 guint32 cols [MONO_TYPEDEF_SIZE];
5729 guint32 cols_next [MONO_TYPEDEF_SIZE];
5730 guint tidx = mono_metadata_token_index (type_token);
5731 MonoGenericContext *context = NULL;
5732 const char *name, *nspace;
5734 MonoClass **interfaces;
5735 guint32 field_last, method_last;
5736 guint32 nesting_tokeen;
5738 mono_error_init (error);
5740 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5741 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5742 g_assert (!mono_loader_get_last_error ());
5746 mono_loader_lock ();
5748 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5749 mono_loader_unlock ();
5750 g_assert (!mono_loader_get_last_error ());
5754 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5756 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5757 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5759 class = mono_image_alloc0 (image, sizeof (MonoClass));
5762 class->name_space = nspace;
5764 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5766 class->image = image;
5767 class->type_token = type_token;
5768 class->flags = cols [MONO_TYPEDEF_FLAGS];
5770 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5772 classes_size += sizeof (MonoClass);
5775 * Check whether we're a generic type definition.
5777 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5778 if (class->generic_container) {
5779 class->is_generic = 1;
5780 class->generic_container->owner.klass = class;
5781 context = &class->generic_container->context;
5784 if (class->generic_container)
5785 enable_gclass_recording ();
5787 if (cols [MONO_TYPEDEF_EXTENDS]) {
5789 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5791 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5792 /*WARNING: this must satisfy mono_metadata_type_hash*/
5793 class->this_arg.byref = 1;
5794 class->this_arg.data.klass = class;
5795 class->this_arg.type = MONO_TYPE_CLASS;
5796 class->byval_arg.data.klass = class;
5797 class->byval_arg.type = MONO_TYPE_CLASS;
5799 parent = mono_class_get_checked (image, parent_token, error);
5800 if (parent && context) /* Always inflate */
5801 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5803 if (parent == NULL) {
5804 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5805 goto parent_failure;
5808 for (tmp = parent; tmp; tmp = tmp->parent) {
5810 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5811 goto parent_failure;
5813 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5814 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5815 goto parent_failure;
5820 mono_class_setup_parent (class, parent);
5822 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5823 mono_class_setup_mono_type (class);
5825 if (class->generic_container)
5826 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5829 * This might access class->byval_arg for recursion generated by generic constraints,
5830 * so it has to come after setup_mono_type ().
5832 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5833 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5834 if (!mono_error_ok (error)) {
5835 /*FIXME implement a mono_class_set_failure_from_mono_error */
5836 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5837 mono_loader_unlock ();
5838 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5839 g_assert (!mono_loader_get_last_error ());
5844 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5848 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5852 class->cast_class = class->element_class = class;
5854 if (!class->enumtype) {
5855 if (!mono_metadata_interfaces_from_typedef_full (
5856 image, type_token, &interfaces, &icount, FALSE, context, error)){
5858 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5859 mono_loader_unlock ();
5860 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5864 class->interfaces = interfaces;
5865 class->interface_count = icount;
5866 class->interfaces_inited = 1;
5869 /*g_print ("Load class %s\n", name);*/
5872 * Compute the field and method lists
5874 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5875 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5877 if (tt->rows > tidx){
5878 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5879 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5880 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5882 field_last = image->tables [MONO_TABLE_FIELD].rows;
5883 method_last = image->tables [MONO_TABLE_METHOD].rows;
5886 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5887 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5888 class->field.count = field_last - class->field.first;
5890 class->field.count = 0;
5892 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5893 class->method.count = method_last - class->method.first;
5895 class->method.count = 0;
5897 /* reserve space to store vector pointer in arrays */
5898 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5899 class->instance_size += 2 * sizeof (gpointer);
5900 g_assert (class->field.count == 0);
5903 if (class->enumtype) {
5904 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5905 if (!enum_basetype) {
5906 /*set it to a default value as the whole runtime can't handle this to be null*/
5907 class->cast_class = class->element_class = mono_defaults.int32_class;
5908 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5909 mono_loader_unlock ();
5910 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5911 g_assert (!mono_loader_get_last_error ());
5914 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5918 * If we're a generic type definition, load the constraints.
5919 * We must do this after the class has been constructed to make certain recursive scenarios
5922 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5923 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)));
5924 mono_loader_unlock ();
5925 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5926 g_assert (!mono_loader_get_last_error ());
5930 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5931 if (!strncmp (name, "Vector", 6))
5932 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");
5935 mono_loader_unlock ();
5937 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5938 g_assert (!mono_loader_get_last_error ());
5943 mono_class_setup_mono_type (class);
5944 mono_loader_unlock ();
5945 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5946 g_assert (!mono_loader_get_last_error ());
5950 /** is klass Nullable<T>? */
5952 mono_class_is_nullable (MonoClass *klass)
5954 return klass->generic_class != NULL &&
5955 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5959 /** if klass is T? return T */
5961 mono_class_get_nullable_param (MonoClass *klass)
5963 g_assert (mono_class_is_nullable (klass));
5964 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5968 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5972 MonoGenericClass *gclass = klass->generic_class;
5974 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5975 if (!mono_error_ok (&error)) {
5976 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5977 klass->parent = mono_defaults.object_class;
5978 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5979 mono_error_cleanup (&error);
5983 mono_class_setup_parent (klass, klass->parent);
5985 if (klass->enumtype) {
5986 klass->cast_class = gtd->cast_class;
5987 klass->element_class = gtd->element_class;
5993 * Create the `MonoClass' for an instantiation of a generic type.
5994 * We only do this if we actually need it.
5997 mono_generic_class_get_class (MonoGenericClass *gclass)
5999 MonoClass *klass, *gklass;
6001 if (gclass->cached_class)
6002 return gclass->cached_class;
6004 mono_loader_lock ();
6005 if (gclass->cached_class) {
6006 mono_loader_unlock ();
6007 return gclass->cached_class;
6010 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6012 gklass = gclass->container_class;
6014 if (record_gclass_instantiation > 0)
6015 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6017 if (gklass->nested_in) {
6018 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6019 klass->nested_in = gklass->nested_in;
6022 klass->name = gklass->name;
6023 klass->name_space = gklass->name_space;
6025 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6027 klass->image = gklass->image;
6028 klass->flags = gklass->flags;
6029 klass->type_token = gklass->type_token;
6030 klass->field.count = gklass->field.count;
6032 klass->is_inflated = 1;
6033 klass->generic_class = gclass;
6035 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6036 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6037 klass->this_arg.byref = TRUE;
6038 klass->enumtype = gklass->enumtype;
6039 klass->valuetype = gklass->valuetype;
6041 klass->cast_class = klass->element_class = klass;
6043 if (mono_class_is_nullable (klass))
6044 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6047 * We're not interested in the nested classes of a generic instance.
6048 * We use the generic type definition to look for nested classes.
6051 mono_generic_class_setup_parent (klass, gklass);
6053 if (gclass->is_dynamic) {
6055 * 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.
6056 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6057 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6059 if (!gklass->wastypebuilder)
6062 mono_class_setup_supertypes (klass);
6064 if (klass->enumtype) {
6066 * For enums, gklass->fields might not been set, but instance_size etc. is
6067 * already set in mono_reflection_create_internal_class (). For non-enums,
6068 * these will be computed normally in mono_class_layout_fields ().
6070 klass->instance_size = gklass->instance_size;
6071 klass->sizes.class_size = gklass->sizes.class_size;
6072 mono_memory_barrier ();
6073 klass->size_inited = 1;
6077 mono_memory_barrier ();
6078 gclass->cached_class = klass;
6080 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6082 inflated_classes ++;
6083 inflated_classes_size += sizeof (MonoClass);
6085 mono_loader_unlock ();
6091 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6093 MonoClass *klass, **ptr;
6095 MonoGenericContainer *container = mono_generic_param_owner (param);
6099 image = mono_defaults.corlib;
6101 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6102 classes_size += sizeof (MonoClass);
6105 klass->name = pinfo->name;
6107 int n = mono_generic_param_num (param);
6108 klass->name = mono_image_alloc0 (image, 16);
6109 sprintf ((char*)klass->name, "%d", n);
6114 MonoMethod *omethod = container->owner.method;
6115 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6117 MonoClass *oklass = container->owner.klass;
6118 klass->name_space = oklass ? oklass->name_space : "";
6121 klass->name_space = "";
6124 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6128 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6132 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6133 klass->parent = pinfo->constraints [0];
6135 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6136 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6138 klass->parent = mono_defaults.object_class;
6141 if (count - pos > 0) {
6142 klass->interface_count = count - pos;
6143 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6144 klass->interfaces_inited = TRUE;
6145 for (i = pos; i < count; i++)
6146 klass->interfaces [i - pos] = pinfo->constraints [i];
6149 klass->image = image;
6151 klass->inited = TRUE;
6152 klass->cast_class = klass->element_class = klass;
6153 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6155 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6156 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6157 klass->this_arg.byref = TRUE;
6159 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6160 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6162 /*Init these fields to sane values*/
6163 klass->min_align = 1;
6165 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6166 * constrained to, the JIT depends on this.
6168 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6169 mono_memory_barrier ();
6170 klass->size_inited = 1;
6171 klass->setup_fields_called = 1;
6173 mono_class_setup_supertypes (klass);
6175 if (count - pos > 0) {
6176 mono_class_setup_vtable (klass->parent);
6177 if (klass->parent->exception_type)
6178 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6180 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6186 #define FAST_CACHE_SIZE 16
6189 * LOCKING: Takes the image lock depending on @take_lock.
6192 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6194 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6195 MonoImage *image = param->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 MonoClass *klass = NULL;
6207 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6210 mono_image_lock (image);
6211 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6213 mono_image_unlock (image);
6220 * LOCKING: Image lock (param->image) must be held
6223 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6225 int n = mono_generic_param_num (param) | ((guint32)param->gshared_constraint << 16);
6226 MonoImage *image = param->image;
6230 if (n < FAST_CACHE_SIZE) {
6232 /* Requires locking to avoid droping an already published class */
6233 if (!image->mvar_cache_fast)
6234 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6235 image->mvar_cache_fast [n] = klass;
6237 if (!image->var_cache_fast)
6238 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6239 image->var_cache_fast [n] = klass;
6242 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6244 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6246 ht = g_hash_table_new (NULL, NULL);
6247 mono_memory_barrier ();
6249 image->mvar_cache_slow = ht;
6251 image->var_cache_slow = ht;
6254 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6259 * LOCKING: Acquires the image lock (@image).
6262 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6264 MonoGenericContainer *container = mono_generic_param_owner (param);
6265 MonoGenericParamInfo *pinfo = NULL;
6266 MonoClass *klass, *klass2;
6269 pinfo = mono_generic_param_info (param);
6270 klass = pinfo->pklass;
6273 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6278 if (!image && container) {
6280 MonoMethod *method = container->owner.method;
6281 image = (method && method->klass) ? method->klass->image : NULL;
6283 MonoClass *klass = container->owner.klass;
6284 // FIXME: 'klass' should not be null
6285 // But, monodis creates GenericContainers without associating a owner to it
6286 image = klass ? klass->image : NULL;
6290 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6292 mono_memory_barrier ();
6294 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6295 image = mono_defaults.corlib;
6297 mono_image_lock (image);
6299 klass2 = pinfo->pklass;
6301 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6307 pinfo->pklass = klass;
6309 set_anon_gparam_class (param, is_mvar, klass);
6311 mono_image_unlock (image);
6313 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6315 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6317 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6323 mono_ptr_class_get (MonoType *type)
6326 MonoClass *el_class;
6330 el_class = mono_class_from_mono_type (type);
6331 image = el_class->image;
6333 mono_image_lock (image);
6334 if (image->ptr_cache) {
6335 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6336 mono_image_unlock (image);
6340 mono_image_unlock (image);
6342 result = mono_image_alloc0 (image, sizeof (MonoClass));
6344 classes_size += sizeof (MonoClass);
6346 result->parent = NULL; /* no parent for PTR types */
6347 result->name_space = el_class->name_space;
6348 name = g_strdup_printf ("%s*", el_class->name);
6349 result->name = mono_image_strdup (image, name);
6352 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6354 result->image = el_class->image;
6355 result->inited = TRUE;
6356 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6357 /* Can pointers get boxed? */
6358 result->instance_size = sizeof (gpointer);
6359 result->cast_class = result->element_class = el_class;
6360 result->blittable = TRUE;
6362 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6363 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6364 result->this_arg.byref = TRUE;
6366 mono_class_setup_supertypes (result);
6368 mono_image_lock (image);
6369 if (image->ptr_cache) {
6371 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6372 mono_image_unlock (image);
6373 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6377 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6379 g_hash_table_insert (image->ptr_cache, el_class, result);
6380 mono_image_unlock (image);
6382 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6388 mono_fnptr_class_get (MonoMethodSignature *sig)
6391 static GHashTable *ptr_hash = NULL;
6393 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6395 mono_loader_lock ();
6398 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6400 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6401 mono_loader_unlock ();
6404 result = g_new0 (MonoClass, 1);
6406 result->parent = NULL; /* no parent for PTR types */
6407 result->name_space = "System";
6408 result->name = "MonoFNPtrFakeClass";
6410 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6412 result->image = mono_defaults.corlib; /* need to fix... */
6413 result->inited = TRUE;
6414 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6415 /* Can pointers get boxed? */
6416 result->instance_size = sizeof (gpointer);
6417 result->cast_class = result->element_class = result;
6418 result->blittable = TRUE;
6420 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6421 result->this_arg.data.method = result->byval_arg.data.method = sig;
6422 result->this_arg.byref = TRUE;
6423 result->blittable = TRUE;
6425 mono_class_setup_supertypes (result);
6427 g_hash_table_insert (ptr_hash, sig, result);
6429 mono_loader_unlock ();
6431 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6437 mono_class_from_mono_type (MonoType *type)
6439 switch (type->type) {
6440 case MONO_TYPE_OBJECT:
6441 return type->data.klass? type->data.klass: mono_defaults.object_class;
6442 case MONO_TYPE_VOID:
6443 return type->data.klass? type->data.klass: mono_defaults.void_class;
6444 case MONO_TYPE_BOOLEAN:
6445 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6446 case MONO_TYPE_CHAR:
6447 return type->data.klass? type->data.klass: mono_defaults.char_class;
6449 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6451 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6453 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6455 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6457 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6459 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6461 return type->data.klass? type->data.klass: mono_defaults.int_class;
6463 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6465 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6467 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6469 return type->data.klass? type->data.klass: mono_defaults.single_class;
6471 return type->data.klass? type->data.klass: mono_defaults.double_class;
6472 case MONO_TYPE_STRING:
6473 return type->data.klass? type->data.klass: mono_defaults.string_class;
6474 case MONO_TYPE_TYPEDBYREF:
6475 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6476 case MONO_TYPE_ARRAY:
6477 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6479 return mono_ptr_class_get (type->data.type);
6480 case MONO_TYPE_FNPTR:
6481 return mono_fnptr_class_get (type->data.method);
6482 case MONO_TYPE_SZARRAY:
6483 return mono_array_class_get (type->data.klass, 1);
6484 case MONO_TYPE_CLASS:
6485 case MONO_TYPE_VALUETYPE:
6486 return type->data.klass;
6487 case MONO_TYPE_GENERICINST:
6488 return mono_generic_class_get_class (type->data.generic_class);
6490 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6491 case MONO_TYPE_MVAR:
6492 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6494 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6495 g_assert_not_reached ();
6502 * mono_type_retrieve_from_typespec
6503 * @image: context where the image is created
6504 * @type_spec: typespec token
6505 * @context: the generic context used to evaluate generic instantiations in
6508 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6510 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6512 *did_inflate = FALSE;
6517 if (context && (context->class_inst || context->method_inst)) {
6518 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6520 if (!mono_error_ok (error)) {
6521 g_assert (!mono_loader_get_last_error ());
6527 *did_inflate = TRUE;
6534 * mono_class_create_from_typespec
6535 * @image: context where the image is created
6536 * @type_spec: typespec token
6537 * @context: the generic context used to evaluate generic instantiations in
6540 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6543 gboolean inflated = FALSE;
6544 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6545 if (!mono_error_ok (error))
6547 ret = mono_class_from_mono_type (t);
6549 mono_metadata_free_type (t);
6554 * mono_bounded_array_class_get:
6555 * @element_class: element class
6556 * @rank: the dimension of the array class
6557 * @bounded: whenever the array has non-zero bounds
6559 * Returns: a class object describing the array with element type @element_type and
6563 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6567 MonoClass *parent = NULL;
6568 GSList *list, *rootlist = NULL;
6571 gboolean corlib_type = FALSE;
6573 g_assert (rank <= 255);
6576 /* bounded only matters for one-dimensional arrays */
6579 image = eclass->image;
6581 if (rank == 1 && !bounded) {
6583 * This case is very frequent not just during compilation because of calls
6584 * from mono_class_from_mono_type (), mono_array_new (),
6585 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6587 mono_mutex_lock (&image->szarray_cache_lock);
6588 if (!image->szarray_cache)
6589 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6590 class = g_hash_table_lookup (image->szarray_cache, eclass);
6591 mono_mutex_unlock (&image->szarray_cache_lock);
6595 mono_loader_lock ();
6597 mono_loader_lock ();
6599 if (!image->array_cache)
6600 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6602 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6603 for (; list; list = list->next) {
6605 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6606 mono_loader_unlock ();
6613 /* for the building corlib use System.Array from it */
6614 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6615 parent = mono_class_from_name (image, "System", "Array");
6618 parent = mono_defaults.array_class;
6619 if (!parent->inited)
6620 mono_class_init (parent);
6623 class = mono_image_alloc0 (image, sizeof (MonoClass));
6625 class->image = image;
6626 class->name_space = eclass->name_space;
6627 nsize = strlen (eclass->name);
6628 name = g_malloc (nsize + 2 + rank + 1);
6629 memcpy (name, eclass->name, nsize);
6632 memset (name + nsize + 1, ',', rank - 1);
6634 name [nsize + rank] = '*';
6635 name [nsize + rank + bounded] = ']';
6636 name [nsize + rank + bounded + 1] = 0;
6637 class->name = mono_image_strdup (image, name);
6640 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6642 classes_size += sizeof (MonoClass);
6644 class->type_token = 0;
6645 /* all arrays are marked serializable and sealed, bug #42779 */
6646 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6647 class->parent = parent;
6648 class->instance_size = mono_class_instance_size (class->parent);
6650 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6651 /*Arrays of those two types are invalid.*/
6652 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6653 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6654 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6655 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6656 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6658 /* element_size -1 is ok as this is not an instantitable type*/
6659 class->sizes.element_size = -1;
6661 class->sizes.element_size = mono_class_array_element_size (eclass);
6663 mono_class_setup_supertypes (class);
6665 if (eclass->generic_class)
6666 mono_class_init (eclass);
6667 if (!eclass->size_inited)
6668 mono_class_setup_fields (eclass);
6669 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6672 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6676 if (eclass->enumtype)
6677 class->cast_class = eclass->element_class;
6679 class->cast_class = eclass;
6681 switch (class->cast_class->byval_arg.type) {
6683 class->cast_class = mono_defaults.byte_class;
6686 class->cast_class = mono_defaults.int16_class;
6689 #if SIZEOF_VOID_P == 4
6693 class->cast_class = mono_defaults.int32_class;
6696 #if SIZEOF_VOID_P == 8
6700 class->cast_class = mono_defaults.int64_class;
6706 class->element_class = eclass;
6708 if ((rank > 1) || bounded) {
6709 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6710 class->byval_arg.type = MONO_TYPE_ARRAY;
6711 class->byval_arg.data.array = at;
6712 at->eklass = eclass;
6714 /* FIXME: complete.... */
6716 class->byval_arg.type = MONO_TYPE_SZARRAY;
6717 class->byval_arg.data.klass = eclass;
6719 class->this_arg = class->byval_arg;
6720 class->this_arg.byref = 1;
6725 class->generic_container = eclass->generic_container;
6727 if (rank == 1 && !bounded) {
6728 MonoClass *prev_class;
6730 mono_mutex_lock (&image->szarray_cache_lock);
6731 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6733 /* Someone got in before us */
6736 g_hash_table_insert (image->szarray_cache, eclass, class);
6737 mono_mutex_unlock (&image->szarray_cache_lock);
6739 list = g_slist_append (rootlist, class);
6740 g_hash_table_insert (image->array_cache, eclass, list);
6743 mono_loader_unlock ();
6745 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6751 * mono_array_class_get:
6752 * @element_class: element class
6753 * @rank: the dimension of the array class
6755 * Returns: a class object describing the array with element type @element_type and
6759 mono_array_class_get (MonoClass *eclass, guint32 rank)
6761 return mono_bounded_array_class_get (eclass, rank, FALSE);
6765 * mono_class_instance_size:
6768 * Returns: the size of an object instance
6771 mono_class_instance_size (MonoClass *klass)
6773 if (!klass->size_inited)
6774 mono_class_init (klass);
6776 return klass->instance_size;
6780 * mono_class_min_align:
6783 * Returns: minimm alignment requirements
6786 mono_class_min_align (MonoClass *klass)
6788 if (!klass->size_inited)
6789 mono_class_init (klass);
6791 return klass->min_align;
6795 * mono_class_value_size:
6798 * This function is used for value types, and return the
6799 * space and the alignment to store that kind of value object.
6801 * Returns: the size of a value of kind @klass
6804 mono_class_value_size (MonoClass *klass, guint32 *align)
6808 /* fixme: check disable, because we still have external revereces to
6809 * mscorlib and Dummy Objects
6811 /*g_assert (klass->valuetype);*/
6813 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6816 *align = klass->min_align;
6822 * mono_class_data_size:
6825 * Returns: the size of the static class data
6828 mono_class_data_size (MonoClass *klass)
6831 mono_class_init (klass);
6832 /* This can happen with dynamically created types */
6833 if (!klass->fields_inited)
6834 mono_class_setup_fields_locking (klass);
6836 /* in arrays, sizes.class_size is unioned with element_size
6837 * and arrays have no static fields
6841 return klass->sizes.class_size;
6845 * Auxiliary routine to mono_class_get_field
6847 * Takes a field index instead of a field token.
6849 static MonoClassField *
6850 mono_class_get_field_idx (MonoClass *class, int idx)
6852 mono_class_setup_fields_locking (class);
6853 if (class->exception_type)
6857 if (class->image->uncompressed_metadata) {
6859 * class->field.first points to the FieldPtr table, while idx points into the
6860 * Field table, so we have to do a search.
6862 /*FIXME this is broken for types with multiple fields with the same name.*/
6863 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6866 for (i = 0; i < class->field.count; ++i)
6867 if (mono_field_get_name (&class->fields [i]) == name)
6868 return &class->fields [i];
6869 g_assert_not_reached ();
6871 if (class->field.count) {
6872 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6873 return &class->fields [idx - class->field.first];
6877 class = class->parent;
6883 * mono_class_get_field:
6884 * @class: the class to lookup the field.
6885 * @field_token: the field token
6887 * Returns: A MonoClassField representing the type and offset of
6888 * the field, or a NULL value if the field does not belong to this
6892 mono_class_get_field (MonoClass *class, guint32 field_token)
6894 int idx = mono_metadata_token_index (field_token);
6896 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6898 return mono_class_get_field_idx (class, idx - 1);
6902 * mono_class_get_field_from_name:
6903 * @klass: the class to lookup the field.
6904 * @name: the field name
6906 * Search the class @klass and it's parents for a field with the name @name.
6908 * Returns: the MonoClassField pointer of the named field or NULL
6911 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6913 return mono_class_get_field_from_name_full (klass, name, NULL);
6917 * mono_class_get_field_from_name_full:
6918 * @klass: the class to lookup the field.
6919 * @name: the field name
6920 * @type: the type of the fields. This optional.
6922 * Search the class @klass and it's parents for a field with the name @name and type @type.
6924 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6925 * of its generic type definition.
6927 * Returns: the MonoClassField pointer of the named field or NULL
6930 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6934 mono_class_setup_fields_locking (klass);
6935 if (klass->exception_type)
6939 for (i = 0; i < klass->field.count; ++i) {
6940 MonoClassField *field = &klass->fields [i];
6942 if (strcmp (name, mono_field_get_name (field)) != 0)
6946 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6947 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6952 klass = klass->parent;
6958 * mono_class_get_field_token:
6959 * @field: the field we need the token of
6961 * Get the token of a field. Note that the tokesn is only valid for the image
6962 * the field was loaded from. Don't use this function for fields in dynamic types.
6964 * Returns: the token representing the field in the image it was loaded from.
6967 mono_class_get_field_token (MonoClassField *field)
6969 MonoClass *klass = field->parent;
6972 mono_class_setup_fields_locking (klass);
6977 for (i = 0; i < klass->field.count; ++i) {
6978 if (&klass->fields [i] == field) {
6979 int idx = klass->field.first + i + 1;
6981 if (klass->image->uncompressed_metadata)
6982 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6983 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6986 klass = klass->parent;
6989 g_assert_not_reached ();
6994 mono_field_get_index (MonoClassField *field)
6996 int index = field - field->parent->fields;
6998 g_assert (index >= 0 && index < field->parent->field.count);
7004 * mono_class_get_field_default_value:
7006 * Return the default value of the field as a pointer into the metadata blob.
7009 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7012 guint32 constant_cols [MONO_CONSTANT_SIZE];
7014 MonoClass *klass = field->parent;
7016 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7018 if (!klass->ext || !klass->ext->field_def_values) {
7019 MonoFieldDefaultValue *def_values;
7021 mono_class_alloc_ext (klass);
7023 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7025 mono_image_lock (klass->image);
7026 mono_memory_barrier ();
7027 if (!klass->ext->field_def_values)
7028 klass->ext->field_def_values = def_values;
7029 mono_image_unlock (klass->image);
7032 field_index = mono_field_get_index (field);
7034 if (!klass->ext->field_def_values [field_index].data) {
7035 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7039 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7041 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7042 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7043 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7046 *def_type = klass->ext->field_def_values [field_index].def_type;
7047 return klass->ext->field_def_values [field_index].data;
7051 mono_property_get_index (MonoProperty *prop)
7053 int index = prop - prop->parent->ext->properties;
7055 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7061 * mono_class_get_property_default_value:
7063 * Return the default value of the field as a pointer into the metadata blob.
7066 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7069 guint32 constant_cols [MONO_CONSTANT_SIZE];
7070 MonoClass *klass = property->parent;
7072 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7074 * We don't cache here because it is not used by C# so it's quite rare, but
7075 * we still do the lookup in klass->ext because that is where the data
7076 * is stored for dynamic assemblies.
7079 if (image_is_dynamic (klass->image)) {
7080 int prop_index = mono_property_get_index (property);
7081 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7082 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7083 return klass->ext->prop_def_values [prop_index].data;
7087 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7091 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7092 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7093 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7097 mono_class_get_event_token (MonoEvent *event)
7099 MonoClass *klass = event->parent;
7104 for (i = 0; i < klass->ext->event.count; ++i) {
7105 if (&klass->ext->events [i] == event)
7106 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7109 klass = klass->parent;
7112 g_assert_not_reached ();
7117 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7121 gpointer iter = NULL;
7122 while ((p = mono_class_get_properties (klass, &iter))) {
7123 if (! strcmp (name, p->name))
7126 klass = klass->parent;
7132 mono_class_get_property_token (MonoProperty *prop)
7134 MonoClass *klass = prop->parent;
7138 gpointer iter = NULL;
7139 while ((p = mono_class_get_properties (klass, &iter))) {
7140 if (&klass->ext->properties [i] == prop)
7141 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7145 klass = klass->parent;
7148 g_assert_not_reached ();
7153 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7155 const char *name, *nspace;
7156 if (image_is_dynamic (image))
7157 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7159 switch (type_token & 0xff000000){
7160 case MONO_TOKEN_TYPE_DEF: {
7161 guint32 cols [MONO_TYPEDEF_SIZE];
7162 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7163 guint tidx = mono_metadata_token_index (type_token);
7165 if (tidx > tt->rows)
7166 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7168 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7169 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7170 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7171 if (strlen (nspace) == 0)
7172 return g_strdup_printf ("%s", name);
7174 return g_strdup_printf ("%s.%s", nspace, name);
7177 case MONO_TOKEN_TYPE_REF: {
7179 guint32 cols [MONO_TYPEREF_SIZE];
7180 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7181 guint tidx = mono_metadata_token_index (type_token);
7184 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7186 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7187 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7188 mono_error_cleanup (&error);
7192 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7193 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7194 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7195 if (strlen (nspace) == 0)
7196 return g_strdup_printf ("%s", name);
7198 return g_strdup_printf ("%s.%s", nspace, name);
7201 case MONO_TOKEN_TYPE_SPEC:
7202 return g_strdup_printf ("Typespec 0x%08x", type_token);
7204 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7209 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7211 if (image_is_dynamic (image))
7212 return g_strdup_printf ("DynamicAssembly %s", image->name);
7214 switch (type_token & 0xff000000){
7215 case MONO_TOKEN_TYPE_DEF:
7216 if (image->assembly)
7217 return mono_stringify_assembly_name (&image->assembly->aname);
7218 else if (image->assembly_name)
7219 return g_strdup (image->assembly_name);
7220 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7221 case MONO_TOKEN_TYPE_REF: {
7223 MonoAssemblyName aname;
7224 guint32 cols [MONO_TYPEREF_SIZE];
7225 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7226 guint32 idx = mono_metadata_token_index (type_token);
7229 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7231 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7232 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7233 mono_error_cleanup (&error);
7236 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7238 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7239 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7240 case MONO_RESOLUTION_SCOPE_MODULE:
7242 return g_strdup ("");
7243 case MONO_RESOLUTION_SCOPE_MODULEREF:
7245 return g_strdup ("");
7246 case MONO_RESOLUTION_SCOPE_TYPEREF:
7248 return g_strdup ("");
7249 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7250 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7251 return mono_stringify_assembly_name (&aname);
7253 g_assert_not_reached ();
7257 case MONO_TOKEN_TYPE_SPEC:
7259 return g_strdup ("");
7261 g_assert_not_reached ();
7268 * mono_class_get_full:
7269 * @image: the image where the class resides
7270 * @type_token: the token for the class
7271 * @context: the generic context used to evaluate generic instantiations in
7272 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7274 * Returns: the MonoClass that represents @type_token in @image
7277 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7281 class = mono_class_get_checked (image, type_token, &error);
7283 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7284 class = mono_class_inflate_generic_class_checked (class, context, &error);
7286 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7292 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7296 mono_error_init (error);
7297 class = mono_class_get_checked (image, type_token, error);
7299 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7300 class = mono_class_inflate_generic_class_checked (class, context, error);
7305 * mono_class_get_checked:
7306 * @image: the image where the class resides
7307 * @type_token: the token for the class
7308 * @error: error object to return any error
7310 * Returns: the MonoClass that represents @type_token in @image
7313 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7315 MonoClass *class = NULL;
7317 mono_error_init (error);
7319 if (image_is_dynamic (image)) {
7320 int table = mono_metadata_token_table (type_token);
7322 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7323 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7326 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7330 switch (type_token & 0xff000000){
7331 case MONO_TOKEN_TYPE_DEF:
7332 class = mono_class_create_from_typedef (image, type_token, error);
7334 case MONO_TOKEN_TYPE_REF:
7335 class = mono_class_from_typeref_checked (image, type_token, error);
7337 case MONO_TOKEN_TYPE_SPEC:
7338 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7341 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7345 /* Generic case, should be avoided for when a better error is possible. */
7346 if (!class && mono_error_ok (error)) {
7347 char *name = mono_class_name_from_token (image, type_token);
7348 char *assembly = mono_assembly_name_from_token (image, type_token);
7349 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7357 * mono_type_get_checked:
7358 * @image: the image where the type resides
7359 * @type_token: the token for the type
7360 * @context: the generic context used to evaluate generic instantiations in
7361 * @error: Error handling context
7363 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7365 * Returns: the MonoType that represents @type_token in @image
7368 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7370 MonoType *type = NULL;
7371 gboolean inflated = FALSE;
7373 mono_error_init (error);
7375 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7376 if (image_is_dynamic (image))
7377 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7379 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7380 MonoClass *class = mono_class_get_checked (image, type_token, error);
7383 g_assert (!mono_loader_get_last_error ());
7388 return mono_class_get_type (class);
7391 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7394 g_assert (!mono_loader_get_last_error ());
7399 MonoType *tmp = type;
7400 type = mono_class_get_type (mono_class_from_mono_type (type));
7401 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7402 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7403 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7405 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7407 if (type->type != tmp->type)
7410 mono_metadata_free_type (tmp);
7417 mono_class_get (MonoImage *image, guint32 type_token)
7419 return mono_class_get_full (image, type_token, NULL);
7423 * mono_image_init_name_cache:
7425 * Initializes the class name cache stored in image->name_cache.
7427 * LOCKING: Acquires the corresponding image lock.
7430 mono_image_init_name_cache (MonoImage *image)
7432 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7433 guint32 cols [MONO_TYPEDEF_SIZE];
7436 guint32 i, visib, nspace_index;
7437 GHashTable *name_cache2, *nspace_table;
7439 mono_image_lock (image);
7441 if (image->name_cache) {
7442 mono_image_unlock (image);
7446 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7448 if (image_is_dynamic (image)) {
7449 mono_image_unlock (image);
7453 /* Temporary hash table to avoid lookups in the nspace_table */
7454 name_cache2 = g_hash_table_new (NULL, NULL);
7456 for (i = 1; i <= t->rows; ++i) {
7457 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7458 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7460 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7461 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7463 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7465 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7466 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7468 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7469 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7470 if (!nspace_table) {
7471 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7472 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7473 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7476 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7479 /* Load type names from EXPORTEDTYPES table */
7481 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7482 guint32 cols [MONO_EXP_TYPE_SIZE];
7485 for (i = 0; i < t->rows; ++i) {
7486 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7487 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7488 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7490 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7491 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7492 if (!nspace_table) {
7493 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7494 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7495 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7498 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7502 g_hash_table_destroy (name_cache2);
7503 mono_image_unlock (image);
7506 /*FIXME Only dynamic assemblies should allow this operation.*/
7508 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7509 const char *name, guint32 index)
7511 GHashTable *nspace_table;
7512 GHashTable *name_cache;
7515 mono_image_lock (image);
7517 if (!image->name_cache)
7518 mono_image_init_name_cache (image);
7520 name_cache = image->name_cache;
7521 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7522 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7523 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7526 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7527 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7529 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7531 mono_image_unlock (image);
7540 find_nocase (gpointer key, gpointer value, gpointer user_data)
7542 char *name = (char*)key;
7543 FindUserData *data = (FindUserData*)user_data;
7545 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7546 data->value = value;
7550 * mono_class_from_name_case:
7551 * @image: The MonoImage where the type is looked up in
7552 * @name_space: the type namespace
7553 * @name: the type short name.
7554 * @deprecated: use the _checked variant
7556 * Obtains a MonoClass with a given namespace and a given name which
7557 * is located in the given MonoImage. The namespace and name
7558 * lookups are case insensitive.
7561 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7564 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7565 g_assert (!mono_error_ok (&error));
7570 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7572 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7573 guint32 cols [MONO_TYPEDEF_SIZE];
7578 mono_error_init (error);
7580 if (image_is_dynamic (image)) {
7582 FindUserData user_data;
7584 mono_image_lock (image);
7586 if (!image->name_cache)
7587 mono_image_init_name_cache (image);
7589 user_data.key = name_space;
7590 user_data.value = NULL;
7591 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7593 if (user_data.value) {
7594 GHashTable *nspace_table = (GHashTable*)user_data.value;
7596 user_data.key = name;
7597 user_data.value = NULL;
7599 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7601 if (user_data.value)
7602 token = GPOINTER_TO_UINT (user_data.value);
7605 mono_image_unlock (image);
7608 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7614 /* add a cache if needed */
7615 for (i = 1; i <= t->rows; ++i) {
7616 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7617 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7619 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7620 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7622 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7624 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7625 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7626 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7627 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7633 return_nested_in (MonoClass *class, char *nested)
7636 char *s = strchr (nested, '/');
7637 gpointer iter = NULL;
7644 while ((found = mono_class_get_nested_types (class, &iter))) {
7645 if (strcmp (found->name, nested) == 0) {
7647 return return_nested_in (found, s);
7655 search_modules (MonoImage *image, const char *name_space, const char *name)
7657 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7658 MonoImage *file_image;
7663 * The EXPORTEDTYPES table only contains public types, so have to search the
7665 * Note: image->modules contains the contents of the MODULEREF table, while
7666 * the real module list is in the FILE table.
7668 for (i = 0; i < file_table->rows; i++) {
7669 guint32 cols [MONO_FILE_SIZE];
7670 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7671 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7674 file_image = mono_image_load_file_for_image (image, i + 1);
7676 class = mono_class_from_name (file_image, name_space, name);
7686 * mono_class_from_name:
7687 * @image: The MonoImage where the type is looked up in
7688 * @name_space: the type namespace
7689 * @name: the type short name.
7691 * Obtains a MonoClass with a given namespace and a given name which
7692 * is located in the given MonoImage.
7694 * To reference nested classes, use the "/" character as a separator.
7695 * For example use "Foo/Bar" to reference the class Bar that is nested
7696 * inside Foo, like this: "class Foo { class Bar {} }".
7699 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7702 GHashTable *nspace_table;
7703 MonoImage *loaded_image;
7710 if ((nested = strchr (name, '/'))) {
7711 int pos = nested - name;
7712 int len = strlen (name);
7715 memcpy (buf, name, len + 1);
7717 nested = buf + pos + 1;
7721 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7722 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7723 gboolean res = get_class_from_name (image, name_space, name, &class);
7726 class = search_modules (image, name_space, name);
7728 return class ? return_nested_in (class, nested) : NULL;
7734 mono_image_lock (image);
7736 if (!image->name_cache)
7737 mono_image_init_name_cache (image);
7739 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7742 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7744 mono_image_unlock (image);
7746 if (!token && image_is_dynamic (image) && image->modules) {
7747 /* Search modules as well */
7748 for (i = 0; i < image->module_count; ++i) {
7749 MonoImage *module = image->modules [i];
7751 class = mono_class_from_name (module, name_space, name);
7758 class = search_modules (image, name_space, name);
7766 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7767 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7768 guint32 cols [MONO_EXP_TYPE_SIZE];
7771 idx = mono_metadata_token_index (token);
7773 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7775 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7776 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7777 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7780 class = mono_class_from_name (loaded_image, name_space, name);
7782 return return_nested_in (class, nested);
7784 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7785 guint32 assembly_idx;
7787 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7789 mono_assembly_load_reference (image, assembly_idx - 1);
7790 g_assert (image->references [assembly_idx - 1]);
7791 if (image->references [assembly_idx - 1] == (gpointer)-1)
7794 /* FIXME: Cycle detection */
7795 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7797 g_error ("not yet implemented");
7801 token = MONO_TOKEN_TYPE_DEF | token;
7803 class = mono_class_get_checked (image, token, &error);
7804 if (!mono_error_ok (&error)) {
7805 mono_loader_set_error_from_mono_error (&error);
7806 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7809 return return_nested_in (class, nested);
7814 * mono_class_is_subclass_of:
7815 * @klass: class to probe if it is a subclass of another one
7816 * @klassc: the class we suspect is the base class
7817 * @check_interfaces: whether we should perform interface checks
7819 * This method determines whether @klass is a subclass of @klassc.
7821 * If the @check_interfaces flag is set, then if @klassc is an interface
7822 * this method return true if the @klass implements the interface or
7823 * if @klass is an interface, if one of its base classes is @klass.
7825 * If @check_interfaces is false then, then if @klass is not an interface
7826 * then it returns true if the @klass is a subclass of @klassc.
7828 * if @klass is an interface and @klassc is System.Object, then this function
7833 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7834 gboolean check_interfaces)
7836 /*FIXME test for interfaces with variant generic arguments*/
7838 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7839 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7841 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7844 for (i = 0; i < klass->interface_count; i ++) {
7845 MonoClass *ic = klass->interfaces [i];
7850 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7855 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7858 if (klassc == mono_defaults.object_class)
7865 mono_type_is_generic_argument (MonoType *type)
7867 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7871 mono_class_has_variant_generic_params (MonoClass *klass)
7874 MonoGenericContainer *container;
7876 if (!klass->generic_class)
7879 container = klass->generic_class->container_class->generic_container;
7881 for (i = 0; i < container->type_argc; ++i)
7882 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7889 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7891 if (target == candidate)
7894 if (check_for_reference_conv &&
7895 mono_type_is_generic_argument (&target->byval_arg) &&
7896 mono_type_is_generic_argument (&candidate->byval_arg)) {
7897 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7898 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7900 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7903 if (!mono_class_is_assignable_from (target, candidate))
7909 * @container the generic container from the GTD
7910 * @klass: the class to be assigned to
7911 * @oklass: the source class
7913 * Both klass and oklass must be instances of the same generic interface.
7914 * Return true if @klass can be assigned to a @klass variable
7917 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7920 MonoType **klass_argv, **oklass_argv;
7921 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7922 MonoGenericContainer *container = klass_gtd->generic_container;
7924 if (klass == oklass)
7927 /*Viable candidates are instances of the same generic interface*/
7928 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7931 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7932 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7934 for (j = 0; j < container->type_argc; ++j) {
7935 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7936 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7938 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7942 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7943 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7945 if (param1_class != param2_class) {
7946 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7947 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7949 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7950 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7960 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7962 MonoGenericParam *gparam, *ogparam;
7963 MonoGenericParamInfo *tinfo, *cinfo;
7964 MonoClass **candidate_class;
7965 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7968 if (target == candidate)
7970 if (target->byval_arg.type != candidate->byval_arg.type)
7973 gparam = target->byval_arg.data.generic_param;
7974 ogparam = candidate->byval_arg.data.generic_param;
7975 tinfo = mono_generic_param_info (gparam);
7976 cinfo = mono_generic_param_info (ogparam);
7978 class_constraint_satisfied = FALSE;
7979 valuetype_constraint_satisfied = FALSE;
7981 /*candidate must have a super set of target's special constraints*/
7982 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7983 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7985 if (cinfo->constraints) {
7986 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7987 MonoClass *cc = *candidate_class;
7989 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7990 class_constraint_satisfied = TRUE;
7991 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7992 valuetype_constraint_satisfied = TRUE;
7995 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7996 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7998 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8000 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8002 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8003 valuetype_constraint_satisfied)) {
8008 /*candidate type constraints must be a superset of target's*/
8009 if (tinfo->constraints) {
8010 MonoClass **target_class;
8011 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8012 MonoClass *tc = *target_class;
8015 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8016 * check it's constraints since it satisfy the constraint by itself.
8018 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8021 if (!cinfo->constraints)
8024 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8025 MonoClass *cc = *candidate_class;
8027 if (mono_class_is_assignable_from (tc, cc))
8031 * This happens when we have the following:
8033 * Bar<K> where K : IFace
8034 * Foo<T, U> where T : U where U : IFace
8036 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8039 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8040 if (mono_gparam_is_assignable_from (target, cc))
8044 if (!*candidate_class)
8049 /*candidate itself must have a constraint that satisfy target*/
8050 if (cinfo->constraints) {
8051 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8052 MonoClass *cc = *candidate_class;
8053 if (mono_class_is_assignable_from (target, cc))
8061 * mono_class_is_assignable_from:
8062 * @klass: the class to be assigned to
8063 * @oklass: the source class
8065 * Return: true if an instance of object oklass can be assigned to an
8066 * instance of object @klass
8069 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8071 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8073 mono_class_init (klass);
8075 if (!oklass->inited)
8076 mono_class_init (oklass);
8078 if (klass->exception_type || oklass->exception_type)
8081 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8082 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8084 return mono_gparam_is_assignable_from (klass, oklass);
8087 if (MONO_CLASS_IS_INTERFACE (klass)) {
8088 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8089 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8090 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8094 for (i = 0; constraints [i]; ++i) {
8095 if (mono_class_is_assignable_from (klass, constraints [i]))
8103 /* interface_offsets might not be set for dynamic classes */
8104 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8106 * oklass might be a generic type parameter but they have
8107 * interface_offsets set.
8109 return mono_reflection_call_is_assignable_to (oklass, klass);
8110 if (!oklass->interface_bitmap)
8111 /* Happens with generic instances of not-yet created dynamic types */
8113 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8116 if (mono_class_has_variant_generic_params (klass)) {
8119 mono_class_setup_interfaces (oklass, &error);
8120 if (!mono_error_ok (&error)) {
8121 mono_error_cleanup (&error);
8125 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8126 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8127 MonoClass *iface = oklass->interfaces_packed [i];
8129 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8134 } else if (klass->delegate) {
8135 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8137 }else if (klass->rank) {
8138 MonoClass *eclass, *eoclass;
8140 if (oklass->rank != klass->rank)
8143 /* vectors vs. one dimensional arrays */
8144 if (oklass->byval_arg.type != klass->byval_arg.type)
8147 eclass = klass->cast_class;
8148 eoclass = oklass->cast_class;
8151 * a is b does not imply a[] is b[] when a is a valuetype, and
8152 * b is a reference type.
8155 if (eoclass->valuetype) {
8156 if ((eclass == mono_defaults.enum_class) ||
8157 (eclass == mono_defaults.enum_class->parent) ||
8158 (eclass == mono_defaults.object_class))
8162 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8163 } else if (mono_class_is_nullable (klass)) {
8164 if (mono_class_is_nullable (oklass))
8165 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8167 return mono_class_is_assignable_from (klass->cast_class, oklass);
8168 } else if (klass == mono_defaults.object_class)
8171 return mono_class_has_parent (oklass, klass);
8174 /*Check if @oklass is variant compatible with @klass.*/
8176 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8179 MonoType **klass_argv, **oklass_argv;
8180 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8181 MonoGenericContainer *container = klass_gtd->generic_container;
8183 /*Viable candidates are instances of the same generic interface*/
8184 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8187 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8188 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8190 for (j = 0; j < container->type_argc; ++j) {
8191 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8192 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8194 if (param1_class->valuetype != param2_class->valuetype)
8198 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8199 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8201 if (param1_class != param2_class) {
8202 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8203 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8205 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8206 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8214 /*Check if @candidate implements the interface @target*/
8216 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8220 gboolean is_variant = mono_class_has_variant_generic_params (target);
8222 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8223 if (mono_class_is_variant_compatible_slow (target, candidate))
8228 if (candidate == target)
8231 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8232 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8233 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8235 if (tb && tb->interfaces) {
8236 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8237 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8238 MonoClass *iface_class;
8240 /* we can't realize the type here since it can do pretty much anything. */
8243 iface_class = mono_class_from_mono_type (iface->type);
8244 if (iface_class == target)
8246 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8248 if (mono_class_implement_interface_slow (target, iface_class))
8253 /*setup_interfaces don't mono_class_init anything*/
8254 /*FIXME this doesn't handle primitive type arrays.
8255 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8256 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8258 mono_class_setup_interfaces (candidate, &error);
8259 if (!mono_error_ok (&error)) {
8260 mono_error_cleanup (&error);
8264 for (i = 0; i < candidate->interface_count; ++i) {
8265 if (candidate->interfaces [i] == target)
8268 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8271 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8275 candidate = candidate->parent;
8276 } while (candidate);
8282 * Check if @oklass can be assigned to @klass.
8283 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8286 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8288 if (candidate == target)
8290 if (target == mono_defaults.object_class)
8293 if (mono_class_has_parent (candidate, target))
8296 /*If target is not an interface there is no need to check them.*/
8297 if (MONO_CLASS_IS_INTERFACE (target))
8298 return mono_class_implement_interface_slow (target, candidate);
8300 if (target->delegate && mono_class_has_variant_generic_params (target))
8301 return mono_class_is_variant_compatible (target, candidate, FALSE);
8304 MonoClass *eclass, *eoclass;
8306 if (target->rank != candidate->rank)
8309 /* vectors vs. one dimensional arrays */
8310 if (target->byval_arg.type != candidate->byval_arg.type)
8313 eclass = target->cast_class;
8314 eoclass = candidate->cast_class;
8317 * a is b does not imply a[] is b[] when a is a valuetype, and
8318 * b is a reference type.
8321 if (eoclass->valuetype) {
8322 if ((eclass == mono_defaults.enum_class) ||
8323 (eclass == mono_defaults.enum_class->parent) ||
8324 (eclass == mono_defaults.object_class))
8328 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8330 /*FIXME properly handle nullables */
8331 /*FIXME properly handle (M)VAR */
8336 * mono_class_get_cctor:
8337 * @klass: A MonoClass pointer
8339 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8342 mono_class_get_cctor (MonoClass *klass)
8344 MonoCachedClassInfo cached_info;
8346 if (image_is_dynamic (klass->image)) {
8348 * has_cctor is not set for these classes because mono_class_init () is
8351 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8354 if (!klass->has_cctor)
8357 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8359 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8360 if (!mono_error_ok (&error))
8361 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8365 if (klass->generic_class && !klass->methods)
8366 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8368 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8372 * mono_class_get_finalizer:
8373 * @klass: The MonoClass pointer
8375 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8378 mono_class_get_finalizer (MonoClass *klass)
8380 MonoCachedClassInfo cached_info;
8383 mono_class_init (klass);
8384 if (!mono_class_has_finalizer (klass))
8387 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8389 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8390 if (!mono_error_ok (&error))
8391 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8394 mono_class_setup_vtable (klass);
8395 return klass->vtable [finalize_slot];
8400 * mono_class_needs_cctor_run:
8401 * @klass: the MonoClass pointer
8402 * @caller: a MonoMethod describing the caller
8404 * Determines whenever the class has a static constructor and whenever it
8405 * needs to be called when executing CALLER.
8408 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8412 method = mono_class_get_cctor (klass);
8414 return (method == caller) ? FALSE : TRUE;
8420 * mono_class_array_element_size:
8423 * Returns: the number of bytes an element of type @klass
8424 * uses when stored into an array.
8427 mono_class_array_element_size (MonoClass *klass)
8429 MonoType *type = &klass->byval_arg;
8432 switch (type->type) {
8435 case MONO_TYPE_BOOLEAN:
8439 case MONO_TYPE_CHAR:
8448 case MONO_TYPE_CLASS:
8449 case MONO_TYPE_STRING:
8450 case MONO_TYPE_OBJECT:
8451 case MONO_TYPE_SZARRAY:
8452 case MONO_TYPE_ARRAY:
8453 return sizeof (gpointer);
8458 case MONO_TYPE_VALUETYPE:
8459 if (type->data.klass->enumtype) {
8460 type = mono_class_enum_basetype (type->data.klass);
8461 klass = klass->element_class;
8464 return mono_class_instance_size (klass) - sizeof (MonoObject);
8465 case MONO_TYPE_GENERICINST:
8466 type = &type->data.generic_class->container_class->byval_arg;
8469 case MONO_TYPE_MVAR: {
8472 return mono_type_size (type, &align);
8474 case MONO_TYPE_VOID:
8478 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8484 * mono_array_element_size:
8485 * @ac: pointer to a #MonoArrayClass
8487 * Returns: the size of single array element.
8490 mono_array_element_size (MonoClass *ac)
8492 g_assert (ac->rank);
8493 return ac->sizes.element_size;
8497 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8498 MonoGenericContext *context)
8501 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8502 g_assert (mono_error_ok (&error));
8507 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8508 MonoGenericContext *context, MonoError *error)
8510 mono_error_init (error);
8512 if (image_is_dynamic (image)) {
8513 MonoClass *tmp_handle_class;
8514 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8516 g_assert (tmp_handle_class);
8518 *handle_class = tmp_handle_class;
8520 if (tmp_handle_class == mono_defaults.typehandle_class)
8521 return &((MonoClass*)obj)->byval_arg;
8526 switch (token & 0xff000000) {
8527 case MONO_TOKEN_TYPE_DEF:
8528 case MONO_TOKEN_TYPE_REF:
8529 case MONO_TOKEN_TYPE_SPEC: {
8532 *handle_class = mono_defaults.typehandle_class;
8533 type = mono_type_get_checked (image, token, context, error);
8537 mono_class_init (mono_class_from_mono_type (type));
8538 /* We return a MonoType* as handle */
8541 case MONO_TOKEN_FIELD_DEF: {
8543 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8545 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8549 *handle_class = mono_defaults.fieldhandle_class;
8550 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8554 mono_class_init (class);
8555 return mono_class_get_field (class, token);
8557 case MONO_TOKEN_METHOD_DEF:
8558 case MONO_TOKEN_METHOD_SPEC: {
8560 meth = mono_get_method_checked (image, token, NULL, context, error);
8562 *handle_class = mono_defaults.methodhandle_class;
8568 case MONO_TOKEN_MEMBER_REF: {
8569 guint32 cols [MONO_MEMBERREF_SIZE];
8571 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8572 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8573 mono_metadata_decode_blob_size (sig, &sig);
8574 if (*sig == 0x6) { /* it's a field */
8576 MonoClassField *field;
8577 field = mono_field_from_token_checked (image, token, &klass, context, error);
8579 *handle_class = mono_defaults.fieldhandle_class;
8583 meth = mono_get_method_checked (image, token, NULL, context, error);
8585 *handle_class = mono_defaults.methodhandle_class;
8590 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8596 * This function might need to call runtime functions so it can't be part
8597 * of the metadata library.
8599 static MonoLookupDynamicToken lookup_dynamic = NULL;
8602 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8604 lookup_dynamic = func;
8608 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8610 MonoClass *handle_class;
8612 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8616 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8618 return lookup_dynamic (image, token, valid_token, handle_class, context);
8621 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8624 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8626 get_cached_class_info = func;
8630 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8632 if (!get_cached_class_info)
8635 return get_cached_class_info (klass, res);
8639 mono_install_get_class_from_name (MonoGetClassFromName func)
8641 get_class_from_name = func;
8645 mono_class_get_image (MonoClass *klass)
8647 return klass->image;
8651 * mono_class_get_element_class:
8652 * @klass: the MonoClass to act on
8654 * Returns: the element class of an array or an enumeration.
8657 mono_class_get_element_class (MonoClass *klass)
8659 return klass->element_class;
8663 * mono_class_is_valuetype:
8664 * @klass: the MonoClass to act on
8666 * Returns: true if the MonoClass represents a ValueType.
8669 mono_class_is_valuetype (MonoClass *klass)
8671 return klass->valuetype;
8675 * mono_class_is_enum:
8676 * @klass: the MonoClass to act on
8678 * Returns: true if the MonoClass represents an enumeration.
8681 mono_class_is_enum (MonoClass *klass)
8683 return klass->enumtype;
8687 * mono_class_enum_basetype:
8688 * @klass: the MonoClass to act on
8690 * Returns: the underlying type representation for an enumeration.
8693 mono_class_enum_basetype (MonoClass *klass)
8695 if (klass->element_class == klass)
8696 /* SRE or broken types */
8699 return &klass->element_class->byval_arg;
8703 * mono_class_get_parent
8704 * @klass: the MonoClass to act on
8706 * Returns: the parent class for this class.
8709 mono_class_get_parent (MonoClass *klass)
8711 return klass->parent;
8715 * mono_class_get_nesting_type;
8716 * @klass: the MonoClass to act on
8718 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8721 mono_class_get_nesting_type (MonoClass *klass)
8723 return klass->nested_in;
8727 * mono_class_get_rank:
8728 * @klass: the MonoClass to act on
8730 * Returns: the rank for the array (the number of dimensions).
8733 mono_class_get_rank (MonoClass *klass)
8739 * mono_class_get_flags:
8740 * @klass: the MonoClass to act on
8742 * The type flags from the TypeDef table from the metadata.
8743 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8746 * Returns: the flags from the TypeDef table.
8749 mono_class_get_flags (MonoClass *klass)
8751 return klass->flags;
8755 * mono_class_get_name
8756 * @klass: the MonoClass to act on
8758 * Returns: the name of the class.
8761 mono_class_get_name (MonoClass *klass)
8767 * mono_class_get_namespace:
8768 * @klass: the MonoClass to act on
8770 * Returns: the namespace of the class.
8773 mono_class_get_namespace (MonoClass *klass)
8775 return klass->name_space;
8779 * mono_class_get_type:
8780 * @klass: the MonoClass to act on
8782 * This method returns the internal Type representation for the class.
8784 * Returns: the MonoType from the class.
8787 mono_class_get_type (MonoClass *klass)
8789 return &klass->byval_arg;
8793 * mono_class_get_type_token
8794 * @klass: the MonoClass to act on
8796 * This method returns type token for the class.
8798 * Returns: the type token for the class.
8801 mono_class_get_type_token (MonoClass *klass)
8803 return klass->type_token;
8807 * mono_class_get_byref_type:
8808 * @klass: the MonoClass to act on
8813 mono_class_get_byref_type (MonoClass *klass)
8815 return &klass->this_arg;
8819 * mono_class_num_fields:
8820 * @klass: the MonoClass to act on
8822 * Returns: the number of static and instance fields in the class.
8825 mono_class_num_fields (MonoClass *klass)
8827 return klass->field.count;
8831 * mono_class_num_methods:
8832 * @klass: the MonoClass to act on
8834 * Returns: the number of methods in the class.
8837 mono_class_num_methods (MonoClass *klass)
8839 return klass->method.count;
8843 * mono_class_num_properties
8844 * @klass: the MonoClass to act on
8846 * Returns: the number of properties in the class.
8849 mono_class_num_properties (MonoClass *klass)
8851 mono_class_setup_properties (klass);
8853 return klass->ext->property.count;
8857 * mono_class_num_events:
8858 * @klass: the MonoClass to act on
8860 * Returns: the number of events in the class.
8863 mono_class_num_events (MonoClass *klass)
8865 mono_class_setup_events (klass);
8867 return klass->ext->event.count;
8871 * mono_class_get_fields:
8872 * @klass: the MonoClass to act on
8874 * This routine is an iterator routine for retrieving the fields in a class.
8876 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8877 * iterate over all of the elements. When no more values are
8878 * available, the return value is NULL.
8880 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8883 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8885 MonoClassField* field;
8889 mono_class_setup_fields_locking (klass);
8890 if (klass->exception_type)
8892 /* start from the first */
8893 if (klass->field.count) {
8894 return *iter = &klass->fields [0];
8902 if (field < &klass->fields [klass->field.count]) {
8903 return *iter = field;
8909 * mono_class_get_methods
8910 * @klass: the MonoClass to act on
8912 * This routine is an iterator routine for retrieving the fields in a class.
8914 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8915 * iterate over all of the elements. When no more values are
8916 * available, the return value is NULL.
8918 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8921 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8923 MonoMethod** method;
8927 mono_class_setup_methods (klass);
8930 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8931 * FIXME we should better report this error to the caller
8933 if (!klass->methods)
8935 /* start from the first */
8936 if (klass->method.count) {
8937 *iter = &klass->methods [0];
8938 return klass->methods [0];
8946 if (method < &klass->methods [klass->method.count]) {
8954 * mono_class_get_virtual_methods:
8956 * Iterate over the virtual methods of KLASS.
8958 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8961 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8963 MonoMethod** method;
8966 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8968 mono_class_setup_methods (klass);
8970 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8971 * FIXME we should better report this error to the caller
8973 if (!klass->methods)
8975 /* start from the first */
8976 method = &klass->methods [0];
8981 while (method < &klass->methods [klass->method.count]) {
8982 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8986 if (method < &klass->methods [klass->method.count]) {
8993 /* Search directly in metadata to avoid calling setup_methods () */
8994 MonoMethod *res = NULL;
9000 start_index = GPOINTER_TO_UINT (*iter);
9003 for (i = start_index; i < klass->method.count; ++i) {
9006 /* class->method.first points into the methodptr table */
9007 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9009 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9013 if (i < klass->method.count) {
9015 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9016 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9018 /* Add 1 here so the if (*iter) check fails */
9019 *iter = GUINT_TO_POINTER (i + 1);
9028 * mono_class_get_properties:
9029 * @klass: the MonoClass to act on
9031 * This routine is an iterator routine for retrieving the properties in a class.
9033 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9034 * iterate over all of the elements. When no more values are
9035 * available, the return value is NULL.
9037 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9040 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9042 MonoProperty* property;
9046 mono_class_setup_properties (klass);
9047 /* start from the first */
9048 if (klass->ext->property.count) {
9049 return *iter = &klass->ext->properties [0];
9057 if (property < &klass->ext->properties [klass->ext->property.count]) {
9058 return *iter = property;
9064 * mono_class_get_events:
9065 * @klass: the MonoClass to act on
9067 * This routine is an iterator routine for retrieving the properties in a class.
9069 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9070 * iterate over all of the elements. When no more values are
9071 * available, the return value is NULL.
9073 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9076 mono_class_get_events (MonoClass* klass, gpointer *iter)
9082 mono_class_setup_events (klass);
9083 /* start from the first */
9084 if (klass->ext->event.count) {
9085 return *iter = &klass->ext->events [0];
9093 if (event < &klass->ext->events [klass->ext->event.count]) {
9094 return *iter = event;
9100 * mono_class_get_interfaces
9101 * @klass: the MonoClass to act on
9103 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9105 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9106 * iterate over all of the elements. When no more values are
9107 * available, the return value is NULL.
9109 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9112 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9120 mono_class_init (klass);
9121 if (!klass->interfaces_inited) {
9122 mono_class_setup_interfaces (klass, &error);
9123 if (!mono_error_ok (&error)) {
9124 mono_error_cleanup (&error);
9128 /* start from the first */
9129 if (klass->interface_count) {
9130 *iter = &klass->interfaces [0];
9131 return klass->interfaces [0];
9139 if (iface < &klass->interfaces [klass->interface_count]) {
9147 setup_nested_types (MonoClass *klass)
9150 GList *classes, *nested_classes, *l;
9153 if (klass->nested_classes_inited)
9156 if (!klass->type_token)
9157 klass->nested_classes_inited = TRUE;
9159 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9163 guint32 cols [MONO_NESTED_CLASS_SIZE];
9164 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9165 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9166 if (!mono_error_ok (&error)) {
9167 /*FIXME don't swallow the error message*/
9168 mono_error_cleanup (&error);
9170 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9174 classes = g_list_prepend (classes, nclass);
9176 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9179 mono_class_alloc_ext (klass);
9181 nested_classes = NULL;
9182 for (l = classes; l; l = l->next)
9183 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9184 g_list_free (classes);
9186 mono_image_lock (klass->image);
9188 mono_memory_barrier ();
9189 if (!klass->nested_classes_inited) {
9190 klass->ext->nested_classes = nested_classes;
9191 mono_memory_barrier ();
9192 klass->nested_classes_inited = TRUE;
9195 mono_image_unlock (klass->image);
9199 * mono_class_get_nested_types
9200 * @klass: the MonoClass to act on
9202 * This routine is an iterator routine for retrieving the nested types of a class.
9203 * This works only if @klass is non-generic, or a generic type definition.
9205 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9206 * iterate over all of the elements. When no more values are
9207 * available, the return value is NULL.
9209 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9212 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9218 if (!klass->nested_classes_inited)
9219 setup_nested_types (klass);
9222 /* start from the first */
9223 if (klass->ext && klass->ext->nested_classes) {
9224 *iter = klass->ext->nested_classes;
9225 return klass->ext->nested_classes->data;
9227 /* no nested types */
9242 * mono_class_is_delegate
9243 * @klass: the MonoClass to act on
9245 * Returns: true if the MonoClass represents a System.Delegate.
9248 mono_class_is_delegate (MonoClass *klass)
9250 return klass->delegate;
9254 * mono_class_implements_interface
9255 * @klass: The MonoClass to act on
9256 * @interface: The interface to check if @klass implements.
9258 * Returns: true if @klass implements @interface.
9261 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9263 return mono_class_is_assignable_from (iface, klass);
9267 * mono_field_get_name:
9268 * @field: the MonoClassField to act on
9270 * Returns: the name of the field.
9273 mono_field_get_name (MonoClassField *field)
9279 * mono_field_get_type:
9280 * @field: the MonoClassField to act on
9282 * Returns: MonoType of the field.
9285 mono_field_get_type (MonoClassField *field)
9288 MonoType *type = mono_field_get_type_checked (field, &error);
9289 if (!mono_error_ok (&error)) {
9290 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9291 mono_error_cleanup (&error);
9298 * mono_field_get_type_checked:
9299 * @field: the MonoClassField to act on
9300 * @error: used to return any erro found while retrieving @field type
9302 * Returns: MonoType of the field.
9305 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9307 mono_error_init (error);
9309 mono_field_resolve_type (field, error);
9314 * mono_field_get_parent:
9315 * @field: the MonoClassField to act on
9317 * Returns: MonoClass where the field was defined.
9320 mono_field_get_parent (MonoClassField *field)
9322 return field->parent;
9326 * mono_field_get_flags;
9327 * @field: the MonoClassField to act on
9329 * The metadata flags for a field are encoded using the
9330 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9332 * Returns: the flags for the field.
9335 mono_field_get_flags (MonoClassField *field)
9338 return mono_field_resolve_flags (field);
9339 return field->type->attrs;
9343 * mono_field_get_offset;
9344 * @field: the MonoClassField to act on
9346 * Returns: the field offset.
9349 mono_field_get_offset (MonoClassField *field)
9351 return field->offset;
9355 mono_field_get_rva (MonoClassField *field)
9359 MonoClass *klass = field->parent;
9360 MonoFieldDefaultValue *field_def_values;
9362 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9364 if (!klass->ext || !klass->ext->field_def_values) {
9365 mono_class_alloc_ext (klass);
9367 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9369 mono_image_lock (klass->image);
9370 if (!klass->ext->field_def_values)
9371 klass->ext->field_def_values = field_def_values;
9372 mono_image_unlock (klass->image);
9375 field_index = mono_field_get_index (field);
9377 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9378 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9380 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9381 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9384 return klass->ext->field_def_values [field_index].data;
9388 * mono_field_get_data;
9389 * @field: the MonoClassField to act on
9391 * Returns: pointer to the metadata constant value or to the field
9392 * data if it has an RVA flag.
9395 mono_field_get_data (MonoClassField *field)
9397 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9398 MonoTypeEnum def_type;
9400 return mono_class_get_field_default_value (field, &def_type);
9401 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9402 return mono_field_get_rva (field);
9409 * mono_property_get_name:
9410 * @prop: the MonoProperty to act on
9412 * Returns: the name of the property
9415 mono_property_get_name (MonoProperty *prop)
9421 * mono_property_get_set_method
9422 * @prop: the MonoProperty to act on.
9424 * Returns: the setter method of the property (A MonoMethod)
9427 mono_property_get_set_method (MonoProperty *prop)
9433 * mono_property_get_get_method
9434 * @prop: the MonoProperty to act on.
9436 * Returns: the setter method of the property (A MonoMethod)
9439 mono_property_get_get_method (MonoProperty *prop)
9445 * mono_property_get_parent:
9446 * @prop: the MonoProperty to act on.
9448 * Returns: the MonoClass where the property was defined.
9451 mono_property_get_parent (MonoProperty *prop)
9453 return prop->parent;
9457 * mono_property_get_flags:
9458 * @prop: the MonoProperty to act on.
9460 * The metadata flags for a property are encoded using the
9461 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9463 * Returns: the flags for the property.
9466 mono_property_get_flags (MonoProperty *prop)
9472 * mono_event_get_name:
9473 * @event: the MonoEvent to act on
9475 * Returns: the name of the event.
9478 mono_event_get_name (MonoEvent *event)
9484 * mono_event_get_add_method:
9485 * @event: The MonoEvent to act on.
9487 * Returns: the @add' method for the event (a MonoMethod).
9490 mono_event_get_add_method (MonoEvent *event)
9496 * mono_event_get_remove_method:
9497 * @event: The MonoEvent to act on.
9499 * Returns: the @remove method for the event (a MonoMethod).
9502 mono_event_get_remove_method (MonoEvent *event)
9504 return event->remove;
9508 * mono_event_get_raise_method:
9509 * @event: The MonoEvent to act on.
9511 * Returns: the @raise method for the event (a MonoMethod).
9514 mono_event_get_raise_method (MonoEvent *event)
9516 return event->raise;
9520 * mono_event_get_parent:
9521 * @event: the MonoEvent to act on.
9523 * Returns: the MonoClass where the event is defined.
9526 mono_event_get_parent (MonoEvent *event)
9528 return event->parent;
9532 * mono_event_get_flags
9533 * @event: the MonoEvent to act on.
9535 * The metadata flags for an event are encoded using the
9536 * EVENT_* constants. See the tabledefs.h file for details.
9538 * Returns: the flags for the event.
9541 mono_event_get_flags (MonoEvent *event)
9543 return event->attrs;
9547 * mono_class_get_method_from_name:
9548 * @klass: where to look for the method
9549 * @name: name of the method
9550 * @param_count: number of parameters. -1 for any number.
9552 * Obtains a MonoMethod with a given name and number of parameters.
9553 * It only works if there are no multiple signatures for any given method name.
9556 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9558 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9562 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9564 MonoMethod *res = NULL;
9567 /* Search directly in the metadata to avoid calling setup_methods () */
9568 for (i = 0; i < klass->method.count; ++i) {
9570 guint32 cols [MONO_METHOD_SIZE];
9572 MonoMethodSignature *sig;
9574 /* class->method.first points into the methodptr table */
9575 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9577 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9578 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9580 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9583 if (param_count == -1) {
9587 sig = mono_method_signature_checked (method, &error);
9589 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9592 if (sig->param_count == param_count) {
9603 * mono_class_get_method_from_name_flags:
9604 * @klass: where to look for the method
9605 * @name_space: name of the method
9606 * @param_count: number of parameters. -1 for any number.
9607 * @flags: flags which must be set in the method
9609 * Obtains a MonoMethod with a given name and number of parameters.
9610 * It only works if there are no multiple signatures for any given method name.
9613 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9615 MonoMethod *res = NULL;
9618 mono_class_init (klass);
9620 if (klass->generic_class && !klass->methods) {
9621 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9624 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9625 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9630 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9631 mono_class_setup_methods (klass);
9633 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9634 See mono/tests/array_load_exception.il
9635 FIXME we should better report this error to the caller
9637 if (!klass->methods)
9639 for (i = 0; i < klass->method.count; ++i) {
9640 MonoMethod *method = klass->methods [i];
9642 if (method->name[0] == name [0] &&
9643 !strcmp (name, method->name) &&
9644 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9645 ((method->flags & flags) == flags)) {
9652 res = find_method_in_metadata (klass, name, param_count, flags);
9659 * mono_class_set_failure:
9660 * @klass: class in which the failure was detected
9661 * @ex_type: the kind of exception/error to be thrown (later)
9662 * @ex_data: exception data (specific to each type of exception/error)
9664 * Keep a detected failure informations in the class for later processing.
9665 * Note that only the first failure is kept.
9667 * LOCKING: Acquires the loader lock.
9670 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9672 if (klass->exception_type)
9675 mono_loader_lock ();
9676 klass->exception_type = ex_type;
9678 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9679 mono_loader_unlock ();
9685 * mono_class_get_exception_data:
9687 * Return the exception_data property of KLASS.
9689 * LOCKING: Acquires the loader lock.
9692 mono_class_get_exception_data (MonoClass *klass)
9694 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9698 * mono_classes_init:
9700 * Initialize the resources used by this module.
9703 mono_classes_init (void)
9705 mono_mutex_init (&classes_mutex);
9707 mono_counters_register ("Inflated methods size",
9708 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9709 mono_counters_register ("Inflated classes",
9710 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9711 mono_counters_register ("Inflated classes size",
9712 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9713 mono_counters_register ("MonoClass size",
9714 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9715 mono_counters_register ("MonoClassExt size",
9716 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9720 * mono_classes_cleanup:
9722 * Free the resources used by this module.
9725 mono_classes_cleanup (void)
9727 if (global_interface_bitset)
9728 mono_bitset_free (global_interface_bitset);
9729 global_interface_bitset = NULL;
9730 mono_mutex_destroy (&classes_mutex);
9734 * mono_class_get_exception_for_failure:
9735 * @klass: class in which the failure was detected
9737 * Return a constructed MonoException than the caller can then throw
9738 * using mono_raise_exception - or NULL if no failure is present (or
9739 * doesn't result in an exception).
9742 mono_class_get_exception_for_failure (MonoClass *klass)
9744 gpointer exception_data = mono_class_get_exception_data (klass);
9746 switch (klass->exception_type) {
9747 #ifndef DISABLE_SECURITY
9748 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9749 MonoDomain *domain = mono_domain_get ();
9750 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9751 MonoMethod *method = exception_data;
9752 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9753 MonoObject *exc = NULL;
9757 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9758 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9759 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9761 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9762 return (MonoException*) exc;
9765 case MONO_EXCEPTION_TYPE_LOAD: {
9768 char *str = mono_type_get_full_name (klass);
9769 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9770 name = mono_string_new (mono_domain_get (), str);
9772 ex = mono_get_exception_type_load (name, astr);
9776 case MONO_EXCEPTION_MISSING_METHOD: {
9777 char *class_name = exception_data;
9778 char *assembly_name = class_name + strlen (class_name) + 1;
9780 return mono_get_exception_missing_method (class_name, assembly_name);
9782 case MONO_EXCEPTION_MISSING_FIELD: {
9783 char *class_name = exception_data;
9784 char *member_name = class_name + strlen (class_name) + 1;
9786 return mono_get_exception_missing_field (class_name, member_name);
9788 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9789 char *msg_format = exception_data;
9790 char *assembly_name = msg_format + strlen (msg_format) + 1;
9791 char *msg = g_strdup_printf (msg_format, assembly_name);
9794 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9800 case MONO_EXCEPTION_BAD_IMAGE: {
9801 return mono_get_exception_bad_image_format (exception_data);
9804 MonoLoaderError *error;
9807 error = mono_loader_get_last_error ();
9809 ex = mono_loader_error_prepare_exception (error);
9813 /* TODO - handle other class related failures */
9820 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9822 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9823 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9825 if (outer_klass == inner_klass)
9827 inner_klass = inner_klass->nested_in;
9828 } while (inner_klass);
9833 mono_class_get_generic_type_definition (MonoClass *klass)
9835 return klass->generic_class ? klass->generic_class->container_class : klass;
9839 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9841 * Generic instantiations are ignored for all super types of @klass.
9843 * Visibility checks ignoring generic instantiations.
9846 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9849 klass = mono_class_get_generic_type_definition (klass);
9850 parent = mono_class_get_generic_type_definition (parent);
9851 mono_class_setup_supertypes (klass);
9853 for (i = 0; i < klass->idepth; ++i) {
9854 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9860 * Subtype can only access parent members with family protection if the site object
9861 * is subclass of Subtype. For example:
9862 * class A { protected int x; }
9864 * void valid_access () {
9868 * void invalid_access () {
9875 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9877 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9880 if (context_klass == NULL)
9882 /*if access_klass is not member_klass context_klass must be type compat*/
9883 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9889 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9892 if (accessing == accessed)
9894 if (!accessed || !accessing)
9897 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9898 * anywhere so untrusted friends are not safe to access platform's code internals */
9899 if (mono_security_core_clr_enabled ()) {
9900 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9904 mono_assembly_load_friends (accessed);
9905 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9906 MonoAssemblyName *friend = tmp->data;
9907 /* Be conservative with checks */
9910 if (strcmp (accessing->aname.name, friend->name))
9912 if (friend->public_key_token [0]) {
9913 if (!accessing->aname.public_key_token [0])
9915 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9924 * If klass is a generic type or if it is derived from a generic type, return the
9925 * MonoClass of the generic definition
9926 * Returns NULL if not found
9929 get_generic_definition_class (MonoClass *klass)
9932 if (klass->generic_class && klass->generic_class->container_class)
9933 return klass->generic_class->container_class;
9934 klass = klass->parent;
9940 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9943 for (i = 0; i < ginst->type_argc; ++i) {
9944 MonoType *type = ginst->type_argv[i];
9945 switch (type->type) {
9946 case MONO_TYPE_SZARRAY:
9947 if (!can_access_type (access_klass, type->data.klass))
9950 case MONO_TYPE_ARRAY:
9951 if (!can_access_type (access_klass, type->data.array->eklass))
9955 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9958 case MONO_TYPE_CLASS:
9959 case MONO_TYPE_VALUETYPE:
9960 case MONO_TYPE_GENERICINST:
9961 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9971 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9975 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9978 if (access_klass->element_class && !access_klass->enumtype)
9979 access_klass = access_klass->element_class;
9981 if (member_klass->element_class && !member_klass->enumtype)
9982 member_klass = member_klass->element_class;
9984 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9986 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9989 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9992 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9995 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9998 /*Non nested type with nested visibility. We just fail it.*/
9999 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10002 switch (access_level) {
10003 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10004 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10006 case TYPE_ATTRIBUTE_PUBLIC:
10009 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10012 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10013 return is_nesting_type (member_klass, access_klass);
10015 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10016 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10018 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10019 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10021 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10022 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10023 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10025 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10026 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10027 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10032 /* FIXME: check visibility of type, too */
10034 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10036 MonoClass *member_generic_def;
10037 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10040 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10041 access_klass->generic_container) &&
10042 (member_generic_def = get_generic_definition_class (member_klass))) {
10043 MonoClass *access_container;
10045 if (access_klass->generic_container)
10046 access_container = access_klass;
10048 access_container = access_klass->generic_class->container_class;
10050 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10054 /* Partition I 8.5.3.2 */
10055 /* the access level values are the same for fields and methods */
10056 switch (access_level) {
10057 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10058 /* same compilation unit */
10059 return access_klass->image == member_klass->image;
10060 case FIELD_ATTRIBUTE_PRIVATE:
10061 return access_klass == member_klass;
10062 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10063 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10064 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10067 case FIELD_ATTRIBUTE_ASSEMBLY:
10068 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10069 case FIELD_ATTRIBUTE_FAMILY:
10070 if (is_valid_family_access (access_klass, member_klass, context_klass))
10073 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10074 if (is_valid_family_access (access_klass, member_klass, context_klass))
10076 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10077 case FIELD_ATTRIBUTE_PUBLIC:
10084 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10086 /* FIXME: check all overlapping fields */
10087 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10089 MonoClass *nested = method->klass->nested_in;
10091 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10094 nested = nested->nested_in;
10101 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10103 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10105 MonoClass *nested = method->klass->nested_in;
10107 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10110 nested = nested->nested_in;
10115 * with generics calls to explicit interface implementations can be expressed
10116 * directly: the method is private, but we must allow it. This may be opening
10117 * a hole or the generics code should handle this differently.
10118 * Maybe just ensure the interface type is public.
10120 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10126 * mono_method_can_access_method_full:
10127 * @method: The caller method
10128 * @called: The called method
10129 * @context_klass: The static type on stack of the owner @called object used
10131 * This function must be used with instance calls, as they have more strict family accessibility.
10132 * It can be used with static methods, but context_klass should be NULL.
10134 * Returns: TRUE if caller have proper visibility and acessibility to @called
10137 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10139 MonoClass *access_class = method->klass;
10140 MonoClass *member_class = called->klass;
10141 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10143 MonoClass *nested = access_class->nested_in;
10145 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10148 nested = nested->nested_in;
10155 can = can_access_type (access_class, member_class);
10157 MonoClass *nested = access_class->nested_in;
10159 can = can_access_type (nested, member_class);
10162 nested = nested->nested_in;
10169 if (called->is_inflated) {
10170 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10171 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10180 * mono_method_can_access_field_full:
10181 * @method: The caller method
10182 * @field: The accessed field
10183 * @context_klass: The static type on stack of the owner @field object used
10185 * This function must be used with instance fields, as they have more strict family accessibility.
10186 * It can be used with static fields, but context_klass should be NULL.
10188 * Returns: TRUE if caller have proper visibility and acessibility to @field
10191 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10193 MonoClass *access_class = method->klass;
10194 MonoClass *member_class = field->parent;
10195 /* FIXME: check all overlapping fields */
10196 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10198 MonoClass *nested = access_class->nested_in;
10200 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10203 nested = nested->nested_in;
10210 can = can_access_type (access_class, member_class);
10212 MonoClass *nested = access_class->nested_in;
10214 can = can_access_type (nested, member_class);
10217 nested = nested->nested_in;
10227 * mono_class_can_access_class:
10228 * @source_class: The source class
10229 * @target_class: The accessed class
10231 * This function returns is @target_class is visible to @source_class
10233 * Returns: TRUE if source have proper visibility and acessibility to target
10236 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10238 return can_access_type (source_class, target_class);
10242 * mono_type_is_valid_enum_basetype:
10243 * @type: The MonoType to check
10245 * Returns: TRUE if the type can be used as the basetype of an enum
10247 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10248 switch (type->type) {
10251 case MONO_TYPE_BOOLEAN:
10254 case MONO_TYPE_CHAR:
10268 * mono_class_is_valid_enum:
10269 * @klass: An enum class to be validated
10271 * This method verify the required properties an enum should have.
10273 * Returns: TRUE if the informed enum class is valid
10275 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10276 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10277 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10279 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10280 MonoClassField * field;
10281 gpointer iter = NULL;
10282 gboolean found_base_field = FALSE;
10284 g_assert (klass->enumtype);
10285 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10286 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10290 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10293 while ((field = mono_class_get_fields (klass, &iter))) {
10294 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10295 if (found_base_field)
10297 found_base_field = TRUE;
10298 if (!mono_type_is_valid_enum_basetype (field->type))
10303 if (!found_base_field)
10306 if (klass->method.count > 0)
10313 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10315 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10319 * mono_class_setup_interface_id:
10321 * Initializes MonoClass::interface_id if required.
10323 * LOCKING: Acquires the loader lock.
10326 mono_class_setup_interface_id (MonoClass *class)
10328 mono_loader_lock ();
10329 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10330 class->interface_id = mono_get_unique_iid (class);
10331 mono_loader_unlock ();
10335 * mono_class_alloc_ext:
10337 * Allocate klass->ext if not already done.
10340 mono_class_alloc_ext (MonoClass *klass)
10347 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10348 mono_image_lock (klass->image);
10349 mono_memory_barrier ();
10352 class_ext_size += sizeof (MonoClassExt);
10353 mono_image_unlock (klass->image);
10357 * mono_class_setup_interfaces:
10359 * Initialize class->interfaces/interfaces_count.
10360 * LOCKING: Acquires the loader lock.
10361 * This function can fail the type.
10364 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10366 int i, interface_count;
10367 MonoClass **interfaces;
10369 mono_error_init (error);
10371 if (klass->interfaces_inited)
10374 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10375 MonoType *args [1];
10377 /* generic IList, ICollection, IEnumerable */
10378 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10379 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10381 args [0] = &klass->element_class->byval_arg;
10382 interfaces [0] = mono_class_bind_generic_parameters (
10383 mono_defaults.generic_ilist_class, 1, args, FALSE);
10384 if (interface_count > 1)
10385 interfaces [1] = mono_class_bind_generic_parameters (
10386 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10387 } else if (klass->generic_class) {
10388 MonoClass *gklass = klass->generic_class->container_class;
10390 mono_class_setup_interfaces (gklass, error);
10391 if (!mono_error_ok (error)) {
10392 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10396 interface_count = gklass->interface_count;
10397 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10398 for (i = 0; i < interface_count; i++) {
10399 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10400 if (!mono_error_ok (error)) {
10401 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10406 interface_count = 0;
10410 mono_image_lock (klass->image);
10412 if (!klass->interfaces_inited) {
10413 klass->interface_count = interface_count;
10414 klass->interfaces = interfaces;
10416 mono_memory_barrier ();
10418 klass->interfaces_inited = TRUE;
10421 mono_image_unlock (klass->image);
10425 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10427 MonoClass *class = field->parent;
10428 MonoImage *image = class->image;
10429 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10430 int field_idx = field - class->fields;
10432 mono_error_init (error);
10435 MonoClassField *gfield = >d->fields [field_idx];
10436 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10437 if (!mono_error_ok (error)) {
10438 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10439 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10443 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10444 if (!mono_error_ok (error)) {
10445 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10446 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10451 guint32 cols [MONO_FIELD_SIZE];
10452 MonoGenericContainer *container = NULL;
10453 int idx = class->field.first + field_idx;
10455 /*FIXME, in theory we do not lazy load SRE fields*/
10456 g_assert (!image_is_dynamic (image));
10458 if (class->generic_container) {
10459 container = class->generic_container;
10461 container = gtd->generic_container;
10462 g_assert (container);
10465 /* class->field.first and idx points into the fieldptr table */
10466 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10468 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10469 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10470 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10474 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10476 mono_metadata_decode_value (sig, &sig);
10477 /* FIELD signature == 0x06 */
10478 g_assert (*sig == 0x06);
10479 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10481 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10486 mono_field_resolve_flags (MonoClassField *field)
10488 MonoClass *class = field->parent;
10489 MonoImage *image = class->image;
10490 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10491 int field_idx = field - class->fields;
10495 MonoClassField *gfield = >d->fields [field_idx];
10496 return mono_field_get_flags (gfield);
10498 int idx = class->field.first + field_idx;
10500 /*FIXME, in theory we do not lazy load SRE fields*/
10501 g_assert (!image_is_dynamic (image));
10503 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10508 * mono_class_setup_basic_field_info:
10509 * @class: The class to initialize
10511 * Initializes the class->fields array of fields.
10512 * Aquires the loader lock.
10515 mono_class_setup_basic_field_info_locking (MonoClass *class)
10517 mono_loader_lock ();
10518 mono_class_setup_basic_field_info (class);
10519 mono_loader_unlock ();
10523 * mono_class_get_fields_lazy:
10524 * @klass: the MonoClass to act on
10526 * This routine is an iterator routine for retrieving the fields in a class.
10527 * Only minimal information about fields are loaded. Accessors must be used
10528 * for all MonoClassField returned.
10530 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10531 * iterate over all of the elements. When no more values are
10532 * available, the return value is NULL.
10534 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10537 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10539 MonoClassField* field;
10543 mono_class_setup_basic_field_info_locking (klass);
10544 if (!klass->fields)
10546 /* start from the first */
10547 if (klass->field.count) {
10548 return *iter = &klass->fields [0];
10556 if (field < &klass->fields [klass->field.count]) {
10557 return *iter = field;
10563 mono_class_full_name (MonoClass *klass)
10565 return mono_type_full_name (&klass->byval_arg);