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_checked (image, nspace, name, error);
202 case MONO_RESOLUTION_SCOPE_MODULEREF:
203 module = mono_image_load_module (image, idx);
205 res = mono_class_from_name_checked (module, nspace, name, error);
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 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
272 /* Generic case, should be avoided for when a better error is possible. */
273 if (!res && mono_error_ok (error)) {
274 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
275 mono_error_set_from_loader_error (error);
277 char *name = mono_class_name_from_token (image, type_token);
278 char *assembly = mono_assembly_name_from_token (image, type_token);
279 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
282 g_assert (!mono_loader_get_last_error ());
288 mono_image_memdup (MonoImage *image, void *data, guint size)
290 void *res = mono_image_alloc (image, size);
291 memcpy (res, data, size);
295 /* Copy everything mono_metadata_free_array free. */
297 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
300 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
302 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
304 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
306 a = g_memdup (a, sizeof (MonoArrayType));
308 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
310 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
315 /* Copy everything mono_metadata_free_method_signature free. */
317 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
321 sig = mono_metadata_signature_dup_full (image, sig);
323 sig->ret = mono_metadata_type_dup (image, sig->ret);
324 for (i = 0; i < sig->param_count; ++i)
325 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
331 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
333 MonoAssembly *ta = klass->image->assembly;
336 name = mono_stringify_assembly_name (&ta->aname);
337 g_string_append_printf (str, ", %s", name);
342 mono_type_name_check_byref (MonoType *type, GString *str)
345 g_string_append_c (str, '&');
349 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
350 MonoTypeNameFormat format)
354 switch (type->type) {
355 case MONO_TYPE_ARRAY: {
356 int i, rank = type->data.array->rank;
357 MonoTypeNameFormat nested_format;
359 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
360 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
362 mono_type_get_name_recurse (
363 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
364 g_string_append_c (str, '[');
366 g_string_append_c (str, '*');
367 for (i = 1; i < rank; i++)
368 g_string_append_c (str, ',');
369 g_string_append_c (str, ']');
371 mono_type_name_check_byref (type, str);
373 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
374 _mono_type_get_assembly_name (type->data.array->eklass, str);
377 case MONO_TYPE_SZARRAY: {
378 MonoTypeNameFormat nested_format;
380 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
381 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
383 mono_type_get_name_recurse (
384 &type->data.klass->byval_arg, str, FALSE, nested_format);
385 g_string_append (str, "[]");
387 mono_type_name_check_byref (type, str);
389 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
390 _mono_type_get_assembly_name (type->data.klass, str);
393 case MONO_TYPE_PTR: {
394 MonoTypeNameFormat nested_format;
396 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
397 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
399 mono_type_get_name_recurse (
400 type->data.type, str, FALSE, nested_format);
401 g_string_append_c (str, '*');
403 mono_type_name_check_byref (type, str);
405 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
406 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
411 if (!mono_generic_param_info (type->data.generic_param))
412 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
414 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
416 mono_type_name_check_byref (type, str);
420 klass = mono_class_from_mono_type (type);
421 if (klass->nested_in) {
422 mono_type_get_name_recurse (
423 &klass->nested_in->byval_arg, str, TRUE, format);
424 if (format == MONO_TYPE_NAME_FORMAT_IL)
425 g_string_append_c (str, '.');
427 g_string_append_c (str, '+');
428 } else if (*klass->name_space) {
429 g_string_append (str, klass->name_space);
430 g_string_append_c (str, '.');
432 if (format == MONO_TYPE_NAME_FORMAT_IL) {
433 char *s = strchr (klass->name, '`');
434 int len = s ? s - klass->name : strlen (klass->name);
436 g_string_append_len (str, klass->name, len);
438 g_string_append (str, klass->name);
441 if (klass->generic_class) {
442 MonoGenericClass *gclass = klass->generic_class;
443 MonoGenericInst *inst = gclass->context.class_inst;
444 MonoTypeNameFormat nested_format;
447 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
448 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
450 if (format == MONO_TYPE_NAME_FORMAT_IL)
451 g_string_append_c (str, '<');
453 g_string_append_c (str, '[');
454 for (i = 0; i < inst->type_argc; i++) {
455 MonoType *t = inst->type_argv [i];
458 g_string_append_c (str, ',');
459 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
460 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
461 g_string_append_c (str, '[');
462 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
463 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
464 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
465 g_string_append_c (str, ']');
467 if (format == MONO_TYPE_NAME_FORMAT_IL)
468 g_string_append_c (str, '>');
470 g_string_append_c (str, ']');
471 } else if (klass->generic_container &&
472 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
473 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
476 if (format == MONO_TYPE_NAME_FORMAT_IL)
477 g_string_append_c (str, '<');
479 g_string_append_c (str, '[');
480 for (i = 0; i < klass->generic_container->type_argc; i++) {
482 g_string_append_c (str, ',');
483 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
485 if (format == MONO_TYPE_NAME_FORMAT_IL)
486 g_string_append_c (str, '>');
488 g_string_append_c (str, ']');
491 mono_type_name_check_byref (type, str);
493 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
494 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
495 _mono_type_get_assembly_name (klass, str);
501 * mono_type_get_name_full:
503 * @format: the format for the return string.
506 * Returns: the string representation in a number of formats:
508 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
509 * returned in the formatrequired by System.Reflection, this is the
510 * inverse of mono_reflection_parse_type ().
512 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
513 * be used by the IL assembler.
515 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
517 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
520 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
524 result = g_string_new ("");
526 mono_type_get_name_recurse (type, result, FALSE, format);
528 return g_string_free (result, FALSE);
532 * mono_type_get_full_name:
535 * Returns: the string representation for type as required by System.Reflection.
536 * The inverse of mono_reflection_parse_type ().
539 mono_type_get_full_name (MonoClass *class)
541 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
545 * mono_type_get_name:
548 * Returns: the string representation for type as it would be represented in IL code.
551 mono_type_get_name (MonoType *type)
553 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
557 * mono_type_get_underlying_type:
560 * Returns: the MonoType for the underlying integer type if @type
561 * is an enum and byref is false, otherwise the type itself.
564 mono_type_get_underlying_type (MonoType *type)
566 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
567 return mono_class_enum_basetype (type->data.klass);
568 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
569 return mono_class_enum_basetype (type->data.generic_class->container_class);
574 * mono_class_is_open_constructed_type:
577 * Returns TRUE if type represents a generics open constructed type.
578 * IOW, not all type parameters required for the instantiation have
579 * been provided or it's a generic type definition.
581 * An open constructed type means it's a non realizable type. Not to
582 * be mixed up with an abstract type - we can't cast or dispatch to
583 * an open type, for example.
586 mono_class_is_open_constructed_type (MonoType *t)
592 case MONO_TYPE_SZARRAY:
593 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
594 case MONO_TYPE_ARRAY:
595 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
597 return mono_class_is_open_constructed_type (t->data.type);
598 case MONO_TYPE_GENERICINST:
599 return t->data.generic_class->context.class_inst->is_open;
600 case MONO_TYPE_CLASS:
601 case MONO_TYPE_VALUETYPE:
602 return t->data.klass->generic_container != NULL;
609 This is a simple function to catch the most common bad instances of generic types.
610 Specially those that might lead to further failures in the runtime.
613 is_valid_generic_argument (MonoType *type)
615 switch (type->type) {
617 //case MONO_TYPE_TYPEDBYREF:
625 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
627 mono_error_init (error);
629 switch (type->type) {
630 case MONO_TYPE_MVAR: {
632 int num = mono_type_get_generic_param_num (type);
633 MonoGenericInst *inst = context->method_inst;
634 if (!inst || !inst->type_argv)
636 if (num >= inst->type_argc) {
637 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
638 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
639 num, info ? info->name : "", inst->type_argc);
643 if (!is_valid_generic_argument (inst->type_argv [num])) {
644 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
645 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
646 num, info ? info->name : "", inst->type_argv [num]->type);
650 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
651 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
652 * ->byref and ->attrs from @type are propagated to the returned type.
654 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
655 nt->byref = type->byref;
656 nt->attrs = type->attrs;
659 case MONO_TYPE_VAR: {
661 int num = mono_type_get_generic_param_num (type);
662 MonoGenericInst *inst = context->class_inst;
665 if (num >= inst->type_argc) {
666 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
667 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
668 num, info ? info->name : "", inst->type_argc);
671 if (!is_valid_generic_argument (inst->type_argv [num])) {
672 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
673 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
674 num, info ? info->name : "", inst->type_argv [num]->type);
677 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
678 nt->byref = type->byref;
679 nt->attrs = type->attrs;
682 case MONO_TYPE_SZARRAY: {
683 MonoClass *eclass = type->data.klass;
684 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
685 if (!inflated || !mono_error_ok (error))
687 nt = mono_metadata_type_dup (image, type);
688 nt->data.klass = mono_class_from_mono_type (inflated);
689 mono_metadata_free_type (inflated);
692 case MONO_TYPE_ARRAY: {
693 MonoClass *eclass = type->data.array->eklass;
694 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
695 if (!inflated || !mono_error_ok (error))
697 nt = mono_metadata_type_dup (image, type);
698 nt->data.array->eklass = mono_class_from_mono_type (inflated);
699 mono_metadata_free_type (inflated);
702 case MONO_TYPE_GENERICINST: {
703 MonoGenericClass *gclass = type->data.generic_class;
704 MonoGenericInst *inst;
706 if (!gclass->context.class_inst->is_open)
709 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
710 if (!mono_error_ok (error))
712 if (inst != gclass->context.class_inst)
713 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
715 if (gclass == type->data.generic_class)
718 nt = mono_metadata_type_dup (image, type);
719 nt->data.generic_class = gclass;
722 case MONO_TYPE_CLASS:
723 case MONO_TYPE_VALUETYPE: {
724 MonoClass *klass = type->data.klass;
725 MonoGenericContainer *container = klass->generic_container;
726 MonoGenericInst *inst;
727 MonoGenericClass *gclass = NULL;
733 /* We can't use context->class_inst directly, since it can have more elements */
734 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
735 if (!mono_error_ok (error))
737 if (inst == container->context.class_inst)
740 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
742 nt = mono_metadata_type_dup (image, type);
743 nt->type = MONO_TYPE_GENERICINST;
744 nt->data.generic_class = gclass;
754 mono_generic_class_get_context (MonoGenericClass *gclass)
756 return &gclass->context;
760 mono_class_get_context (MonoClass *class)
762 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
766 * mono_class_get_generic_container:
768 * Return the generic container of KLASS which should be a generic type definition.
770 MonoGenericContainer*
771 mono_class_get_generic_container (MonoClass *klass)
773 g_assert (klass->is_generic);
775 return klass->generic_container;
779 * mono_class_get_generic_class:
781 * Return the MonoGenericClass of KLASS, which should be a generic instance.
784 mono_class_get_generic_class (MonoClass *klass)
786 g_assert (klass->is_inflated);
788 return klass->generic_class;
792 * mono_class_inflate_generic_type_with_mempool:
793 * @mempool: a mempool
795 * @context: a generics context
796 * @error: error context
798 * The same as mono_class_inflate_generic_type, but allocates the MonoType
799 * from mempool if it is non-NULL. If it is NULL, the MonoType is
800 * allocated on the heap and is owned by the caller.
801 * The returned type can potentially be the same as TYPE, so it should not be
802 * modified by the caller, and it should be freed using mono_metadata_free_type ().
805 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
807 MonoType *inflated = NULL;
808 mono_error_init (error);
811 inflated = inflate_generic_type (image, type, context, error);
812 if (!mono_error_ok (error))
816 MonoType *shared = mono_metadata_get_shared_type (type);
821 return mono_metadata_type_dup (image, type);
825 mono_stats.inflated_type_count++;
830 * mono_class_inflate_generic_type:
832 * @context: a generics context
834 * If @type is a generic type and @context is not NULL, instantiate it using the
835 * generics context @context.
837 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
838 * on the heap and is owned by the caller. Returns NULL on error.
840 * @deprecated Please use mono_class_inflate_generic_type_checked instead
843 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
847 result = mono_class_inflate_generic_type_checked (type, context, &error);
849 if (!mono_error_ok (&error)) {
850 mono_error_cleanup (&error);
857 * mono_class_inflate_generic_type:
859 * @context: a generics context
860 * @error: error context to use
862 * If @type is a generic type and @context is not NULL, instantiate it using the
863 * generics context @context.
865 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
866 * on the heap and is owned by the caller.
869 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
871 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
875 * mono_class_inflate_generic_type_no_copy:
877 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
881 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
883 MonoType *inflated = NULL;
885 mono_error_init (error);
887 inflated = inflate_generic_type (image, type, context, error);
888 if (!mono_error_ok (error))
895 mono_stats.inflated_type_count++;
900 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
905 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
906 if (!mono_error_ok (error))
909 res = mono_class_from_mono_type (inflated);
910 mono_metadata_free_type (inflated);
915 * mono_class_inflate_generic_class:
917 * Inflate the class GKLASS with CONTEXT.
920 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
925 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
926 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
933 static MonoGenericContext
934 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
936 MonoGenericInst *class_inst = NULL;
937 MonoGenericInst *method_inst = NULL;
938 MonoGenericContext res = { NULL, NULL };
940 mono_error_init (error);
942 if (context->class_inst) {
943 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
944 if (!mono_error_ok (error))
948 if (context->method_inst) {
949 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
950 if (!mono_error_ok (error))
954 res.class_inst = class_inst;
955 res.method_inst = method_inst;
961 * mono_class_inflate_generic_method:
962 * @method: a generic method
963 * @context: a generics context
965 * Instantiate the generic method @method using the generics context @context.
967 * Returns: the new instantiated method
970 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
972 return mono_class_inflate_generic_method_full (method, NULL, context);
976 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
978 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
982 * mono_class_inflate_generic_method_full:
984 * Instantiate method @method with the generic context @context.
985 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
986 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
989 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
992 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
993 if (!mono_error_ok (&error))
994 /*FIXME do proper error handling - on this case, kill this function. */
995 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1001 * mono_class_inflate_generic_method_full_checked:
1002 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1005 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1008 MonoMethodInflated *iresult, *cached;
1009 MonoMethodSignature *sig;
1010 MonoGenericContext tmp_context;
1011 gboolean is_mb_open = FALSE;
1013 mono_error_init (error);
1015 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1016 while (method->is_inflated) {
1017 MonoGenericContext *method_context = mono_method_get_context (method);
1018 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1020 tmp_context = inflate_generic_context (method_context, context, error);
1021 if (!mono_error_ok (error))
1023 context = &tmp_context;
1025 if (mono_metadata_generic_context_equal (method_context, context))
1028 method = imethod->declaring;
1032 * A method only needs to be inflated if the context has argument for which it is
1035 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1036 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1039 if (!((method->is_generic && context->method_inst) ||
1040 (method->klass->generic_container && context->class_inst)))
1044 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1045 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1046 * This is opposite to the way non-SRE MethodInfos behave.
1048 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1050 * void Example<T> () {
1054 * In Example, the method token must be encoded as: "void Example<!!0>()"
1056 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1057 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1059 * On the other hand, inflating a non-SRE generic method with its own arguments should
1060 * return itself. For example:
1062 * MethodInfo m = ... //m is a generic method definition
1063 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1066 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1067 * what happens with regular methods.
1069 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1070 * everything should behave like a regular type or method.
1073 is_mb_open = method->is_generic &&
1074 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1075 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1077 iresult = g_new0 (MonoMethodInflated, 1);
1078 iresult->context = *context;
1079 iresult->declaring = method;
1080 iresult->method.method.is_mb_open = is_mb_open;
1082 if (!context->method_inst && method->is_generic)
1083 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1085 if (!context->class_inst) {
1086 g_assert (!iresult->declaring->klass->generic_class);
1087 if (iresult->declaring->klass->generic_container)
1088 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1089 else if (iresult->declaring->klass->generic_class)
1090 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1092 /* This can happen with some callers like mono_object_get_virtual_method () */
1093 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1094 iresult->context.class_inst = NULL;
1096 cached = mono_method_inflated_lookup (iresult, FALSE);
1099 return (MonoMethod*)cached;
1102 mono_stats.inflated_method_count++;
1104 inflated_methods_size += sizeof (MonoMethodInflated);
1106 sig = mono_method_signature (method);
1108 char *name = mono_type_get_full_name (method->klass);
1109 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1115 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1117 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1120 result = (MonoMethod *) iresult;
1121 result->is_inflated = TRUE;
1122 result->is_generic = FALSE;
1123 result->sre_method = FALSE;
1124 result->signature = NULL;
1125 result->is_mb_open = is_mb_open;
1127 if (!context->method_inst) {
1128 /* Set the generic_container of the result to the generic_container of method */
1129 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1131 if (generic_container) {
1132 result->is_generic = 1;
1133 mono_method_set_generic_container (result, generic_container);
1137 if (!klass_hint || !klass_hint->generic_class ||
1138 klass_hint->generic_class->container_class != method->klass ||
1139 klass_hint->generic_class->context.class_inst != context->class_inst)
1142 if (method->klass->generic_container)
1143 result->klass = klass_hint;
1145 if (!result->klass) {
1146 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1147 if (!mono_error_ok (error))
1150 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1152 mono_metadata_free_type (inflated);
1156 * FIXME: This should hold, but it doesn't:
1158 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1159 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1160 * g_assert (result->is_generic);
1163 * Fixing this here causes other things to break, hence a very
1164 * ugly hack in mini-trampolines.c - see
1165 * is_generic_method_definition().
1168 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1176 * mono_get_inflated_method:
1178 * Obsolete. We keep it around since it's mentioned in the public API.
1181 mono_get_inflated_method (MonoMethod *method)
1187 * mono_method_get_context_general:
1189 * @uninflated: handle uninflated methods?
1191 * Returns the generic context of a method or NULL if it doesn't have
1192 * one. For an inflated method that's the context stored in the
1193 * method. Otherwise it's in the method's generic container or in the
1194 * generic container of the method's class.
1197 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1199 if (method->is_inflated) {
1200 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1201 return &imethod->context;
1205 if (method->is_generic)
1206 return &(mono_method_get_generic_container (method)->context);
1207 if (method->klass->generic_container)
1208 return &method->klass->generic_container->context;
1213 * mono_method_get_context:
1216 * Returns the generic context for method if it's inflated, otherwise
1220 mono_method_get_context (MonoMethod *method)
1222 return mono_method_get_context_general (method, FALSE);
1226 * mono_method_get_generic_container:
1228 * Returns the generic container of METHOD, which should be a generic method definition.
1229 * Returns NULL if METHOD is not a generic method definition.
1230 * LOCKING: Acquires the loader lock.
1232 MonoGenericContainer*
1233 mono_method_get_generic_container (MonoMethod *method)
1235 MonoGenericContainer *container;
1237 if (!method->is_generic)
1240 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1241 g_assert (container);
1247 * mono_method_set_generic_container:
1249 * Sets the generic container of METHOD to CONTAINER.
1250 * LOCKING: Acquires the image lock.
1253 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1255 g_assert (method->is_generic);
1257 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1261 * mono_class_find_enum_basetype:
1262 * @class: The enum class
1264 * Determine the basetype of an enum by iterating through its fields. We do this
1265 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1268 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1270 MonoGenericContainer *container = NULL;
1271 MonoImage *m = class->image;
1272 const int top = class->field.count;
1275 g_assert (class->enumtype);
1277 mono_error_init (error);
1279 if (class->generic_container)
1280 container = class->generic_container;
1281 else if (class->generic_class) {
1282 MonoClass *gklass = class->generic_class->container_class;
1284 container = gklass->generic_container;
1285 g_assert (container);
1289 * Fetch all the field information.
1291 for (i = 0; i < top; i++){
1293 guint32 cols [MONO_FIELD_SIZE];
1294 int idx = class->field.first + i;
1297 /* class->field.first and idx points into the fieldptr table */
1298 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1300 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1303 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1304 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1308 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1309 mono_metadata_decode_value (sig, &sig);
1310 /* FIELD signature == 0x06 */
1312 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1316 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1318 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1319 mono_error_set_from_loader_error (error);
1321 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1324 if (class->generic_class) {
1325 //FIXME do we leak here?
1326 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1327 if (!mono_error_ok (error))
1329 ftype->attrs = cols [MONO_FIELD_FLAGS];
1334 mono_error_set_type_load_class (error, class, "Could not find base type");
1337 g_assert (!mono_loader_get_last_error ());
1342 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1345 mono_type_has_exceptions (MonoType *type)
1347 switch (type->type) {
1348 case MONO_TYPE_CLASS:
1349 case MONO_TYPE_VALUETYPE:
1350 case MONO_TYPE_SZARRAY:
1351 return type->data.klass->exception_type;
1352 case MONO_TYPE_ARRAY:
1353 return type->data.array->eklass->exception_type;
1354 case MONO_TYPE_GENERICINST:
1355 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1364 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1368 mono_class_alloc (MonoClass *class, int size)
1370 if (class->generic_class)
1371 return mono_image_set_alloc (class->generic_class->owner, size);
1373 return mono_image_alloc (class->image, size);
1377 mono_class_alloc0 (MonoClass *class, int size)
1381 res = mono_class_alloc (class, size);
1382 memset (res, 0, size);
1386 #define mono_class_new0(class,struct_type, n_structs) \
1387 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1390 * mono_class_setup_basic_field_info:
1391 * @class: The class to initialize
1393 * Initializes the class->fields.
1394 * LOCKING: Assumes the loader lock is held.
1397 mono_class_setup_basic_field_info (MonoClass *class)
1399 MonoClassField *field;
1407 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1408 image = class->image;
1409 top = class->field.count;
1411 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1413 * This happens when a generic instance of an unfinished generic typebuilder
1414 * is used as an element type for creating an array type. We can't initialize
1415 * the fields of this class using the fields of gklass, since gklass is not
1416 * finished yet, fields could be added to it later.
1422 mono_class_setup_basic_field_info (gtd);
1424 top = gtd->field.count;
1425 class->field.first = gtd->field.first;
1426 class->field.count = gtd->field.count;
1429 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1432 * Fetch all the field information.
1434 for (i = 0; i < top; i++){
1435 field = &class->fields [i];
1436 field->parent = class;
1439 field->name = mono_field_get_name (>d->fields [i]);
1441 int idx = class->field.first + i;
1442 /* class->field.first and idx points into the fieldptr table */
1443 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1444 /* The name is needed for fieldrefs */
1445 field->name = mono_metadata_string_heap (image, name_idx);
1451 * mono_class_setup_fields:
1452 * @class: The class to initialize
1454 * Initializes the class->fields.
1455 * LOCKING: Assumes the loader lock is held.
1458 mono_class_setup_fields (MonoClass *class)
1461 MonoImage *m = class->image;
1463 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1464 int i, blittable = TRUE;
1465 guint32 real_size = 0;
1466 guint32 packing_size = 0;
1467 gboolean explicit_size;
1468 MonoClassField *field;
1469 MonoGenericContainer *container = NULL;
1470 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1473 * FIXME: We have a race condition here. It's possible that this function returns
1474 * to its caller with `instance_size` set to `0` instead of the actual size. This
1475 * is not a problem when the function is called recursively on the same class,
1476 * because the size will be initialized by the outer invocation. What follows is a
1477 * description of how it can occur in other cases, too. There it is a problem,
1478 * because it can lead to the GC being asked to allocate an object of size `0`,
1479 * which SGen chokes on. The race condition is triggered infrequently by
1480 * `tests/sgen-suspend.cs`.
1482 * This function is called for a class whenever one of its subclasses is inited.
1483 * For example, it's called for every subclass of Object. What it does is this:
1485 * if (class->setup_fields_called)
1488 * class->instance_size = 0;
1490 * class->setup_fields_called = 1;
1491 * ... critical point
1492 * class->instance_size = actual_instance_size;
1494 * The last two steps are sometimes reversed, but that only changes the way in which
1495 * the race condition works.
1497 * Assume thread A goes through this function and makes it to the critical point.
1498 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1499 * immediately, but `instance_size` is incorrect.
1501 * The other case looks like this:
1503 * if (class->setup_fields_called)
1505 * ... critical point X
1506 * class->instance_size = 0;
1507 * ... critical point Y
1508 * class->instance_size = actual_instance_size;
1510 * class->setup_fields_called = 1;
1512 * Assume thread A goes through the function and makes it to critical point X. Now
1513 * thread B runs through the whole of the function, returning, assuming
1514 * `instance_size` is set. At that point thread A gets to run and makes it to
1515 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1518 if (class->setup_fields_called)
1521 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1523 * This happens when a generic instance of an unfinished generic typebuilder
1524 * is used as an element type for creating an array type. We can't initialize
1525 * the fields of this class using the fields of gklass, since gklass is not
1526 * finished yet, fields could be added to it later.
1531 mono_class_setup_basic_field_info (class);
1532 top = class->field.count;
1535 mono_class_setup_fields (gtd);
1536 if (gtd->exception_type) {
1537 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1542 class->instance_size = 0;
1544 class->sizes.class_size = 0;
1546 if (class->parent) {
1547 /* For generic instances, class->parent might not have been initialized */
1548 mono_class_init (class->parent);
1549 if (!class->parent->size_inited) {
1550 mono_class_setup_fields (class->parent);
1551 if (class->parent->exception_type) {
1552 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1556 class->instance_size += class->parent->instance_size;
1557 class->min_align = class->parent->min_align;
1558 /* we use |= since it may have been set already */
1559 class->has_references |= class->parent->has_references;
1560 blittable = class->parent->blittable;
1562 class->instance_size = sizeof (MonoObject);
1563 class->min_align = 1;
1566 /* We can't really enable 16 bytes alignment until the GC supports it.
1567 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1568 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1569 Bug #506144 is an example of this issue.
1571 if (class->simd_type)
1572 class->min_align = 16;
1574 /* Get the real size */
1575 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1577 if (explicit_size) {
1578 if ((packing_size & 0xffffff00) != 0) {
1579 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1580 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1583 class->packing_size = packing_size;
1584 real_size += class->instance_size;
1588 if (explicit_size && real_size) {
1589 class->instance_size = MAX (real_size, class->instance_size);
1591 class->blittable = blittable;
1592 mono_memory_barrier ();
1593 class->size_inited = 1;
1594 class->fields_inited = 1;
1595 class->setup_fields_called = 1;
1599 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1602 /* Prevent infinite loops if the class references itself */
1603 class->setup_fields_called = 1;
1605 if (class->generic_container) {
1606 container = class->generic_container;
1608 container = gtd->generic_container;
1609 g_assert (container);
1613 * Fetch all the field information.
1615 for (i = 0; i < top; i++){
1616 int idx = class->field.first + i;
1617 field = &class->fields [i];
1619 field->parent = class;
1622 mono_field_resolve_type (field, &error);
1623 if (!mono_error_ok (&error)) {
1624 /*mono_field_resolve_type already failed class*/
1625 mono_error_cleanup (&error);
1629 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1630 g_assert (field->type);
1633 if (mono_field_is_deleted (field))
1636 MonoClassField *gfield = >d->fields [i];
1637 field->offset = gfield->offset;
1639 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1641 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1642 field->offset = offset;
1644 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1645 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1648 if (field->offset < -1) { /*-1 is used to encode special static fields */
1649 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1652 if (class->generic_container) {
1653 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1659 /* Only do these checks if we still think this type is blittable */
1660 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1661 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1664 MonoClass *field_class = mono_class_from_mono_type (field->type);
1666 mono_class_setup_fields (field_class);
1667 if (field_class->exception_type) {
1668 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1672 if (!field_class || !field_class->blittable)
1677 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1678 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1679 blittable = class->element_class->blittable;
1682 if (mono_type_has_exceptions (field->type)) {
1683 char *class_name = mono_type_get_full_name (class);
1684 char *type_name = mono_type_full_name (field->type);
1686 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1687 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1688 g_free (class_name);
1692 /* The def_value of fields is compute lazily during vtable creation */
1695 if (class == mono_defaults.string_class)
1698 class->blittable = blittable;
1700 if (class->enumtype && !mono_class_enum_basetype (class)) {
1701 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1704 if (explicit_size && real_size) {
1705 class->instance_size = MAX (real_size, class->instance_size);
1708 if (class->exception_type)
1710 mono_class_layout_fields (class);
1712 /*valuetypes can't be neither bigger than 1Mb or empty. */
1713 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1714 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1716 mono_memory_barrier ();
1717 class->fields_inited = 1;
1721 * mono_class_setup_fields_locking:
1722 * @class: The class to initialize
1724 * Initializes the class->fields array of fields.
1725 * Aquires the loader lock.
1728 mono_class_setup_fields_locking (MonoClass *class)
1730 /* This can be checked without locks */
1731 if (class->fields_inited)
1733 mono_loader_lock ();
1734 mono_class_setup_fields (class);
1735 mono_loader_unlock ();
1739 * mono_class_has_references:
1741 * Returns whenever @klass->has_references is set, initializing it if needed.
1742 * Aquires the loader lock.
1745 mono_class_has_references (MonoClass *klass)
1747 if (klass->init_pending) {
1748 /* Be conservative */
1751 mono_class_init (klass);
1753 return klass->has_references;
1758 * mono_type_get_basic_type_from_generic:
1761 * Returns a closed type corresponding to the possibly open type
1765 mono_type_get_basic_type_from_generic (MonoType *type)
1767 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1768 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1769 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1770 return &mono_defaults.object_class->byval_arg;
1775 * mono_class_layout_fields:
1778 * Compute the placement of fields inside an object or struct, according to
1779 * the layout rules and set the following fields in @class:
1780 * - has_references (if the class contains instance references firled or structs that contain references)
1781 * - has_static_refs (same, but for static fields)
1782 * - instance_size (size of the object in memory)
1783 * - class_size (size needed for the static fields)
1784 * - size_inited (flag set when the instance_size is set)
1786 * LOCKING: this is supposed to be called with the loader lock held.
1789 mono_class_layout_fields (MonoClass *class)
1792 const int top = class->field.count;
1793 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1794 guint32 pass, passes, real_size;
1795 gboolean gc_aware_layout = FALSE;
1796 gboolean has_static_fields = FALSE;
1797 MonoClassField *field;
1800 * When we do generic sharing we need to have layout
1801 * information for open generic classes (either with a generic
1802 * context containing type variables or with a generic
1803 * container), so we don't return in that case anymore.
1807 * Enable GC aware auto layout: in this mode, reference
1808 * fields are grouped together inside objects, increasing collector
1810 * Requires that all classes whose layout is known to native code be annotated
1811 * with [StructLayout (LayoutKind.Sequential)]
1812 * Value types have gc_aware_layout disabled by default, as per
1813 * what the default is for other runtimes.
1815 /* corlib is missing [StructLayout] directives in many places */
1816 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1817 if (!class->valuetype)
1818 gc_aware_layout = TRUE;
1821 /* Compute klass->has_references */
1823 * Process non-static fields first, since static fields might recursively
1824 * refer to the class itself.
1826 for (i = 0; i < top; i++) {
1829 field = &class->fields [i];
1831 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1832 ftype = mono_type_get_underlying_type (field->type);
1833 ftype = mono_type_get_basic_type_from_generic (ftype);
1834 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1835 class->has_references = TRUE;
1839 for (i = 0; i < top; i++) {
1842 field = &class->fields [i];
1844 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1845 ftype = mono_type_get_underlying_type (field->type);
1846 ftype = mono_type_get_basic_type_from_generic (ftype);
1847 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1848 class->has_static_refs = TRUE;
1852 for (i = 0; i < top; i++) {
1855 field = &class->fields [i];
1857 ftype = mono_type_get_underlying_type (field->type);
1858 ftype = mono_type_get_basic_type_from_generic (ftype);
1859 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1860 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1861 class->has_static_refs = TRUE;
1863 class->has_references = TRUE;
1868 * Compute field layout and total size (not considering static fields)
1872 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1873 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1875 if (gc_aware_layout)
1880 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1883 if (class->parent) {
1884 mono_class_setup_fields (class->parent);
1885 if (class->parent->exception_type) {
1886 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1889 real_size = class->parent->instance_size;
1891 real_size = sizeof (MonoObject);
1894 for (pass = 0; pass < passes; ++pass) {
1895 for (i = 0; i < top; i++){
1900 field = &class->fields [i];
1902 if (mono_field_is_deleted (field))
1904 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1907 ftype = mono_type_get_underlying_type (field->type);
1908 ftype = mono_type_get_basic_type_from_generic (ftype);
1909 if (gc_aware_layout) {
1910 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1919 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1920 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1921 /* This field is a hack inserted by MCS to empty structures */
1925 size = mono_type_size (field->type, &align);
1927 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1928 align = class->packing_size ? MIN (class->packing_size, align): align;
1929 /* if the field has managed references, we need to force-align it
1932 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1933 align = MAX (align, sizeof (gpointer));
1935 class->min_align = MAX (align, class->min_align);
1936 field->offset = real_size;
1938 field->offset += align - 1;
1939 field->offset &= ~(align - 1);
1941 /*TypeBuilders produce all sort of weird things*/
1942 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1943 real_size = field->offset + size;
1946 class->instance_size = MAX (real_size, class->instance_size);
1948 if (class->instance_size & (class->min_align - 1)) {
1949 class->instance_size += class->min_align - 1;
1950 class->instance_size &= ~(class->min_align - 1);
1954 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1958 for (i = 0; i < top; i++) {
1963 field = &class->fields [i];
1966 * There must be info about all the fields in a type if it
1967 * uses explicit layout.
1969 if (mono_field_is_deleted (field))
1971 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1974 size = mono_type_size (field->type, &align);
1975 align = class->packing_size ? MIN (class->packing_size, align): align;
1976 class->min_align = MAX (align, class->min_align);
1979 * When we get here, field->offset is already set by the
1980 * loader (for either runtime fields or fields loaded from metadata).
1981 * The offset is from the start of the object: this works for both
1982 * classes and valuetypes.
1984 field->offset += sizeof (MonoObject);
1985 ftype = mono_type_get_underlying_type (field->type);
1986 ftype = mono_type_get_basic_type_from_generic (ftype);
1987 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1988 if (field->offset % sizeof (gpointer)) {
1989 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1996 real_size = MAX (real_size, size + field->offset);
1999 if (class->has_references) {
2000 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2002 /* Check for overlapping reference and non-reference fields */
2003 for (i = 0; i < top; i++) {
2006 field = &class->fields [i];
2008 if (mono_field_is_deleted (field))
2010 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2012 ftype = mono_type_get_underlying_type (field->type);
2013 if (MONO_TYPE_IS_REFERENCE (ftype))
2014 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2016 for (i = 0; i < top; i++) {
2017 field = &class->fields [i];
2019 if (mono_field_is_deleted (field))
2021 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2024 // FIXME: Too much code does this
2026 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2027 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);
2028 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2032 g_free (ref_bitmap);
2035 class->instance_size = MAX (real_size, class->instance_size);
2036 if (class->instance_size & (class->min_align - 1)) {
2037 class->instance_size += class->min_align - 1;
2038 class->instance_size &= ~(class->min_align - 1);
2044 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2046 * For small structs, set min_align to at least the struct size to improve
2047 * performance, and since the JIT memset/memcpy code assumes this and generates
2048 * unaligned accesses otherwise. See #78990 for a testcase.
2050 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2051 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2054 mono_memory_barrier ();
2055 class->size_inited = 1;
2058 * Compute static field layout and size
2060 for (i = 0; i < top; i++){
2064 field = &class->fields [i];
2066 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2068 if (mono_field_is_deleted (field))
2071 if (mono_type_has_exceptions (field->type)) {
2072 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2076 has_static_fields = TRUE;
2078 size = mono_type_size (field->type, &align);
2079 field->offset = class->sizes.class_size;
2080 /*align is always non-zero here*/
2081 field->offset += align - 1;
2082 field->offset &= ~(align - 1);
2083 class->sizes.class_size = field->offset + size;
2086 if (has_static_fields && class->sizes.class_size == 0)
2087 /* Simplify code which depends on class_size != 0 if the class has static fields */
2088 class->sizes.class_size = 8;
2092 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2096 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2097 method->klass = class;
2098 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2099 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2100 method->signature = sig;
2101 method->name = name;
2104 if (name [0] == '.') {
2105 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2107 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2113 * mono_class_setup_methods:
2116 * Initializes the 'methods' array in CLASS.
2117 * Calling this method should be avoided if possible since it allocates a lot
2118 * of long-living MonoMethod structures.
2119 * Methods belonging to an interface are assigned a sequential slot starting
2122 * On failure this function sets class->exception_type
2125 mono_class_setup_methods (MonoClass *class)
2128 MonoMethod **methods;
2133 if (class->generic_class) {
2135 MonoClass *gklass = class->generic_class->container_class;
2137 mono_class_init (gklass);
2138 if (!gklass->exception_type)
2139 mono_class_setup_methods (gklass);
2140 if (gklass->exception_type) {
2141 /* FIXME make exception_data less opaque so it's possible to dup it here */
2142 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2146 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2147 count = gklass->method.count;
2148 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2150 for (i = 0; i < count; i++) {
2151 methods [i] = mono_class_inflate_generic_method_full_checked (
2152 gklass->methods [i], class, mono_class_get_context (class), &error);
2153 if (!mono_error_ok (&error)) {
2154 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2155 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)));
2158 mono_error_cleanup (&error);
2162 } else if (class->rank) {
2164 MonoMethod *amethod;
2165 MonoMethodSignature *sig;
2166 int count_generic = 0, first_generic = 0;
2168 gboolean jagged_ctor = FALSE;
2170 count = 3 + (class->rank > 1? 2: 1);
2172 mono_class_setup_interfaces (class, &error);
2173 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2175 if (class->rank == 1 && class->element_class->rank) {
2177 class->method.count ++;
2180 if (class->interface_count) {
2181 count_generic = generic_array_methods (class);
2182 first_generic = count;
2183 count += class->interface_count * count_generic;
2186 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2188 sig = mono_metadata_signature_alloc (class->image, class->rank);
2189 sig->ret = &mono_defaults.void_class->byval_arg;
2190 sig->pinvoke = TRUE;
2191 sig->hasthis = TRUE;
2192 for (i = 0; i < class->rank; ++i)
2193 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2195 amethod = create_array_method (class, ".ctor", sig);
2196 methods [method_num++] = amethod;
2197 if (class->rank > 1) {
2198 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2199 sig->ret = &mono_defaults.void_class->byval_arg;
2200 sig->pinvoke = TRUE;
2201 sig->hasthis = TRUE;
2202 for (i = 0; i < class->rank * 2; ++i)
2203 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2205 amethod = create_array_method (class, ".ctor", sig);
2206 methods [method_num++] = amethod;
2210 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2211 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2212 sig->ret = &mono_defaults.void_class->byval_arg;
2213 sig->pinvoke = TRUE;
2214 sig->hasthis = TRUE;
2215 for (i = 0; i < class->rank + 1; ++i)
2216 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2217 amethod = create_array_method (class, ".ctor", sig);
2218 methods [method_num++] = amethod;
2221 /* element Get (idx11, [idx2, ...]) */
2222 sig = mono_metadata_signature_alloc (class->image, class->rank);
2223 sig->ret = &class->element_class->byval_arg;
2224 sig->pinvoke = TRUE;
2225 sig->hasthis = TRUE;
2226 for (i = 0; i < class->rank; ++i)
2227 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2228 amethod = create_array_method (class, "Get", sig);
2229 methods [method_num++] = amethod;
2230 /* element& Address (idx11, [idx2, ...]) */
2231 sig = mono_metadata_signature_alloc (class->image, class->rank);
2232 sig->ret = &class->element_class->this_arg;
2233 sig->pinvoke = TRUE;
2234 sig->hasthis = TRUE;
2235 for (i = 0; i < class->rank; ++i)
2236 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2237 amethod = create_array_method (class, "Address", sig);
2238 methods [method_num++] = amethod;
2239 /* void Set (idx11, [idx2, ...], element) */
2240 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2241 sig->ret = &mono_defaults.void_class->byval_arg;
2242 sig->pinvoke = TRUE;
2243 sig->hasthis = TRUE;
2244 for (i = 0; i < class->rank; ++i)
2245 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2246 sig->params [i] = &class->element_class->byval_arg;
2247 amethod = create_array_method (class, "Set", sig);
2248 methods [method_num++] = amethod;
2250 for (i = 0; i < class->interface_count; i++)
2251 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2255 count = class->method.count;
2256 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2257 for (i = 0; i < count; ++i) {
2258 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2259 methods [i] = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | idx, class, NULL, &error);
2261 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)));
2262 mono_error_cleanup (&error);
2267 if (MONO_CLASS_IS_INTERFACE (class)) {
2269 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2270 for (i = 0; i < count; ++i) {
2271 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2272 methods [i]->slot = slot++;
2276 mono_image_lock (class->image);
2278 if (!class->methods) {
2279 class->method.count = count;
2281 /* Needed because of the double-checking locking pattern */
2282 mono_memory_barrier ();
2284 class->methods = methods;
2287 mono_image_unlock (class->image);
2291 * mono_class_get_method_by_index:
2293 * Returns class->methods [index], initializing class->methods if neccesary.
2295 * LOCKING: Acquires the loader lock.
2298 mono_class_get_method_by_index (MonoClass *class, int index)
2301 /* Avoid calling setup_methods () if possible */
2302 if (class->generic_class && !class->methods) {
2303 MonoClass *gklass = class->generic_class->container_class;
2306 m = mono_class_inflate_generic_method_full_checked (
2307 gklass->methods [index], class, mono_class_get_context (class), &error);
2308 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2310 * If setup_methods () is called later for this class, no duplicates are created,
2311 * since inflate_generic_method guarantees that only one instance of a method
2312 * is created for each context.
2315 mono_class_setup_methods (class);
2316 g_assert (m == class->methods [index]);
2320 mono_class_setup_methods (class);
2321 if (class->exception_type) /*FIXME do proper error handling*/
2323 g_assert (index >= 0 && index < class->method.count);
2324 return class->methods [index];
2329 * mono_class_get_inflated_method:
2331 * Given an inflated class CLASS and a method METHOD which should be a method of
2332 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2335 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2337 MonoClass *gklass = class->generic_class->container_class;
2340 g_assert (method->klass == gklass);
2342 mono_class_setup_methods (gklass);
2343 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2345 for (i = 0; i < gklass->method.count; ++i) {
2346 if (gklass->methods [i] == method) {
2347 if (class->methods) {
2348 return class->methods [i];
2351 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2352 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2362 * mono_class_get_vtable_entry:
2364 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2365 * LOCKING: Acquires the loader lock.
2368 mono_class_get_vtable_entry (MonoClass *class, int offset)
2372 if (class->rank == 1) {
2374 * szarrays do not overwrite any methods of Array, so we can avoid
2375 * initializing their vtables in some cases.
2377 mono_class_setup_vtable (class->parent);
2378 if (offset < class->parent->vtable_size)
2379 return class->parent->vtable [offset];
2382 if (class->generic_class) {
2384 MonoClass *gklass = class->generic_class->container_class;
2385 mono_class_setup_vtable (gklass);
2386 m = gklass->vtable [offset];
2388 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2389 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2391 mono_class_setup_vtable (class);
2392 if (class->exception_type)
2394 m = class->vtable [offset];
2401 * mono_class_get_vtable_size:
2403 * Return the vtable size for KLASS.
2406 mono_class_get_vtable_size (MonoClass *klass)
2408 mono_class_setup_vtable (klass);
2410 return klass->vtable_size;
2414 * mono_class_setup_properties:
2416 * Initialize class->ext.property and class->ext.properties.
2418 * This method can fail the class.
2421 mono_class_setup_properties (MonoClass *class)
2423 guint startm, endm, i, j;
2424 guint32 cols [MONO_PROPERTY_SIZE];
2425 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2426 MonoProperty *properties;
2430 if (class->ext && class->ext->properties)
2433 if (class->generic_class) {
2434 MonoClass *gklass = class->generic_class->container_class;
2436 mono_class_init (gklass);
2437 mono_class_setup_properties (gklass);
2438 if (gklass->exception_type) {
2439 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2443 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2445 for (i = 0; i < gklass->ext->property.count; i++) {
2447 MonoProperty *prop = &properties [i];
2449 *prop = gklass->ext->properties [i];
2452 prop->get = mono_class_inflate_generic_method_full_checked (
2453 prop->get, class, mono_class_get_context (class), &error);
2455 prop->set = mono_class_inflate_generic_method_full_checked (
2456 prop->set, class, mono_class_get_context (class), &error);
2458 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2459 prop->parent = class;
2462 first = gklass->ext->property.first;
2463 count = gklass->ext->property.count;
2465 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2466 count = last - first;
2469 mono_class_setup_methods (class);
2470 if (class->exception_type)
2474 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2475 for (i = first; i < last; ++i) {
2476 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2477 properties [i - first].parent = class;
2478 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2479 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2481 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2482 for (j = startm; j < endm; ++j) {
2485 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2487 if (class->image->uncompressed_metadata) {
2489 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2490 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2491 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2493 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2496 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2497 case METHOD_SEMANTIC_SETTER:
2498 properties [i - first].set = method;
2500 case METHOD_SEMANTIC_GETTER:
2501 properties [i - first].get = method;
2510 mono_class_alloc_ext (class);
2512 mono_image_lock (class->image);
2514 if (class->ext->properties) {
2515 /* We leak 'properties' which was allocated from the image mempool */
2516 mono_image_unlock (class->image);
2520 class->ext->property.first = first;
2521 class->ext->property.count = count;
2523 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2524 mono_memory_barrier ();
2526 /* Leave this assignment as the last op in the function */
2527 class->ext->properties = properties;
2529 mono_image_unlock (class->image);
2533 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2535 MonoMethod **om, **retval;
2538 for (om = methods, count = 0; *om; ++om, ++count)
2541 retval = g_new0 (MonoMethod*, count + 1);
2543 for (om = methods, count = 0; *om; ++om, ++count) {
2545 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2546 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2552 /*This method can fail the class.*/
2554 mono_class_setup_events (MonoClass *class)
2557 guint startm, endm, i, j;
2558 guint32 cols [MONO_EVENT_SIZE];
2559 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2563 if (class->ext && class->ext->events)
2566 if (class->generic_class) {
2567 MonoClass *gklass = class->generic_class->container_class;
2568 MonoGenericContext *context = NULL;
2570 mono_class_setup_events (gklass);
2571 if (gklass->exception_type) {
2572 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2576 first = gklass->ext->event.first;
2577 count = gklass->ext->event.count;
2579 events = mono_class_new0 (class, MonoEvent, count);
2582 context = mono_class_get_context (class);
2584 for (i = 0; i < count; i++) {
2586 MonoEvent *event = &events [i];
2587 MonoEvent *gevent = &gklass->ext->events [i];
2589 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2591 event->parent = class;
2592 event->name = gevent->name;
2593 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2594 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2595 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2596 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2597 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2598 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2600 #ifndef MONO_SMALL_CONFIG
2601 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2603 event->attrs = gevent->attrs;
2606 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2607 count = last - first;
2610 mono_class_setup_methods (class);
2611 if (class->exception_type) {
2612 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2617 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2618 for (i = first; i < last; ++i) {
2619 MonoEvent *event = &events [i - first];
2621 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2622 event->parent = class;
2623 event->attrs = cols [MONO_EVENT_FLAGS];
2624 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2626 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2627 for (j = startm; j < endm; ++j) {
2630 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2632 if (class->image->uncompressed_metadata) {
2634 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2635 method = mono_get_method_checked (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class, NULL, &error);
2636 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2638 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2641 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2642 case METHOD_SEMANTIC_ADD_ON:
2643 event->add = method;
2645 case METHOD_SEMANTIC_REMOVE_ON:
2646 event->remove = method;
2648 case METHOD_SEMANTIC_FIRE:
2649 event->raise = method;
2651 case METHOD_SEMANTIC_OTHER: {
2652 #ifndef MONO_SMALL_CONFIG
2655 if (event->other == NULL) {
2656 event->other = g_new0 (MonoMethod*, 2);
2658 while (event->other [n])
2660 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2662 event->other [n] = method;
2663 /* NULL terminated */
2664 event->other [n + 1] = NULL;
2675 mono_class_alloc_ext (class);
2677 mono_image_lock (class->image);
2679 if (class->ext->events) {
2680 mono_image_unlock (class->image);
2684 class->ext->event.first = first;
2685 class->ext->event.count = count;
2687 /* Flush any pending writes as we do double checked locking on class->ext.events */
2688 mono_memory_barrier ();
2690 /* Leave this assignment as the last op in the function */
2691 class->ext->events = events;
2693 mono_image_unlock (class->image);
2697 * Global pool of interface IDs, represented as a bitset.
2698 * LOCKING: Protected by the classes lock.
2700 static MonoBitSet *global_interface_bitset = NULL;
2703 * mono_unload_interface_ids:
2704 * @bitset: bit set of interface IDs
2706 * When an image is unloaded, the interface IDs associated with
2707 * the image are put back in the global pool of IDs so the numbers
2711 mono_unload_interface_ids (MonoBitSet *bitset)
2714 mono_bitset_sub (global_interface_bitset, bitset);
2719 mono_unload_interface_id (MonoClass *class)
2721 if (global_interface_bitset && class->interface_id) {
2723 mono_bitset_clear (global_interface_bitset, class->interface_id);
2729 * mono_get_unique_iid:
2732 * Assign a unique integer ID to the interface represented by @class.
2733 * The ID will positive and as small as possible.
2734 * LOCKING: Acquires the classes lock.
2735 * Returns: the new ID.
2738 mono_get_unique_iid (MonoClass *class)
2742 g_assert (MONO_CLASS_IS_INTERFACE (class));
2746 if (!global_interface_bitset) {
2747 global_interface_bitset = mono_bitset_new (128, 0);
2750 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2752 int old_size = mono_bitset_size (global_interface_bitset);
2753 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2754 mono_bitset_free (global_interface_bitset);
2755 global_interface_bitset = new_set;
2758 mono_bitset_set (global_interface_bitset, iid);
2759 /* set the bit also in the per-image set */
2760 if (!class->generic_class) {
2761 if (class->image->interface_bitset) {
2762 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2763 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2764 mono_bitset_free (class->image->interface_bitset);
2765 class->image->interface_bitset = new_set;
2768 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2770 mono_bitset_set (class->image->interface_bitset, iid);
2775 #ifndef MONO_SMALL_CONFIG
2776 if (mono_print_vtable) {
2778 char *type_name = mono_type_full_name (&class->byval_arg);
2779 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2780 generic_id = class->generic_class->context.class_inst->id;
2781 g_assert (generic_id != 0);
2785 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2790 g_assert (iid <= 65535);
2795 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2800 mono_class_setup_interfaces (klass, error);
2801 if (!mono_error_ok (error))
2804 for (i = 0; i < klass->interface_count; i++) {
2805 ic = klass->interfaces [i];
2808 *res = g_ptr_array_new ();
2809 g_ptr_array_add (*res, ic);
2810 mono_class_init (ic);
2811 if (ic->exception_type) {
2812 mono_error_set_type_load_class (error, ic, "Error Loading class");
2816 collect_implemented_interfaces_aux (ic, res, error);
2817 if (!mono_error_ok (error))
2823 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2825 GPtrArray *res = NULL;
2827 collect_implemented_interfaces_aux (klass, &res, error);
2828 if (!mono_error_ok (error)) {
2830 g_ptr_array_free (res, TRUE);
2837 compare_interface_ids (const void *p_key, const void *p_element) {
2838 const MonoClass *key = p_key;
2839 const MonoClass *element = *(MonoClass**) p_element;
2841 return (key->interface_id - element->interface_id);
2844 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2846 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2847 MonoClass **result = mono_binary_search (
2849 klass->interfaces_packed,
2850 klass->interface_offsets_count,
2851 sizeof (MonoClass *),
2852 compare_interface_ids);
2854 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2861 * mono_class_interface_offset_with_variance:
2863 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2864 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2866 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2868 * FIXME figure out MS disambiguation rules and fix this function.
2871 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2872 int i = mono_class_interface_offset (klass, itf);
2873 *non_exact_match = FALSE;
2877 if (!mono_class_has_variant_generic_params (itf))
2880 for (i = 0; i < klass->interface_offsets_count; i++) {
2881 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2882 *non_exact_match = TRUE;
2883 return klass->interface_offsets_packed [i];
2891 print_implemented_interfaces (MonoClass *klass) {
2894 GPtrArray *ifaces = NULL;
2896 int ancestor_level = 0;
2898 name = mono_type_get_full_name (klass);
2899 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2902 for (i = 0; i < klass->interface_offsets_count; i++)
2903 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2904 klass->interfaces_packed [i]->interface_id,
2905 klass->interface_offsets_packed [i],
2906 klass->interfaces_packed [i]->method.count,
2907 klass->interfaces_packed [i]->name_space,
2908 klass->interfaces_packed [i]->name );
2909 printf ("Interface flags: ");
2910 for (i = 0; i <= klass->max_interface_id; i++)
2911 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2912 printf ("(%d,T)", i);
2914 printf ("(%d,F)", i);
2916 printf ("Dump interface flags:");
2917 #ifdef COMPRESSED_INTERFACE_BITMAP
2919 const uint8_t* p = klass->interface_bitmap;
2920 i = klass->max_interface_id;
2922 printf (" %d x 00 %02X", p [0], p [1]);
2928 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2929 printf (" %02X", klass->interface_bitmap [i]);
2932 while (klass != NULL) {
2933 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2934 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2935 if (!mono_error_ok (&error)) {
2936 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2937 mono_error_cleanup (&error);
2938 } else if (ifaces) {
2939 for (i = 0; i < ifaces->len; i++) {
2940 MonoClass *ic = g_ptr_array_index (ifaces, i);
2941 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2942 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2944 mono_class_interface_offset (klass, ic),
2949 g_ptr_array_free (ifaces, TRUE);
2952 klass = klass->parent;
2957 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2960 args [0] = &arg0->byval_arg;
2962 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2966 array_class_get_if_rank (MonoClass *class, guint rank)
2968 return rank ? mono_array_class_get (class, rank) : class;
2972 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2974 valuetype_types [0] = eclass;
2975 if (eclass == mono_defaults.int16_class)
2976 valuetype_types [1] = mono_defaults.uint16_class;
2977 else if (eclass == mono_defaults.uint16_class)
2978 valuetype_types [1] = mono_defaults.int16_class;
2979 else if (eclass == mono_defaults.int32_class)
2980 valuetype_types [1] = mono_defaults.uint32_class;
2981 else if (eclass == mono_defaults.uint32_class)
2982 valuetype_types [1] = mono_defaults.int32_class;
2983 else if (eclass == mono_defaults.int64_class)
2984 valuetype_types [1] = mono_defaults.uint64_class;
2985 else if (eclass == mono_defaults.uint64_class)
2986 valuetype_types [1] = mono_defaults.int64_class;
2987 else if (eclass == mono_defaults.byte_class)
2988 valuetype_types [1] = mono_defaults.sbyte_class;
2989 else if (eclass == mono_defaults.sbyte_class)
2990 valuetype_types [1] = mono_defaults.byte_class;
2991 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2992 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2995 /* this won't be needed once bug #325495 is completely fixed
2996 * though we'll need something similar to know which interfaces to allow
2997 * in arrays when they'll be lazyly created
2999 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3000 * MS returns diferrent types based on which instance is called. For example:
3001 * object obj = new byte[10][];
3002 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3003 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3006 * Fixing this should kill quite some code, save some bits and improve compatibility.
3009 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
3011 MonoClass *eclass = class->element_class;
3012 static MonoClass* generic_icollection_class = NULL;
3013 static MonoClass* generic_ienumerable_class = NULL;
3014 static MonoClass* generic_ienumerator_class = NULL;
3015 static MonoClass* generic_ireadonlylist_class = NULL;
3016 static MonoClass* generic_ireadonlycollection_class = NULL;
3017 MonoClass *valuetype_types[2] = { NULL, NULL };
3018 MonoClass **interfaces = NULL;
3019 int i, nifaces, interface_count, real_count, original_rank;
3021 gboolean internal_enumerator;
3022 gboolean eclass_is_valuetype;
3024 if (!mono_defaults.generic_ilist_class) {
3028 internal_enumerator = FALSE;
3029 eclass_is_valuetype = FALSE;
3030 original_rank = eclass->rank;
3031 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3032 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3034 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3036 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3037 original_rank = eclass->rank;
3039 eclass = eclass->element_class;
3040 internal_enumerator = TRUE;
3041 *is_enumerator = TRUE;
3049 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3050 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3052 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3054 if (!generic_icollection_class) {
3055 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3056 "System.Collections.Generic", "ICollection`1");
3057 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3058 "System.Collections.Generic", "IEnumerable`1");
3059 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3060 "System.Collections.Generic", "IEnumerator`1");
3061 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3062 "System.Collections.Generic", "IReadOnlyList`1");
3063 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3064 "System.Collections.Generic", "IReadOnlyCollection`1");
3067 mono_class_init (eclass);
3070 * Arrays in 2.0 need to implement a number of generic interfaces
3071 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3072 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3073 * We collect the types needed to build the
3074 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3075 * the generic interfaces needed to implement.
3077 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3078 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3080 if (eclass->valuetype) {
3081 nifaces = generic_ireadonlylist_class ? 5 : 3;
3082 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3084 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3085 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3086 if (internal_enumerator) {
3088 if (valuetype_types [1])
3092 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3093 interfaces [0] = valuetype_types [0];
3094 if (valuetype_types [1])
3095 interfaces [nifaces] = valuetype_types [1];
3097 eclass_is_valuetype = TRUE;
3100 int idepth = eclass->idepth;
3101 if (!internal_enumerator)
3103 nifaces = generic_ireadonlylist_class ? 2 : 3;
3105 // FIXME: This doesn't seem to work/required for generic params
3106 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3107 mono_class_setup_interface_offsets (eclass);
3109 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3110 /* we add object for interfaces and the supertypes for the other
3111 * types. The last of the supertypes is the element class itself which we
3112 * already created the explicit interfaces for (so we include it for IEnumerator
3113 * and exclude it for arrays).
3115 if (MONO_CLASS_IS_INTERFACE (eclass))
3118 interface_count += idepth;
3119 if (eclass->rank && eclass->element_class->valuetype) {
3120 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3121 if (valuetype_types [1])
3124 /* IList, ICollection, IEnumerable, IReadOnlyList */
3125 interface_count *= nifaces;
3126 real_count = interface_count;
3127 if (internal_enumerator) {
3128 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3129 if (valuetype_types [1])
3132 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3133 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3134 interfaces [0] = mono_defaults.object_class;
3138 for (i = 0; i < idepth; i++) {
3139 mono_class_init (eclass->supertypes [i]);
3140 interfaces [j] = eclass->supertypes [i];
3144 if (all_interfaces) {
3145 for (i = 0; i < eclass->interface_offsets_count; i++) {
3146 interfaces [j] = eclass->interfaces_packed [i];
3150 for (i = 0; i < eclass->interface_count; i++) {
3151 interfaces [j] = eclass->interfaces [i];
3155 if (valuetype_types [1]) {
3156 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3161 /* instantiate the generic interfaces */
3162 for (i = 0; i < interface_count; i += nifaces) {
3163 MonoClass *iface = interfaces [i];
3165 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3166 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3168 if (eclass->valuetype) {
3169 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3170 if (generic_ireadonlylist_class) {
3171 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3172 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3175 if (!generic_ireadonlylist_class)
3176 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3179 if (internal_enumerator) {
3181 /* instantiate IEnumerator<iface> */
3182 for (i = 0; i < interface_count; i++) {
3183 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3185 j = interface_count;
3186 if (!eclass_is_valuetype) {
3187 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3188 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3191 for (i = 0; i < eclass->idepth; i++) {
3192 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3196 for (i = 0; i < eclass->interface_offsets_count; i++) {
3197 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3201 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3203 if (valuetype_types [1])
3204 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3208 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3209 for (i = 0; i < real_count; ++i) {
3210 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3211 g_print ("%s implements %s\n", type_name, name);
3222 find_array_interface (MonoClass *klass, const char *name)
3225 for (i = 0; i < klass->interface_count; ++i) {
3226 if (strcmp (klass->interfaces [i]->name, name) == 0)
3233 * Return the number of virtual methods.
3234 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3235 * Return -1 on failure.
3236 * FIXME It would be nice if this information could be cached somewhere.
3239 count_virtual_methods (MonoClass *class)
3243 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3245 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3246 mono_class_setup_methods (class);
3247 if (class->exception_type)
3250 for (i = 0; i < class->method.count; ++i) {
3251 flags = class->methods [i]->flags;
3252 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3256 for (i = 0; i < class->method.count; ++i) {
3257 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3259 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3267 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3275 m = (l + num_ifaces) / 2;
3276 if (interfaces_full [m] == ic)
3278 if (l == num_ifaces)
3280 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3289 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3291 int i = find_interface (num_ifaces, interfaces_full, ic);
3293 return interface_offsets_full [i];
3298 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3300 int i = find_interface (num_ifaces, interfaces_full, ic);
3304 interface_offsets_full [i] = offset;
3307 for (i = 0; i < num_ifaces; ++i) {
3308 if (interfaces_full [i]) {
3310 if (interfaces_full [i]->interface_id < ic->interface_id)
3313 while (end < num_ifaces && interfaces_full [end]) end++;
3314 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3315 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3317 interfaces_full [i] = ic;
3318 interface_offsets_full [i] = offset;
3324 #ifdef COMPRESSED_INTERFACE_BITMAP
3327 * Compressed interface bitmap design.
3329 * Interface bitmaps take a large amount of memory, because their size is
3330 * linear with the maximum interface id assigned in the process (each interface
3331 * is assigned a unique id as it is loaded). The number of interface classes
3332 * is high because of the many implicit interfaces implemented by arrays (we'll
3333 * need to lazy-load them in the future).
3334 * Most classes implement a very small number of interfaces, so the bitmap is
3335 * sparse. This bitmap needs to be checked by interface casts, so access to the
3336 * needed bit must be fast and doable with few jit instructions.
3338 * The current compression format is as follows:
3339 * *) it is a sequence of one or more two-byte elements
3340 * *) the first byte in the element is the count of empty bitmap bytes
3341 * at the current bitmap position
3342 * *) the second byte in the element is an actual bitmap byte at the current
3345 * As an example, the following compressed bitmap bytes:
3346 * 0x07 0x01 0x00 0x7
3347 * correspond to the following bitmap:
3348 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3350 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3351 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3352 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3356 * mono_compress_bitmap:
3357 * @dest: destination buffer
3358 * @bitmap: bitmap buffer
3359 * @size: size of @bitmap in bytes
3361 * This is a mono internal function.
3362 * The @bitmap data is compressed into a format that is small but
3363 * still searchable in few instructions by the JIT and runtime.
3364 * The compressed data is stored in the buffer pointed to by the
3365 * @dest array. Passing a #NULL value for @dest allows to just compute
3366 * the size of the buffer.
3367 * This compression algorithm assumes the bits set in the bitmap are
3368 * few and far between, like in interface bitmaps.
3369 * Returns: the size of the compressed bitmap in bytes.
3372 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3376 const uint8_t *end = bitmap + size;
3377 while (bitmap < end) {
3378 if (*bitmap || numz == 255) {
3402 * mono_class_interface_match:
3403 * @bitmap: a compressed bitmap buffer
3404 * @id: the index to check in the bitmap
3406 * This is a mono internal function.
3407 * Checks if a bit is set in a compressed interface bitmap. @id must
3408 * be already checked for being smaller than the maximum id encoded in the
3411 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3415 mono_class_interface_match (const uint8_t *bitmap, int id)
3418 id -= bitmap [0] * 8;
3422 return bitmap [1] & (1 << id);
3431 * LOCKING: this is supposed to be called with the loader lock held.
3432 * Return -1 on failure and set exception_type
3435 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3439 int i, j, max_iid, num_ifaces;
3440 MonoClass **interfaces_full = NULL;
3441 int *interface_offsets_full = NULL;
3443 GPtrArray **ifaces_array = NULL;
3444 int interface_offsets_count;
3445 MonoClass **array_interfaces = NULL;
3446 int num_array_interfaces;
3447 int is_enumerator = FALSE;
3449 mono_class_setup_supertypes (class);
3451 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3452 * implicit interfaces have the property that they are assigned the same slot in the
3453 * vtables for compatible interfaces
3455 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3457 /* compute maximum number of slots and maximum interface id */
3459 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3460 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3461 for (j = 0; j < class->idepth; j++) {
3462 k = class->supertypes [j];
3463 num_ifaces += k->interface_count;
3464 for (i = 0; i < k->interface_count; i++) {
3465 ic = k->interfaces [i];
3468 mono_class_init (ic);
3470 if (max_iid < ic->interface_id)
3471 max_iid = ic->interface_id;
3473 ifaces = mono_class_get_implemented_interfaces (k, &error);
3474 if (!mono_error_ok (&error)) {
3475 char *name = mono_type_get_full_name (k);
3476 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)));
3478 mono_error_cleanup (&error);
3483 num_ifaces += ifaces->len;
3484 for (i = 0; i < ifaces->len; ++i) {
3485 ic = g_ptr_array_index (ifaces, i);
3486 if (max_iid < ic->interface_id)
3487 max_iid = ic->interface_id;
3489 ifaces_array [j] = ifaces;
3493 for (i = 0; i < num_array_interfaces; ++i) {
3494 ic = array_interfaces [i];
3495 mono_class_init (ic);
3496 if (max_iid < ic->interface_id)
3497 max_iid = ic->interface_id;
3500 if (MONO_CLASS_IS_INTERFACE (class)) {
3502 if (max_iid < class->interface_id)
3503 max_iid = class->interface_id;
3505 class->max_interface_id = max_iid;
3506 /* compute vtable offset for interfaces */
3507 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3508 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3510 for (i = 0; i < num_ifaces; i++) {
3511 interface_offsets_full [i] = -1;
3514 /* skip the current class */
3515 for (j = 0; j < class->idepth - 1; j++) {
3516 k = class->supertypes [j];
3517 ifaces = ifaces_array [j];
3520 for (i = 0; i < ifaces->len; ++i) {
3522 ic = g_ptr_array_index (ifaces, i);
3524 /*Force the sharing of interface offsets between parent and subtypes.*/
3525 io = mono_class_interface_offset (k, ic);
3527 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3532 g_assert (class == class->supertypes [class->idepth - 1]);
3533 ifaces = ifaces_array [class->idepth - 1];
3535 for (i = 0; i < ifaces->len; ++i) {
3537 ic = g_ptr_array_index (ifaces, i);
3538 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3540 count = count_virtual_methods (ic);
3542 char *name = mono_type_get_full_name (ic);
3543 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3552 if (MONO_CLASS_IS_INTERFACE (class))
3553 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3555 if (num_array_interfaces) {
3556 if (is_enumerator) {
3557 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3558 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3559 g_assert (ienumerator_offset >= 0);
3560 for (i = 0; i < num_array_interfaces; ++i) {
3561 ic = array_interfaces [i];
3562 if (strcmp (ic->name, "IEnumerator`1") == 0)
3563 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3565 g_assert_not_reached ();
3566 /*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);*/
3569 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3570 int ilist_iface_idx = find_array_interface (class, "IList`1");
3571 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3572 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3573 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3574 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3575 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3576 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3577 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3578 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3579 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3580 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3581 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3582 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3583 for (i = 0; i < num_array_interfaces; ++i) {
3585 ic = array_interfaces [i];
3586 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3587 offset = ilist_offset;
3588 else if (strcmp (ic->name, "ICollection`1") == 0)
3589 offset = icollection_offset;
3590 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3591 offset = ienumerable_offset;
3592 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3593 offset = ireadonlylist_offset;
3594 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3595 offset = ireadonlycollection_offset;
3597 g_assert_not_reached ();
3598 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3599 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3604 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3605 if (interface_offsets_full [i] != -1) {
3606 interface_offsets_count ++;
3611 * We might get called multiple times:
3612 * - mono_class_init ()
3613 * - mono_class_setup_vtable ().
3614 * - mono_class_setup_interface_offsets ().
3615 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3616 * means we have to overwrite those when called from other places (#4440).
3618 if (class->interfaces_packed && !overwrite) {
3619 g_assert (class->interface_offsets_count == interface_offsets_count);
3623 class->interface_offsets_count = interface_offsets_count;
3624 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3625 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3626 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3627 #ifdef COMPRESSED_INTERFACE_BITMAP
3628 bitmap = g_malloc0 (bsize);
3630 bitmap = mono_class_alloc0 (class, bsize);
3632 for (i = 0; i < interface_offsets_count; i++) {
3633 int id = interfaces_full [i]->interface_id;
3634 bitmap [id >> 3] |= (1 << (id & 7));
3635 class->interfaces_packed [i] = interfaces_full [i];
3636 class->interface_offsets_packed [i] = interface_offsets_full [i];
3637 /*if (num_array_interfaces)
3638 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&class->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3640 #ifdef COMPRESSED_INTERFACE_BITMAP
3641 i = mono_compress_bitmap (NULL, bitmap, bsize);
3642 class->interface_bitmap = mono_class_alloc0 (class, i);
3643 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3646 class->interface_bitmap = bitmap;
3651 g_free (interfaces_full);
3652 g_free (interface_offsets_full);
3653 g_free (array_interfaces);
3654 for (i = 0; i < class->idepth; i++) {
3655 ifaces = ifaces_array [i];
3657 g_ptr_array_free (ifaces, TRUE);
3659 g_free (ifaces_array);
3661 //printf ("JUST DONE: ");
3662 //print_implemented_interfaces (class);
3668 * Setup interface offsets for interfaces.
3670 * - class->max_interface_id
3671 * - class->interface_offsets_count
3672 * - class->interfaces_packed
3673 * - class->interface_offsets_packed
3674 * - class->interface_bitmap
3676 * This function can fail @class.
3679 mono_class_setup_interface_offsets (MonoClass *class)
3681 mono_loader_lock ();
3683 setup_interface_offsets (class, 0, FALSE);
3685 mono_loader_unlock ();
3688 /*Checks if @klass has @parent as one of it's parents type gtd
3692 * Bar<T> : Foo<Bar<Bar<T>>>
3696 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3698 klass = mono_class_get_generic_type_definition (klass);
3699 parent = mono_class_get_generic_type_definition (parent);
3700 mono_class_setup_supertypes (klass);
3701 mono_class_setup_supertypes (parent);
3703 return klass->idepth >= parent->idepth &&
3704 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3708 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3710 MonoGenericInst *ginst;
3712 if (!class->generic_class) {
3713 mono_class_setup_vtable_full (class, in_setup);
3714 return class->exception_type == 0;
3717 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3718 if (class->generic_class->container_class->exception_type) {
3719 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3723 ginst = class->generic_class->context.class_inst;
3724 for (i = 0; i < ginst->type_argc; ++i) {
3726 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3728 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3729 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3730 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3732 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3733 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3741 * mono_class_setup_vtable:
3743 * Creates the generic vtable of CLASS.
3744 * Initializes the following fields in MonoClass:
3747 * Plus all the fields initialized by setup_interface_offsets ().
3748 * If there is an error during vtable construction, class->exception_type is set.
3750 * LOCKING: Acquires the loader lock.
3753 mono_class_setup_vtable (MonoClass *class)
3755 mono_class_setup_vtable_full (class, NULL);
3759 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3761 MonoMethod **overrides;
3762 MonoGenericContext *context;
3770 if (MONO_CLASS_IS_INTERFACE (class)) {
3771 /* This sets method->slot for all methods if this is an interface */
3772 mono_class_setup_methods (class);
3776 if (class->exception_type)
3779 if (g_list_find (in_setup, class))
3782 mono_loader_lock ();
3784 if (class->vtable) {
3785 mono_loader_unlock ();
3789 mono_stats.generic_vtable_count ++;
3790 in_setup = g_list_prepend (in_setup, class);
3792 if (class->generic_class) {
3793 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3794 mono_loader_unlock ();
3795 g_list_remove (in_setup, class);
3799 context = mono_class_get_context (class);
3800 type_token = class->generic_class->container_class->type_token;
3802 context = (MonoGenericContext *) class->generic_container;
3803 type_token = class->type_token;
3806 if (image_is_dynamic (class->image)) {
3807 /* Generic instances can have zero method overrides without causing any harm.
3808 * This is true since we don't do layout all over again for them, we simply inflate
3809 * the layout of the parent.
3811 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3813 /* The following call fails if there are missing methods in the type */
3814 /* FIXME it's probably a good idea to avoid this for generic instances. */
3815 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3819 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3821 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3825 mono_loader_unlock ();
3826 g_list_remove (in_setup, class);
3831 #define DEBUG_INTERFACE_VTABLE_CODE 0
3832 #define TRACE_INTERFACE_VTABLE_CODE 0
3833 #define VERIFY_INTERFACE_VTABLE_CODE 0
3834 #define VTABLE_SELECTOR (1)
3836 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3837 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3838 if (!(VTABLE_SELECTOR)) break; \
3842 #define DEBUG_INTERFACE_VTABLE(stmt)
3845 #if TRACE_INTERFACE_VTABLE_CODE
3846 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3847 if (!(VTABLE_SELECTOR)) break; \
3851 #define TRACE_INTERFACE_VTABLE(stmt)
3854 #if VERIFY_INTERFACE_VTABLE_CODE
3855 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3856 if (!(VTABLE_SELECTOR)) break; \
3860 #define VERIFY_INTERFACE_VTABLE(stmt)
3864 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3866 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3870 GString *res = g_string_new ("");
3872 g_string_append_c (res, '(');
3873 for (i = 0; i < sig->param_count; ++i) {
3875 g_string_append_c (res, ',');
3876 mono_type_get_desc (res, sig->params [i], include_namespace);
3878 g_string_append (res, ")=>");
3879 if (sig->ret != NULL) {
3880 mono_type_get_desc (res, sig->ret, include_namespace);
3882 g_string_append (res, "NULL");
3885 g_string_free (res, FALSE);
3889 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3890 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3891 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3892 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3900 is_wcf_hack_disabled (void)
3902 static gboolean disabled;
3903 static gboolean inited = FALSE;
3905 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3912 check_interface_method_override (MonoClass *class, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty, gboolean security_enabled) {
3913 MonoMethodSignature *cmsig, *imsig;
3914 if (strcmp (im->name, cm->name) == 0) {
3915 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3916 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3919 if (! slot_is_empty) {
3920 if (require_newslot) {
3921 if (! interface_is_explicitly_implemented_by_class) {
3922 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3925 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3926 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3930 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3933 cmsig = mono_method_signature (cm);
3934 imsig = mono_method_signature (im);
3935 if (!cmsig || !imsig) {
3936 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3940 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3941 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3942 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3943 TRACE_INTERFACE_VTABLE (printf ("]"));
3946 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3947 /* CAS - SecurityAction.InheritanceDemand on interface */
3948 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3949 mono_secman_inheritancedemand_method (cm, im);
3952 if (mono_security_core_clr_enabled ())
3953 mono_security_core_clr_check_override (class, cm, im);
3955 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3956 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3957 char *body_name = mono_method_full_name (cm, TRUE);
3958 char *decl_name = mono_method_full_name (im, TRUE);
3959 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));
3967 MonoClass *ic = im->klass;
3968 const char *ic_name_space = ic->name_space;
3969 const char *ic_name = ic->name;
3972 if (! require_newslot) {
3973 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3976 if (cm->klass->rank == 0) {
3977 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3980 cmsig = mono_method_signature (cm);
3981 imsig = mono_method_signature (im);
3982 if (!cmsig || !imsig) {
3983 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3987 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3988 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3989 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3990 TRACE_INTERFACE_VTABLE (printf ("]"));
3993 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3994 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3997 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3998 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4001 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))) {
4002 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4006 subname = strstr (cm->name, ic_name_space);
4007 if (subname != cm->name) {
4008 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4011 subname += strlen (ic_name_space);
4012 if (subname [0] != '.') {
4013 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4017 if (strstr (subname, ic_name) != subname) {
4018 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4021 subname += strlen (ic_name);
4022 if (subname [0] != '.') {
4023 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4027 if (strcmp (subname, im->name) != 0) {
4028 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4032 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4033 /* CAS - SecurityAction.InheritanceDemand on interface */
4034 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4035 mono_secman_inheritancedemand_method (cm, im);
4038 if (mono_security_core_clr_enabled ())
4039 mono_security_core_clr_check_override (class, cm, im);
4041 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4042 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4043 char *body_name = mono_method_full_name (cm, TRUE);
4044 char *decl_name = mono_method_full_name (im, TRUE);
4045 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));
4055 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4057 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4058 MonoMethod *method = key;
4059 MonoMethod *override = value;
4060 MonoClass *method_class = mono_method_get_class (method);
4061 MonoClass *override_class = mono_method_get_class (override);
4063 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4064 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4065 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4068 print_overrides (GHashTable *override_map, const char *message) {
4070 printf ("Override map \"%s\" START:\n", message);
4071 g_hash_table_foreach (override_map, foreach_override, NULL);
4072 printf ("Override map \"%s\" END.\n", message);
4074 printf ("Override map \"%s\" EMPTY.\n", message);
4078 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4079 char *full_name = mono_type_full_name (&class->byval_arg);
4083 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4085 if (print_interfaces) {
4086 print_implemented_interfaces (class);
4087 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4090 if (class->parent) {
4091 parent_size = class->parent->vtable_size;
4095 for (i = 0; i < size; ++i) {
4096 MonoMethod *cm = vtable [i];
4097 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4098 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4100 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4108 #if VERIFY_INTERFACE_VTABLE_CODE
4110 mono_method_try_get_vtable_index (MonoMethod *method)
4112 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4113 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4114 if (imethod->declaring->is_generic)
4115 return imethod->declaring->slot;
4117 return method->slot;
4121 mono_class_verify_vtable (MonoClass *class)
4124 char *full_name = mono_type_full_name (&class->byval_arg);
4126 printf ("*** Verifying VTable of class '%s' \n", full_name);
4130 if (!class->methods)
4133 for (i = 0; i < class->method.count; ++i) {
4134 MonoMethod *cm = class->methods [i];
4137 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4141 full_name = mono_method_full_name (cm, TRUE);
4143 slot = mono_method_try_get_vtable_index (cm);
4145 if (slot >= class->vtable_size) {
4146 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4150 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4151 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4152 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4153 g_free (other_name);
4156 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4163 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4165 char *method_signature;
4168 for (index = 0; index < onum; ++index) {
4169 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4170 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4172 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4173 type_name = mono_type_full_name (&class->byval_arg);
4174 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4175 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4176 g_free (method_signature);
4178 mono_class_setup_methods (class);
4179 if (class->exception_type) {
4180 char *name = mono_type_get_full_name (class);
4181 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4185 for (index = 0; index < class->method.count; ++index) {
4186 MonoMethod *cm = class->methods [index];
4187 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4189 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4190 g_free (method_signature);
4195 mono_method_get_method_definition (MonoMethod *method)
4197 while (method->is_inflated)
4198 method = ((MonoMethodInflated*)method)->declaring;
4203 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4207 for (i = 0; i < onum; ++i) {
4208 MonoMethod *decl = overrides [i * 2];
4209 MonoMethod *body = overrides [i * 2 + 1];
4211 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4212 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4216 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4217 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4218 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4220 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4224 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4225 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4226 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4228 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4232 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4233 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4237 body = mono_method_get_method_definition (body);
4238 decl = mono_method_get_method_definition (decl);
4240 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4241 char *body_name = mono_method_full_name (body, TRUE);
4242 char *decl_name = mono_method_full_name (decl, TRUE);
4243 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));
4253 mono_class_need_stelemref_method (MonoClass *class)
4255 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4259 * LOCKING: this is supposed to be called with the loader lock held.
4262 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4266 MonoMethod **vtable;
4267 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4268 GPtrArray *ifaces = NULL;
4269 GHashTable *override_map = NULL;
4270 gboolean security_enabled = mono_security_enabled ();
4272 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4273 int first_non_interface_slot;
4275 GSList *virt_methods = NULL, *l;
4276 int stelemref_slot = 0;
4281 if (overrides && !verify_class_overrides (class, overrides, onum))
4284 ifaces = mono_class_get_implemented_interfaces (class, &error);
4285 if (!mono_error_ok (&error)) {
4286 char *name = mono_type_get_full_name (class);
4287 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)));
4289 mono_error_cleanup (&error);
4291 } else if (ifaces) {
4292 for (i = 0; i < ifaces->len; i++) {
4293 MonoClass *ic = g_ptr_array_index (ifaces, i);
4294 max_vtsize += ic->method.count;
4296 g_ptr_array_free (ifaces, TRUE);
4300 if (class->parent) {
4301 mono_class_init (class->parent);
4302 mono_class_setup_vtable_full (class->parent, in_setup);
4304 if (class->parent->exception_type) {
4305 char *name = mono_type_get_full_name (class->parent);
4306 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4311 max_vtsize += class->parent->vtable_size;
4312 cur_slot = class->parent->vtable_size;
4315 max_vtsize += class->method.count;
4317 /*Array have a slot for stelemref*/
4318 if (mono_class_need_stelemref_method (class)) {
4319 stelemref_slot = cur_slot;
4324 vtable = alloca (sizeof (gpointer) * max_vtsize);
4325 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4327 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4329 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4330 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4333 max_iid = class->max_interface_id;
4334 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4336 /* Optimized version for generic instances */
4337 if (class->generic_class) {
4339 MonoClass *gklass = class->generic_class->container_class;
4342 mono_class_setup_vtable_full (gklass, in_setup);
4343 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4344 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4348 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4349 class->vtable_size = gklass->vtable_size;
4350 for (i = 0; i < gklass->vtable_size; ++i)
4351 if (gklass->vtable [i]) {
4352 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4353 if (!mono_error_ok (&error)) {
4354 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4355 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4357 mono_error_cleanup (&error);
4361 tmp [i]->slot = gklass->vtable [i]->slot;
4363 mono_memory_barrier ();
4364 class->vtable = tmp;
4366 /* Have to set method->slot for abstract virtual methods */
4367 if (class->methods && gklass->methods) {
4368 for (i = 0; i < class->method.count; ++i)
4369 if (class->methods [i]->slot == -1)
4370 class->methods [i]->slot = gklass->methods [i]->slot;
4376 if (class->parent && class->parent->vtable_size) {
4377 MonoClass *parent = class->parent;
4380 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4382 // Also inherit parent interface vtables, just as a starting point.
4383 // This is needed otherwise bug-77127.exe fails when the property methods
4384 // have different names in the iterface and the class, because for child
4385 // classes the ".override" information is not used anymore.
4386 for (i = 0; i < parent->interface_offsets_count; i++) {
4387 MonoClass *parent_interface = parent->interfaces_packed [i];
4388 int interface_offset = mono_class_interface_offset (class, parent_interface);
4389 /*FIXME this is now dead code as this condition will never hold true.
4390 Since interface offsets are inherited then the offset of an interface implemented
4391 by a parent will never be the out of it's vtable boundary.
4393 if (interface_offset >= parent->vtable_size) {
4394 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4397 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4398 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4399 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4400 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4401 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4402 parent_interface_offset + j, parent_interface_offset, j,
4403 interface_offset + j, interface_offset, j));
4410 /*Array have a slot for stelemref*/
4411 if (mono_class_need_stelemref_method (class)) {
4412 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4414 method->slot = stelemref_slot;
4416 g_assert (method->slot == stelemref_slot);
4418 vtable [stelemref_slot] = method;
4421 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4422 /* override interface methods */
4423 for (i = 0; i < onum; i++) {
4424 MonoMethod *decl = overrides [i*2];
4425 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4427 dslot = mono_method_get_vtable_slot (decl);
4429 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4433 dslot += mono_class_interface_offset (class, decl->klass);
4434 vtable [dslot] = overrides [i*2 + 1];
4435 vtable [dslot]->slot = dslot;
4437 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4439 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4441 if (mono_security_core_clr_enabled ())
4442 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4445 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4446 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4449 * Create a list of virtual methods to avoid calling
4450 * mono_class_get_virtual_methods () which is slow because of the metadata
4454 gpointer iter = NULL;
4457 virt_methods = NULL;
4458 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4459 virt_methods = g_slist_prepend (virt_methods, cm);
4461 if (class->exception_type)
4465 // Loop on all implemented interfaces...
4466 for (i = 0; i < class->interface_offsets_count; i++) {
4467 MonoClass *parent = class->parent;
4469 gboolean interface_is_explicitly_implemented_by_class;
4472 ic = class->interfaces_packed [i];
4473 ic_offset = mono_class_interface_offset (class, ic);
4475 mono_class_setup_methods (ic);
4476 if (ic->exception_type)
4479 // Check if this interface is explicitly implemented (instead of just inherited)
4480 if (parent != NULL) {
4481 int implemented_interfaces_index;
4482 interface_is_explicitly_implemented_by_class = FALSE;
4483 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4484 if (ic == class->interfaces [implemented_interfaces_index]) {
4485 interface_is_explicitly_implemented_by_class = TRUE;
4490 interface_is_explicitly_implemented_by_class = TRUE;
4493 // Loop on all interface methods...
4494 for (im_index = 0; im_index < ic->method.count; im_index++) {
4495 MonoMethod *im = ic->methods [im_index];
4496 int im_slot = ic_offset + im->slot;
4497 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4499 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4502 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4504 // If there is an explicit implementation, just use it right away,
4505 // otherwise look for a matching method
4506 if (override_im == NULL) {
4510 // First look for a suitable method among the class methods
4511 for (l = virt_methods; l; l = l->next) {
4513 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)));
4514 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4515 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4516 vtable [im_slot] = cm;
4517 /* Why do we need this? */
4522 TRACE_INTERFACE_VTABLE (printf ("\n"));
4523 if (class->exception_type) /*Might be set by check_interface_method_override*/
4527 // If the slot is still empty, look in all the inherited virtual methods...
4528 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4529 MonoClass *parent = class->parent;
4530 // Reverse order, so that last added methods are preferred
4531 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4532 MonoMethod *cm = parent->vtable [cm_index];
4534 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));
4535 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4536 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4537 vtable [im_slot] = cm;
4538 /* Why do we need this? */
4544 if (class->exception_type) /*Might be set by check_interface_method_override*/
4546 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4550 g_assert (vtable [im_slot] == override_im);
4555 // If the class is not abstract, check that all its interface slots are full.
4556 // The check is done here and not directly at the end of the loop above because
4557 // it can happen (for injected generic array interfaces) that the same slot is
4558 // processed multiple times (those interfaces have overlapping slots), and it
4559 // will not always be the first pass the one that fills the slot.
4560 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4561 for (i = 0; i < class->interface_offsets_count; i++) {
4565 ic = class->interfaces_packed [i];
4566 ic_offset = mono_class_interface_offset (class, ic);
4568 for (im_index = 0; im_index < ic->method.count; im_index++) {
4569 MonoMethod *im = ic->methods [im_index];
4570 int im_slot = ic_offset + im->slot;
4572 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4575 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4576 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4577 if (vtable [im_slot] == NULL) {
4578 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4585 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4586 for (l = virt_methods; l; l = l->next) {
4589 * If the method is REUSE_SLOT, we must check in the
4590 * base class for a method to override.
4592 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4594 for (k = class->parent; k ; k = k->parent) {
4599 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4600 MonoMethodSignature *cmsig, *m1sig;
4602 cmsig = mono_method_signature (cm);
4603 m1sig = mono_method_signature (m1);
4605 if (!cmsig || !m1sig) {
4606 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4610 if (!strcmp(cm->name, m1->name) &&
4611 mono_metadata_signature_equal (cmsig, m1sig)) {
4613 /* CAS - SecurityAction.InheritanceDemand */
4614 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4615 mono_secman_inheritancedemand_method (cm, m1);
4618 if (mono_security_core_clr_enabled ())
4619 mono_security_core_clr_check_override (class, cm, m1);
4621 slot = mono_method_get_vtable_slot (m1);
4625 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4626 char *body_name = mono_method_full_name (cm, TRUE);
4627 char *decl_name = mono_method_full_name (m1, TRUE);
4628 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));
4634 g_assert (cm->slot < max_vtsize);
4636 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4637 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4638 mono_method_full_name (m1, 1), m1,
4639 mono_method_full_name (cm, 1), cm));
4640 g_hash_table_insert (override_map, m1, cm);
4644 if (k->exception_type)
4654 /*Non final newslot methods must be given a non-interface vtable slot*/
4655 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4659 cm->slot = cur_slot++;
4661 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4662 vtable [cm->slot] = cm;
4665 /* override non interface methods */
4666 for (i = 0; i < onum; i++) {
4667 MonoMethod *decl = overrides [i*2];
4668 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4669 g_assert (decl->slot != -1);
4670 vtable [decl->slot] = overrides [i*2 + 1];
4671 overrides [i * 2 + 1]->slot = decl->slot;
4673 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4674 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4675 mono_method_full_name (decl, 1), decl,
4676 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4677 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4679 if (mono_security_core_clr_enabled ())
4680 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4685 * If a method occupies more than one place in the vtable, and it is
4686 * overriden, then change the other occurances too.
4691 for (i = 0; i < max_vtsize; ++i)
4693 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4695 cm = g_hash_table_lookup (override_map, vtable [i]);
4700 g_hash_table_destroy (override_map);
4701 override_map = NULL;
4704 g_slist_free (virt_methods);
4705 virt_methods = NULL;
4707 /* Ensure that all vtable slots are filled with concrete instance methods */
4708 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4709 for (i = 0; i < cur_slot; ++i) {
4710 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4711 char *type_name = mono_type_get_full_name (class);
4712 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4713 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));
4715 g_free (method_name);
4721 if (class->generic_class) {
4722 MonoClass *gklass = class->generic_class->container_class;
4724 mono_class_init (gklass);
4726 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4728 /* Check that the vtable_size value computed in mono_class_init () is correct */
4729 if (class->vtable_size)
4730 g_assert (cur_slot == class->vtable_size);
4731 class->vtable_size = cur_slot;
4734 /* Try to share the vtable with our parent. */
4735 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4736 mono_memory_barrier ();
4737 class->vtable = class->parent->vtable;
4739 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4740 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4741 mono_memory_barrier ();
4742 class->vtable = tmp;
4745 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4746 if (mono_print_vtable) {
4749 print_implemented_interfaces (class);
4751 for (i = 0; i <= max_iid; i++)
4752 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4755 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4756 class->vtable_size, icount);
4758 for (i = 0; i < cur_slot; ++i) {
4763 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4764 mono_method_full_name (cm, TRUE));
4770 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4771 class->name, max_iid);
4773 for (i = 0; i < class->interface_count; i++) {
4774 ic = class->interfaces [i];
4775 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4776 mono_class_interface_offset (class, ic),
4777 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4780 for (k = class->parent; k ; k = k->parent) {
4781 for (i = 0; i < k->interface_count; i++) {
4782 ic = k->interfaces [i];
4783 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4784 mono_class_interface_offset (class, ic),
4785 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4791 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4796 char *name = mono_type_get_full_name (class);
4797 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4800 g_hash_table_destroy (override_map);
4802 g_slist_free (virt_methods);
4807 * mono_method_get_vtable_slot:
4809 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4810 * LOCKING: Acquires the loader lock.
4812 * FIXME Use proper MonoError machinery here.
4815 mono_method_get_vtable_slot (MonoMethod *method)
4817 if (method->slot == -1) {
4818 mono_class_setup_vtable (method->klass);
4819 if (method->klass->exception_type)
4821 if (method->slot == -1) {
4825 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4826 g_assert (method->klass->generic_class);
4827 gklass = method->klass->generic_class->container_class;
4828 mono_class_setup_methods (method->klass);
4829 g_assert (method->klass->methods);
4830 for (i = 0; i < method->klass->method.count; ++i) {
4831 if (method->klass->methods [i] == method)
4834 g_assert (i < method->klass->method.count);
4835 g_assert (gklass->methods);
4836 method->slot = gklass->methods [i]->slot;
4838 g_assert (method->slot != -1);
4840 return method->slot;
4844 * mono_method_get_vtable_index:
4847 * Returns the index into the runtime vtable to access the method or,
4848 * in the case of a virtual generic method, the virtual generic method
4849 * thunk. Returns -1 on failure.
4851 * FIXME Use proper MonoError machinery here.
4854 mono_method_get_vtable_index (MonoMethod *method)
4856 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4857 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4858 if (imethod->declaring->is_generic)
4859 return mono_method_get_vtable_slot (imethod->declaring);
4861 return mono_method_get_vtable_slot (method);
4864 static MonoMethod *default_ghc = NULL;
4865 static MonoMethod *default_finalize = NULL;
4866 static int finalize_slot = -1;
4867 static int ghc_slot = -1;
4870 initialize_object_slots (MonoClass *class)
4875 if (class == mono_defaults.object_class) {
4876 mono_class_setup_vtable (class);
4877 for (i = 0; i < class->vtable_size; ++i) {
4878 MonoMethod *cm = class->vtable [i];
4880 if (!strcmp (cm->name, "GetHashCode"))
4882 else if (!strcmp (cm->name, "Finalize"))
4886 g_assert (ghc_slot > 0);
4887 default_ghc = class->vtable [ghc_slot];
4889 g_assert (finalize_slot > 0);
4890 default_finalize = class->vtable [finalize_slot];
4895 MonoMethod *array_method;
4897 } GenericArrayMethodInfo;
4899 static int generic_array_method_num = 0;
4900 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4903 generic_array_methods (MonoClass *class)
4905 int i, count_generic = 0;
4906 GList *list = NULL, *tmp;
4907 if (generic_array_method_num)
4908 return generic_array_method_num;
4909 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4910 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4911 for (i = 0; i < class->parent->method.count; i++) {
4912 MonoMethod *m = class->parent->methods [i];
4913 if (!strncmp (m->name, "InternalArray__", 15)) {
4915 list = g_list_prepend (list, m);
4918 list = g_list_reverse (list);
4919 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4921 for (tmp = list; tmp; tmp = tmp->next) {
4922 const char *mname, *iname;
4924 MonoMethod *m = tmp->data;
4925 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4926 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4928 generic_array_method_info [i].array_method = m;
4929 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4930 iname = "System.Collections.Generic.ICollection`1.";
4931 mname = m->name + 27;
4932 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4933 iname = "System.Collections.Generic.IEnumerable`1.";
4934 mname = m->name + 27;
4935 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4936 iname = "System.Collections.Generic.IReadOnlyList`1.";
4937 mname = m->name + strlen (ireadonlylist_prefix);
4938 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4939 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4940 mname = m->name + strlen (ireadonlycollection_prefix);
4941 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4942 iname = "System.Collections.Generic.IList`1.";
4943 mname = m->name + 15;
4945 g_assert_not_reached ();
4948 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4949 strcpy (name, iname);
4950 strcpy (name + strlen (iname), mname);
4951 generic_array_method_info [i].name = name;
4954 /*g_print ("array generic methods: %d\n", count_generic);*/
4956 generic_array_method_num = count_generic;
4958 return generic_array_method_num;
4962 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4964 MonoGenericContext tmp_context;
4967 tmp_context.class_inst = NULL;
4968 tmp_context.method_inst = iface->generic_class->context.class_inst;
4969 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4971 for (i = 0; i < generic_array_method_num; i++) {
4973 MonoMethod *m = generic_array_method_info [i].array_method;
4974 MonoMethod *inflated;
4976 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4977 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4978 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4983 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4985 int null_length = strlen ("(null)");
4986 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4987 char *s = mono_image_alloc (image, len);
4990 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4991 g_assert (result == len - 1);
4997 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4999 gpointer exception_data = NULL;
5001 switch (error->exception_type) {
5002 case MONO_EXCEPTION_TYPE_LOAD:
5003 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
5006 case MONO_EXCEPTION_MISSING_METHOD:
5007 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
5010 case MONO_EXCEPTION_MISSING_FIELD: {
5011 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5012 const char *class_name;
5015 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5017 class_name = error->klass->name;
5019 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5022 g_free ((void*)class_name);
5026 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5029 if (error->ref_only)
5030 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.";
5032 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5034 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5038 case MONO_EXCEPTION_BAD_IMAGE:
5039 exception_data = error->msg;
5043 g_assert_not_reached ();
5046 mono_class_set_failure (class, error->exception_type, exception_data);
5051 * @class: the class to initialize
5053 * Compute the instance_size, class_size and other infos that cannot be
5054 * computed at mono_class_get() time. Also compute vtable_size if possible.
5055 * Returns TRUE on success or FALSE if there was a problem in loading
5056 * the type (incorrect assemblies, missing assemblies, methods, etc).
5058 * LOCKING: Acquires the loader lock.
5061 mono_class_init (MonoClass *class)
5064 MonoCachedClassInfo cached_info;
5065 gboolean has_cached_info;
5069 /* Double-checking locking pattern */
5070 if (class->inited || class->exception_type)
5071 return class->exception_type == MONO_EXCEPTION_NONE;
5073 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5075 /* We do everything inside the lock to prevent races */
5076 mono_loader_lock ();
5078 if (class->inited || class->exception_type) {
5079 mono_loader_unlock ();
5080 /* Somebody might have gotten in before us */
5081 return class->exception_type == MONO_EXCEPTION_NONE;
5084 if (class->init_pending) {
5085 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5089 class->init_pending = 1;
5091 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5092 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5097 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5098 MonoClass *element_class = class->element_class;
5099 if (!element_class->inited)
5100 mono_class_init (element_class);
5101 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5102 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5107 /* CAS - SecurityAction.InheritanceDemand */
5108 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5109 mono_secman_inheritancedemand_class (class, class->parent);
5112 mono_stats.initialized_class_count++;
5114 if (class->generic_class && !class->generic_class->is_dynamic) {
5115 MonoClass *gklass = class->generic_class->container_class;
5117 mono_stats.generic_class_count++;
5119 class->method = gklass->method;
5120 class->field = gklass->field;
5122 mono_class_init (gklass);
5123 // FIXME: Why is this needed ?
5124 if (!gklass->exception_type)
5125 mono_class_setup_methods (gklass);
5126 if (gklass->exception_type) {
5127 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5131 if (MONO_CLASS_IS_INTERFACE (class))
5132 class->interface_id = mono_get_unique_iid (class);
5135 if (class->parent && !class->parent->inited)
5136 mono_class_init (class->parent);
5138 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5140 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5141 class->nested_classes_inited = TRUE;
5144 * Computes the size used by the fields, and their locations
5146 if (has_cached_info) {
5147 class->instance_size = cached_info.instance_size;
5148 class->sizes.class_size = cached_info.class_size;
5149 class->packing_size = cached_info.packing_size;
5150 class->min_align = cached_info.min_align;
5151 class->blittable = cached_info.blittable;
5152 class->has_references = cached_info.has_references;
5153 class->has_static_refs = cached_info.has_static_refs;
5154 class->no_special_static_fields = cached_info.no_special_static_fields;
5157 if (!class->size_inited){
5158 mono_class_setup_fields (class);
5159 if (class->exception_type || mono_loader_get_last_error ())
5163 /* Initialize arrays */
5165 class->method.count = 3 + (class->rank > 1? 2: 1);
5167 if (class->interface_count) {
5168 int count_generic = generic_array_methods (class);
5169 class->method.count += class->interface_count * count_generic;
5173 mono_class_setup_supertypes (class);
5176 initialize_object_slots (class);
5179 * Initialize the rest of the data without creating a generic vtable if possible.
5180 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5181 * also avoid computing a generic vtable.
5183 if (has_cached_info) {
5185 class->vtable_size = cached_info.vtable_size;
5186 class->has_finalize = cached_info.has_finalize;
5187 class->has_finalize_inited = TRUE;
5188 class->ghcimpl = cached_info.ghcimpl;
5189 class->has_cctor = cached_info.has_cctor;
5190 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5191 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5192 * The first slot if for array with.
5194 static int szarray_vtable_size[2] = { 0 };
5196 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5199 if (!szarray_vtable_size [slot]) {
5200 mono_class_setup_vtable (class);
5201 szarray_vtable_size [slot] = class->vtable_size;
5203 class->vtable_size = szarray_vtable_size[slot];
5205 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5206 MonoClass *gklass = class->generic_class->container_class;
5208 /* Generic instance case */
5209 class->ghcimpl = gklass->ghcimpl;
5210 class->has_cctor = gklass->has_cctor;
5212 mono_class_setup_vtable (gklass);
5213 if (gklass->exception_type) {
5214 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5218 class->vtable_size = gklass->vtable_size;
5222 /* ghcimpl is not currently used
5224 if (class->parent) {
5225 MonoMethod *cmethod = class->vtable [ghc_slot];
5226 if (cmethod->is_inflated)
5227 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5228 if (cmethod == default_ghc) {
5234 /* C# doesn't allow interfaces to have cctors */
5235 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5236 MonoMethod *cmethod = NULL;
5238 if (class->type_token) {
5239 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5240 /* The find_method function ignores the 'flags' argument */
5241 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5242 class->has_cctor = 1;
5244 mono_class_setup_methods (class);
5245 if (class->exception_type)
5248 for (i = 0; i < class->method.count; ++i) {
5249 MonoMethod *method = class->methods [i];
5250 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5251 (strcmp (".cctor", method->name) == 0)) {
5252 class->has_cctor = 1;
5260 if (class->parent) {
5261 int first_iface_slot;
5262 /* This will compute class->parent->vtable_size for some classes */
5263 mono_class_init (class->parent);
5264 if (class->parent->exception_type) {
5265 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5268 if (mono_loader_get_last_error ())
5270 if (!class->parent->vtable_size) {
5271 /* FIXME: Get rid of this somehow */
5272 mono_class_setup_vtable (class->parent);
5273 if (class->parent->exception_type) {
5274 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5277 if (mono_loader_get_last_error ())
5280 first_iface_slot = class->parent->vtable_size;
5281 if (mono_class_need_stelemref_method (class))
5283 setup_interface_offsets (class, first_iface_slot, TRUE);
5285 setup_interface_offsets (class, 0, TRUE);
5288 if (mono_security_core_clr_enabled ())
5289 mono_security_core_clr_check_inheritance (class);
5291 if (mono_loader_get_last_error ()) {
5292 if (class->exception_type == MONO_EXCEPTION_NONE) {
5293 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5295 mono_loader_clear_error ();
5298 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5299 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5304 /* Because of the double-checking locking pattern */
5305 mono_memory_barrier ();
5307 class->init_pending = 0;
5309 mono_loader_unlock ();
5311 return class->exception_type == MONO_EXCEPTION_NONE;
5315 * mono_class_has_finalizer:
5317 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5321 mono_class_has_finalizer (MonoClass *klass)
5323 MonoClass *class = klass;
5324 gboolean has_finalize = FALSE;
5326 if (klass->has_finalize_inited)
5327 return klass->has_finalize;
5329 /* Interfaces and valuetypes are not supposed to have finalizers */
5330 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5331 MonoMethod *cmethod = NULL;
5333 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5334 } else if (class->generic_class) {
5335 MonoClass *gklass = class->generic_class->container_class;
5337 has_finalize = mono_class_has_finalizer (gklass);
5338 } else if (class->parent && class->parent->has_finalize) {
5339 has_finalize = TRUE;
5341 if (class->parent) {
5343 * Can't search in metadata for a method named Finalize, because that
5344 * ignores overrides.
5346 mono_class_setup_vtable (class);
5347 if (class->exception_type || mono_loader_get_last_error ())
5350 cmethod = class->vtable [finalize_slot];
5354 g_assert (class->vtable_size > finalize_slot);
5356 if (class->parent) {
5357 if (cmethod->is_inflated)
5358 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5359 if (cmethod != default_finalize)
5360 has_finalize = TRUE;
5366 mono_image_lock (klass->image);
5368 if (!klass->has_finalize_inited) {
5369 klass->has_finalize = has_finalize ? 1 : 0;
5371 mono_memory_barrier ();
5372 klass->has_finalize_inited = TRUE;
5375 mono_image_unlock (klass->image);
5377 return klass->has_finalize;
5381 mono_is_corlib_image (MonoImage *image)
5383 /* FIXME: allow the dynamic case for our compilers and with full trust */
5384 if (image_is_dynamic (image))
5385 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5387 return image == mono_defaults.corlib;
5391 * LOCKING: this assumes the loader lock is held
5394 mono_class_setup_mono_type (MonoClass *class)
5396 const char *name = class->name;
5397 const char *nspace = class->name_space;
5398 gboolean is_corlib = mono_is_corlib_image (class->image);
5400 class->this_arg.byref = 1;
5401 class->this_arg.data.klass = class;
5402 class->this_arg.type = MONO_TYPE_CLASS;
5403 class->byval_arg.data.klass = class;
5404 class->byval_arg.type = MONO_TYPE_CLASS;
5406 if (is_corlib && !strcmp (nspace, "System")) {
5407 if (!strcmp (name, "ValueType")) {
5409 * do not set the valuetype bit for System.ValueType.
5410 * class->valuetype = 1;
5412 class->blittable = TRUE;
5413 } else if (!strcmp (name, "Enum")) {
5415 * do not set the valuetype bit for System.Enum.
5416 * class->valuetype = 1;
5418 class->valuetype = 0;
5419 class->enumtype = 0;
5420 } else if (!strcmp (name, "Object")) {
5421 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5422 } else if (!strcmp (name, "String")) {
5423 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5424 } else if (!strcmp (name, "TypedReference")) {
5425 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5429 if (class->valuetype) {
5430 int t = MONO_TYPE_VALUETYPE;
5432 if (is_corlib && !strcmp (nspace, "System")) {
5435 if (!strcmp (name, "Boolean")) {
5436 t = MONO_TYPE_BOOLEAN;
5437 } else if (!strcmp(name, "Byte")) {
5439 class->blittable = TRUE;
5443 if (!strcmp (name, "Char")) {
5448 if (!strcmp (name, "Double")) {
5450 class->blittable = TRUE;
5454 if (!strcmp (name, "Int32")) {
5456 class->blittable = TRUE;
5457 } else if (!strcmp(name, "Int16")) {
5459 class->blittable = TRUE;
5460 } else if (!strcmp(name, "Int64")) {
5462 class->blittable = TRUE;
5463 } else if (!strcmp(name, "IntPtr")) {
5465 class->blittable = TRUE;
5469 if (!strcmp (name, "Single")) {
5471 class->blittable = TRUE;
5472 } else if (!strcmp(name, "SByte")) {
5474 class->blittable = TRUE;
5478 if (!strcmp (name, "UInt32")) {
5480 class->blittable = TRUE;
5481 } else if (!strcmp(name, "UInt16")) {
5483 class->blittable = TRUE;
5484 } else if (!strcmp(name, "UInt64")) {
5486 class->blittable = TRUE;
5487 } else if (!strcmp(name, "UIntPtr")) {
5489 class->blittable = TRUE;
5493 if (!strcmp (name, "TypedReference")) {
5494 t = MONO_TYPE_TYPEDBYREF;
5495 class->blittable = TRUE;
5499 if (!strcmp (name, "Void")) {
5507 class->this_arg.type = class->byval_arg.type = t;
5510 if (MONO_CLASS_IS_INTERFACE (class))
5511 class->interface_id = mono_get_unique_iid (class);
5517 * COM initialization is delayed until needed.
5518 * However when a [ComImport] attribute is present on a type it will trigger
5519 * the initialization. This is not a problem unless the BCL being executed
5520 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5523 init_com_from_comimport (MonoClass *class)
5525 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5526 if (mono_security_core_clr_enabled ()) {
5527 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5528 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5529 /* but it can not be made available for application (i.e. user code) since all COM calls
5530 * are considered native calls. In this case we fail with a TypeLoadException (just like
5531 * Silverlight 2 does */
5532 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5537 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5539 #endif /*DISABLE_COM*/
5542 * LOCKING: this assumes the loader lock is held
5545 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5547 gboolean system_namespace;
5548 gboolean is_corlib = mono_is_corlib_image (class->image);
5550 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5552 /* if root of the hierarchy */
5553 if (system_namespace && !strcmp (class->name, "Object")) {
5554 class->parent = NULL;
5555 class->instance_size = sizeof (MonoObject);
5558 if (!strcmp (class->name, "<Module>")) {
5559 class->parent = NULL;
5560 class->instance_size = 0;
5564 if (!MONO_CLASS_IS_INTERFACE (class)) {
5565 /* Imported COM Objects always derive from __ComObject. */
5567 if (MONO_CLASS_IS_IMPORT (class)) {
5568 init_com_from_comimport (class);
5569 if (parent == mono_defaults.object_class)
5570 parent = mono_class_get_com_object_class ();
5574 /* set the parent to something useful and safe, but mark the type as broken */
5575 parent = mono_defaults.object_class;
5576 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5579 class->parent = parent;
5581 if (parent->generic_class && !parent->name) {
5583 * If the parent is a generic instance, we may get
5584 * called before it is fully initialized, especially
5585 * before it has its name.
5590 #ifndef DISABLE_REMOTING
5591 class->marshalbyref = parent->marshalbyref;
5592 class->contextbound = parent->contextbound;
5595 class->delegate = parent->delegate;
5597 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5598 mono_class_set_is_com_object (class);
5600 if (system_namespace) {
5601 #ifndef DISABLE_REMOTING
5602 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5603 class->marshalbyref = 1;
5605 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5606 class->contextbound = 1;
5608 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5609 class->delegate = 1;
5612 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5613 (strcmp (class->parent->name_space, "System") == 0)))
5614 class->valuetype = 1;
5615 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5616 class->valuetype = class->enumtype = 1;
5618 /*class->enumtype = class->parent->enumtype; */
5620 /* initialize com types if COM interfaces are present */
5622 if (MONO_CLASS_IS_IMPORT (class))
5623 init_com_from_comimport (class);
5625 class->parent = NULL;
5631 * mono_class_setup_supertypes:
5634 * Build the data structure needed to make fast type checks work.
5635 * This currently sets two fields in @class:
5636 * - idepth: distance between @class and System.Object in the type
5638 * - supertypes: array of classes: each element has a class in the hierarchy
5639 * starting from @class up to System.Object
5641 * LOCKING: This function is atomic, in case of contention we waste memory.
5644 mono_class_setup_supertypes (MonoClass *class)
5647 MonoClass **supertypes;
5649 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5653 if (class->parent && !class->parent->supertypes)
5654 mono_class_setup_supertypes (class->parent);
5656 class->idepth = class->parent->idepth + 1;
5660 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5661 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5663 if (class->parent) {
5664 supertypes [class->idepth - 1] = class;
5665 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5667 supertypes [0] = class;
5670 mono_atomic_store_release (&class->supertypes, supertypes);
5674 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5676 MonoClass *gtd = (MonoClass*)user_data;
5677 /* Only try to fix generic instances of @gtd */
5678 if (gclass->generic_class->container_class != gtd)
5681 /* Check if the generic instance has no parent. */
5682 if (gtd->parent && !gclass->parent)
5683 mono_generic_class_setup_parent (gclass, gtd);
5689 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5691 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5692 mono_error_set_type_load_class (error, class, msg);
5696 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5698 MonoLoaderError *lerror = mono_loader_get_last_error ();
5701 set_failure_from_loader_error (class, lerror);
5702 mono_error_set_from_loader_error (error);
5706 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5707 mono_error_set_type_load_class (error, class, msg);
5712 * mono_class_create_from_typedef:
5713 * @image: image where the token is valid
5714 * @type_token: typedef token
5715 * @error: used to return any error found while creating the type
5717 * Create the MonoClass* representing the specified type token.
5718 * @type_token must be a TypeDef token.
5720 * FIXME: don't return NULL on failure, just the the caller figure it out.
5723 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5725 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5726 MonoClass *class, *parent = NULL;
5727 guint32 cols [MONO_TYPEDEF_SIZE];
5728 guint32 cols_next [MONO_TYPEDEF_SIZE];
5729 guint tidx = mono_metadata_token_index (type_token);
5730 MonoGenericContext *context = NULL;
5731 const char *name, *nspace;
5733 MonoClass **interfaces;
5734 guint32 field_last, method_last;
5735 guint32 nesting_tokeen;
5737 mono_error_init (error);
5739 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5740 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5741 g_assert (!mono_loader_get_last_error ());
5745 mono_loader_lock ();
5747 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5748 mono_loader_unlock ();
5749 g_assert (!mono_loader_get_last_error ());
5753 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5755 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5756 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5758 class = mono_image_alloc0 (image, sizeof (MonoClass));
5761 class->name_space = nspace;
5763 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5765 class->image = image;
5766 class->type_token = type_token;
5767 class->flags = cols [MONO_TYPEDEF_FLAGS];
5769 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5771 classes_size += sizeof (MonoClass);
5774 * Check whether we're a generic type definition.
5776 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5777 if (class->generic_container) {
5778 class->is_generic = 1;
5779 class->generic_container->owner.klass = class;
5780 context = &class->generic_container->context;
5783 if (class->generic_container)
5784 enable_gclass_recording ();
5786 if (cols [MONO_TYPEDEF_EXTENDS]) {
5788 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5790 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5791 /*WARNING: this must satisfy mono_metadata_type_hash*/
5792 class->this_arg.byref = 1;
5793 class->this_arg.data.klass = class;
5794 class->this_arg.type = MONO_TYPE_CLASS;
5795 class->byval_arg.data.klass = class;
5796 class->byval_arg.type = MONO_TYPE_CLASS;
5798 parent = mono_class_get_checked (image, parent_token, error);
5799 if (parent && context) /* Always inflate */
5800 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5802 if (parent == NULL) {
5803 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5804 goto parent_failure;
5807 for (tmp = parent; tmp; tmp = tmp->parent) {
5809 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5810 goto parent_failure;
5812 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5813 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5814 goto parent_failure;
5819 mono_class_setup_parent (class, parent);
5821 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5822 mono_class_setup_mono_type (class);
5824 if (class->generic_container)
5825 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5828 * This might access class->byval_arg for recursion generated by generic constraints,
5829 * so it has to come after setup_mono_type ().
5831 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5832 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5833 if (!mono_error_ok (error)) {
5834 /*FIXME implement a mono_class_set_failure_from_mono_error */
5835 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5836 mono_loader_unlock ();
5837 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5838 g_assert (!mono_loader_get_last_error ());
5843 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5847 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5851 class->cast_class = class->element_class = class;
5853 if (!class->enumtype) {
5854 if (!mono_metadata_interfaces_from_typedef_full (
5855 image, type_token, &interfaces, &icount, FALSE, context, error)){
5857 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5858 mono_loader_unlock ();
5859 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5863 class->interfaces = interfaces;
5864 class->interface_count = icount;
5865 class->interfaces_inited = 1;
5868 /*g_print ("Load class %s\n", name);*/
5871 * Compute the field and method lists
5873 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5874 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5876 if (tt->rows > tidx){
5877 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5878 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5879 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5881 field_last = image->tables [MONO_TABLE_FIELD].rows;
5882 method_last = image->tables [MONO_TABLE_METHOD].rows;
5885 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5886 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5887 class->field.count = field_last - class->field.first;
5889 class->field.count = 0;
5891 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5892 class->method.count = method_last - class->method.first;
5894 class->method.count = 0;
5896 /* reserve space to store vector pointer in arrays */
5897 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5898 class->instance_size += 2 * sizeof (gpointer);
5899 g_assert (class->field.count == 0);
5902 if (class->enumtype) {
5903 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5904 if (!enum_basetype) {
5905 /*set it to a default value as the whole runtime can't handle this to be null*/
5906 class->cast_class = class->element_class = mono_defaults.int32_class;
5907 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5908 mono_loader_unlock ();
5909 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5910 g_assert (!mono_loader_get_last_error ());
5913 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5917 * If we're a generic type definition, load the constraints.
5918 * We must do this after the class has been constructed to make certain recursive scenarios
5921 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5922 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)));
5923 mono_loader_unlock ();
5924 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5925 g_assert (!mono_loader_get_last_error ());
5929 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5930 if (!strncmp (name, "Vector", 6))
5931 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");
5934 mono_loader_unlock ();
5936 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5937 g_assert (!mono_loader_get_last_error ());
5942 mono_class_setup_mono_type (class);
5943 mono_loader_unlock ();
5944 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5945 g_assert (!mono_loader_get_last_error ());
5949 /** is klass Nullable<T>? */
5951 mono_class_is_nullable (MonoClass *klass)
5953 return klass->generic_class != NULL &&
5954 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5958 /** if klass is T? return T */
5960 mono_class_get_nullable_param (MonoClass *klass)
5962 g_assert (mono_class_is_nullable (klass));
5963 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5967 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5971 MonoGenericClass *gclass = klass->generic_class;
5973 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5974 if (!mono_error_ok (&error)) {
5975 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5976 klass->parent = mono_defaults.object_class;
5977 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5978 mono_error_cleanup (&error);
5982 mono_class_setup_parent (klass, klass->parent);
5984 if (klass->enumtype) {
5985 klass->cast_class = gtd->cast_class;
5986 klass->element_class = gtd->element_class;
5992 * Create the `MonoClass' for an instantiation of a generic type.
5993 * We only do this if we actually need it.
5996 mono_generic_class_get_class (MonoGenericClass *gclass)
5998 MonoClass *klass, *gklass;
6000 if (gclass->cached_class)
6001 return gclass->cached_class;
6003 mono_loader_lock ();
6004 if (gclass->cached_class) {
6005 mono_loader_unlock ();
6006 return gclass->cached_class;
6009 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6011 gklass = gclass->container_class;
6013 if (record_gclass_instantiation > 0)
6014 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6016 if (gklass->nested_in) {
6017 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6018 klass->nested_in = gklass->nested_in;
6021 klass->name = gklass->name;
6022 klass->name_space = gklass->name_space;
6024 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6026 klass->image = gklass->image;
6027 klass->flags = gklass->flags;
6028 klass->type_token = gklass->type_token;
6029 klass->field.count = gklass->field.count;
6031 klass->is_inflated = 1;
6032 klass->generic_class = gclass;
6034 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6035 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6036 klass->this_arg.byref = TRUE;
6037 klass->enumtype = gklass->enumtype;
6038 klass->valuetype = gklass->valuetype;
6040 klass->cast_class = klass->element_class = klass;
6042 if (mono_class_is_nullable (klass))
6043 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6046 * We're not interested in the nested classes of a generic instance.
6047 * We use the generic type definition to look for nested classes.
6050 mono_generic_class_setup_parent (klass, gklass);
6052 if (gclass->is_dynamic) {
6054 * 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.
6055 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6056 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6058 if (!gklass->wastypebuilder)
6061 mono_class_setup_supertypes (klass);
6063 if (klass->enumtype) {
6065 * For enums, gklass->fields might not been set, but instance_size etc. is
6066 * already set in mono_reflection_create_internal_class (). For non-enums,
6067 * these will be computed normally in mono_class_layout_fields ().
6069 klass->instance_size = gklass->instance_size;
6070 klass->sizes.class_size = gklass->sizes.class_size;
6071 mono_memory_barrier ();
6072 klass->size_inited = 1;
6076 mono_memory_barrier ();
6077 gclass->cached_class = klass;
6079 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6081 inflated_classes ++;
6082 inflated_classes_size += sizeof (MonoClass);
6084 mono_loader_unlock ();
6090 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6092 MonoClass *klass, **ptr;
6094 MonoGenericContainer *container = mono_generic_param_owner (param);
6098 image = mono_defaults.corlib;
6100 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6101 classes_size += sizeof (MonoClass);
6104 klass->name = pinfo->name;
6106 int n = mono_generic_param_num (param);
6107 klass->name = mono_image_alloc0 (image, 16);
6108 sprintf ((char*)klass->name, "%d", n);
6113 MonoMethod *omethod = container->owner.method;
6114 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6116 MonoClass *oklass = container->owner.klass;
6117 klass->name_space = oklass ? oklass->name_space : "";
6120 klass->name_space = "";
6123 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6127 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6131 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6132 klass->parent = pinfo->constraints [0];
6134 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6135 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6137 klass->parent = mono_defaults.object_class;
6140 if (count - pos > 0) {
6141 klass->interface_count = count - pos;
6142 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6143 klass->interfaces_inited = TRUE;
6144 for (i = pos; i < count; i++)
6145 klass->interfaces [i - pos] = pinfo->constraints [i];
6148 klass->image = image;
6150 klass->inited = TRUE;
6151 klass->cast_class = klass->element_class = klass;
6152 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6154 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6155 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6156 klass->this_arg.byref = TRUE;
6158 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6159 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6161 /*Init these fields to sane values*/
6162 klass->min_align = 1;
6164 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6165 * constrained to, the JIT depends on this.
6167 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6168 mono_memory_barrier ();
6169 klass->size_inited = 1;
6170 klass->setup_fields_called = 1;
6172 mono_class_setup_supertypes (klass);
6174 if (count - pos > 0) {
6175 mono_class_setup_vtable (klass->parent);
6176 if (klass->parent->exception_type)
6177 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6179 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6185 #define FAST_CACHE_SIZE 16
6188 * LOCKING: Takes the image lock depending on @take_lock.
6191 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6193 int n = mono_generic_param_num (param);
6194 MonoImage *image = param->image;
6195 MonoClass *klass = NULL;
6200 if (param->gshared_constraint) {
6201 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6204 mono_image_lock (image);
6205 klass = g_hash_table_lookup (ht, param);
6207 mono_image_unlock (image);
6212 if (n < FAST_CACHE_SIZE) {
6214 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6216 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6218 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6221 mono_image_lock (image);
6222 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6224 mono_image_unlock (image);
6231 * LOCKING: Image lock (param->image) must be held
6234 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6236 int n = mono_generic_param_num (param);
6237 MonoImage *image = param->image;
6241 if (param->gshared_constraint) {
6242 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6244 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6245 mono_memory_barrier ();
6247 image->mvar_cache_constrained = ht;
6249 image->var_cache_constrained = ht;
6251 g_hash_table_insert (ht, param, klass);
6252 } else if (n < FAST_CACHE_SIZE) {
6254 /* Requires locking to avoid droping an already published class */
6255 if (!image->mvar_cache_fast)
6256 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6257 image->mvar_cache_fast [n] = klass;
6259 if (!image->var_cache_fast)
6260 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6261 image->var_cache_fast [n] = klass;
6264 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6266 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6268 ht = g_hash_table_new (NULL, NULL);
6269 mono_memory_barrier ();
6271 image->mvar_cache_slow = ht;
6273 image->var_cache_slow = ht;
6276 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6281 * LOCKING: Acquires the image lock (@image).
6284 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6286 MonoGenericContainer *container = mono_generic_param_owner (param);
6287 MonoGenericParamInfo *pinfo = NULL;
6288 MonoClass *klass, *klass2;
6291 pinfo = mono_generic_param_info (param);
6292 klass = pinfo->pklass;
6295 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6300 if (!image && container) {
6302 MonoMethod *method = container->owner.method;
6303 image = (method && method->klass) ? method->klass->image : NULL;
6305 MonoClass *klass = container->owner.klass;
6306 // FIXME: 'klass' should not be null
6307 // But, monodis creates GenericContainers without associating a owner to it
6308 image = klass ? klass->image : NULL;
6312 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6314 mono_memory_barrier ();
6316 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6317 image = mono_defaults.corlib;
6319 mono_image_lock (image);
6321 klass2 = pinfo->pklass;
6323 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6329 pinfo->pklass = klass;
6331 set_anon_gparam_class (param, is_mvar, klass);
6333 mono_image_unlock (image);
6335 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6337 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6339 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6345 mono_ptr_class_get (MonoType *type)
6348 MonoClass *el_class;
6352 el_class = mono_class_from_mono_type (type);
6353 image = el_class->image;
6355 mono_image_lock (image);
6356 if (image->ptr_cache) {
6357 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6358 mono_image_unlock (image);
6362 mono_image_unlock (image);
6364 result = mono_image_alloc0 (image, sizeof (MonoClass));
6366 classes_size += sizeof (MonoClass);
6368 result->parent = NULL; /* no parent for PTR types */
6369 result->name_space = el_class->name_space;
6370 name = g_strdup_printf ("%s*", el_class->name);
6371 result->name = mono_image_strdup (image, name);
6374 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6376 result->image = el_class->image;
6377 result->inited = TRUE;
6378 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6379 /* Can pointers get boxed? */
6380 result->instance_size = sizeof (gpointer);
6381 result->cast_class = result->element_class = el_class;
6382 result->blittable = TRUE;
6384 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6385 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6386 result->this_arg.byref = TRUE;
6388 mono_class_setup_supertypes (result);
6390 mono_image_lock (image);
6391 if (image->ptr_cache) {
6393 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6394 mono_image_unlock (image);
6395 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6399 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6401 g_hash_table_insert (image->ptr_cache, el_class, result);
6402 mono_image_unlock (image);
6404 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6410 mono_fnptr_class_get (MonoMethodSignature *sig)
6413 static GHashTable *ptr_hash = NULL;
6415 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6417 mono_loader_lock ();
6420 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6422 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6423 mono_loader_unlock ();
6426 result = g_new0 (MonoClass, 1);
6428 result->parent = NULL; /* no parent for PTR types */
6429 result->name_space = "System";
6430 result->name = "MonoFNPtrFakeClass";
6432 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6434 result->image = mono_defaults.corlib; /* need to fix... */
6435 result->inited = TRUE;
6436 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6437 /* Can pointers get boxed? */
6438 result->instance_size = sizeof (gpointer);
6439 result->cast_class = result->element_class = result;
6440 result->blittable = TRUE;
6442 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6443 result->this_arg.data.method = result->byval_arg.data.method = sig;
6444 result->this_arg.byref = TRUE;
6445 result->blittable = TRUE;
6447 mono_class_setup_supertypes (result);
6449 g_hash_table_insert (ptr_hash, sig, result);
6451 mono_loader_unlock ();
6453 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6459 mono_class_from_mono_type (MonoType *type)
6461 switch (type->type) {
6462 case MONO_TYPE_OBJECT:
6463 return type->data.klass? type->data.klass: mono_defaults.object_class;
6464 case MONO_TYPE_VOID:
6465 return type->data.klass? type->data.klass: mono_defaults.void_class;
6466 case MONO_TYPE_BOOLEAN:
6467 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6468 case MONO_TYPE_CHAR:
6469 return type->data.klass? type->data.klass: mono_defaults.char_class;
6471 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6473 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6475 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6477 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6479 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6481 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6483 return type->data.klass? type->data.klass: mono_defaults.int_class;
6485 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6487 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6489 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6491 return type->data.klass? type->data.klass: mono_defaults.single_class;
6493 return type->data.klass? type->data.klass: mono_defaults.double_class;
6494 case MONO_TYPE_STRING:
6495 return type->data.klass? type->data.klass: mono_defaults.string_class;
6496 case MONO_TYPE_TYPEDBYREF:
6497 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6498 case MONO_TYPE_ARRAY:
6499 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6501 return mono_ptr_class_get (type->data.type);
6502 case MONO_TYPE_FNPTR:
6503 return mono_fnptr_class_get (type->data.method);
6504 case MONO_TYPE_SZARRAY:
6505 return mono_array_class_get (type->data.klass, 1);
6506 case MONO_TYPE_CLASS:
6507 case MONO_TYPE_VALUETYPE:
6508 return type->data.klass;
6509 case MONO_TYPE_GENERICINST:
6510 return mono_generic_class_get_class (type->data.generic_class);
6512 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6513 case MONO_TYPE_MVAR:
6514 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6516 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6517 g_assert_not_reached ();
6524 * mono_type_retrieve_from_typespec
6525 * @image: context where the image is created
6526 * @type_spec: typespec token
6527 * @context: the generic context used to evaluate generic instantiations in
6530 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6532 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6534 *did_inflate = FALSE;
6539 if (context && (context->class_inst || context->method_inst)) {
6540 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6542 if (!mono_error_ok (error)) {
6543 g_assert (!mono_loader_get_last_error ());
6549 *did_inflate = TRUE;
6556 * mono_class_create_from_typespec
6557 * @image: context where the image is created
6558 * @type_spec: typespec token
6559 * @context: the generic context used to evaluate generic instantiations in
6562 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6565 gboolean inflated = FALSE;
6566 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6567 if (!mono_error_ok (error))
6569 ret = mono_class_from_mono_type (t);
6571 mono_metadata_free_type (t);
6576 * mono_bounded_array_class_get:
6577 * @element_class: element class
6578 * @rank: the dimension of the array class
6579 * @bounded: whenever the array has non-zero bounds
6581 * Returns: a class object describing the array with element type @element_type and
6585 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6589 MonoClass *parent = NULL;
6590 GSList *list, *rootlist = NULL;
6593 gboolean corlib_type = FALSE;
6595 g_assert (rank <= 255);
6598 /* bounded only matters for one-dimensional arrays */
6601 image = eclass->image;
6603 if (rank == 1 && !bounded) {
6605 * This case is very frequent not just during compilation because of calls
6606 * from mono_class_from_mono_type (), mono_array_new (),
6607 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6609 mono_mutex_lock (&image->szarray_cache_lock);
6610 if (!image->szarray_cache)
6611 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6612 class = g_hash_table_lookup (image->szarray_cache, eclass);
6613 mono_mutex_unlock (&image->szarray_cache_lock);
6617 mono_loader_lock ();
6619 mono_loader_lock ();
6621 if (!image->array_cache)
6622 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6624 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6625 for (; list; list = list->next) {
6627 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6628 mono_loader_unlock ();
6635 /* for the building corlib use System.Array from it */
6636 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6637 parent = mono_class_from_name (image, "System", "Array");
6640 parent = mono_defaults.array_class;
6641 if (!parent->inited)
6642 mono_class_init (parent);
6645 class = mono_image_alloc0 (image, sizeof (MonoClass));
6647 class->image = image;
6648 class->name_space = eclass->name_space;
6649 nsize = strlen (eclass->name);
6650 name = g_malloc (nsize + 2 + rank + 1);
6651 memcpy (name, eclass->name, nsize);
6654 memset (name + nsize + 1, ',', rank - 1);
6656 name [nsize + rank] = '*';
6657 name [nsize + rank + bounded] = ']';
6658 name [nsize + rank + bounded + 1] = 0;
6659 class->name = mono_image_strdup (image, name);
6662 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6664 classes_size += sizeof (MonoClass);
6666 class->type_token = 0;
6667 /* all arrays are marked serializable and sealed, bug #42779 */
6668 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6669 class->parent = parent;
6670 class->instance_size = mono_class_instance_size (class->parent);
6672 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6673 /*Arrays of those two types are invalid.*/
6674 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6675 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6676 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6677 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6678 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6680 /* element_size -1 is ok as this is not an instantitable type*/
6681 class->sizes.element_size = -1;
6683 class->sizes.element_size = mono_class_array_element_size (eclass);
6685 mono_class_setup_supertypes (class);
6687 if (eclass->generic_class)
6688 mono_class_init (eclass);
6689 if (!eclass->size_inited)
6690 mono_class_setup_fields (eclass);
6691 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6692 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6694 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6698 if (eclass->enumtype)
6699 class->cast_class = eclass->element_class;
6701 class->cast_class = eclass;
6703 switch (class->cast_class->byval_arg.type) {
6705 class->cast_class = mono_defaults.byte_class;
6708 class->cast_class = mono_defaults.int16_class;
6711 #if SIZEOF_VOID_P == 4
6715 class->cast_class = mono_defaults.int32_class;
6718 #if SIZEOF_VOID_P == 8
6722 class->cast_class = mono_defaults.int64_class;
6728 class->element_class = eclass;
6730 if ((rank > 1) || bounded) {
6731 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6732 class->byval_arg.type = MONO_TYPE_ARRAY;
6733 class->byval_arg.data.array = at;
6734 at->eklass = eclass;
6736 /* FIXME: complete.... */
6738 class->byval_arg.type = MONO_TYPE_SZARRAY;
6739 class->byval_arg.data.klass = eclass;
6741 class->this_arg = class->byval_arg;
6742 class->this_arg.byref = 1;
6747 class->generic_container = eclass->generic_container;
6749 if (rank == 1 && !bounded) {
6750 MonoClass *prev_class;
6752 mono_mutex_lock (&image->szarray_cache_lock);
6753 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6755 /* Someone got in before us */
6758 g_hash_table_insert (image->szarray_cache, eclass, class);
6759 mono_mutex_unlock (&image->szarray_cache_lock);
6761 list = g_slist_append (rootlist, class);
6762 g_hash_table_insert (image->array_cache, eclass, list);
6765 mono_loader_unlock ();
6767 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6773 * mono_array_class_get:
6774 * @element_class: element class
6775 * @rank: the dimension of the array class
6777 * Returns: a class object describing the array with element type @element_type and
6781 mono_array_class_get (MonoClass *eclass, guint32 rank)
6783 return mono_bounded_array_class_get (eclass, rank, FALSE);
6787 * mono_class_instance_size:
6790 * Returns: the size of an object instance
6793 mono_class_instance_size (MonoClass *klass)
6795 if (!klass->size_inited)
6796 mono_class_init (klass);
6798 return klass->instance_size;
6802 * mono_class_min_align:
6805 * Returns: minimm alignment requirements
6808 mono_class_min_align (MonoClass *klass)
6810 if (!klass->size_inited)
6811 mono_class_init (klass);
6813 return klass->min_align;
6817 * mono_class_value_size:
6820 * This function is used for value types, and return the
6821 * space and the alignment to store that kind of value object.
6823 * Returns: the size of a value of kind @klass
6826 mono_class_value_size (MonoClass *klass, guint32 *align)
6830 /* fixme: check disable, because we still have external revereces to
6831 * mscorlib and Dummy Objects
6833 /*g_assert (klass->valuetype);*/
6835 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6838 *align = klass->min_align;
6844 * mono_class_data_size:
6847 * Returns: the size of the static class data
6850 mono_class_data_size (MonoClass *klass)
6853 mono_class_init (klass);
6854 /* This can happen with dynamically created types */
6855 if (!klass->fields_inited)
6856 mono_class_setup_fields_locking (klass);
6858 /* in arrays, sizes.class_size is unioned with element_size
6859 * and arrays have no static fields
6863 return klass->sizes.class_size;
6867 * Auxiliary routine to mono_class_get_field
6869 * Takes a field index instead of a field token.
6871 static MonoClassField *
6872 mono_class_get_field_idx (MonoClass *class, int idx)
6874 mono_class_setup_fields_locking (class);
6875 if (class->exception_type)
6879 if (class->image->uncompressed_metadata) {
6881 * class->field.first points to the FieldPtr table, while idx points into the
6882 * Field table, so we have to do a search.
6884 /*FIXME this is broken for types with multiple fields with the same name.*/
6885 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6888 for (i = 0; i < class->field.count; ++i)
6889 if (mono_field_get_name (&class->fields [i]) == name)
6890 return &class->fields [i];
6891 g_assert_not_reached ();
6893 if (class->field.count) {
6894 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6895 return &class->fields [idx - class->field.first];
6899 class = class->parent;
6905 * mono_class_get_field:
6906 * @class: the class to lookup the field.
6907 * @field_token: the field token
6909 * Returns: A MonoClassField representing the type and offset of
6910 * the field, or a NULL value if the field does not belong to this
6914 mono_class_get_field (MonoClass *class, guint32 field_token)
6916 int idx = mono_metadata_token_index (field_token);
6918 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6920 return mono_class_get_field_idx (class, idx - 1);
6924 * mono_class_get_field_from_name:
6925 * @klass: the class to lookup the field.
6926 * @name: the field name
6928 * Search the class @klass and it's parents for a field with the name @name.
6930 * Returns: the MonoClassField pointer of the named field or NULL
6933 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6935 return mono_class_get_field_from_name_full (klass, name, NULL);
6939 * mono_class_get_field_from_name_full:
6940 * @klass: the class to lookup the field.
6941 * @name: the field name
6942 * @type: the type of the fields. This optional.
6944 * Search the class @klass and it's parents for a field with the name @name and type @type.
6946 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6947 * of its generic type definition.
6949 * Returns: the MonoClassField pointer of the named field or NULL
6952 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6956 mono_class_setup_fields_locking (klass);
6957 if (klass->exception_type)
6961 for (i = 0; i < klass->field.count; ++i) {
6962 MonoClassField *field = &klass->fields [i];
6964 if (strcmp (name, mono_field_get_name (field)) != 0)
6968 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6969 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6974 klass = klass->parent;
6980 * mono_class_get_field_token:
6981 * @field: the field we need the token of
6983 * Get the token of a field. Note that the tokesn is only valid for the image
6984 * the field was loaded from. Don't use this function for fields in dynamic types.
6986 * Returns: the token representing the field in the image it was loaded from.
6989 mono_class_get_field_token (MonoClassField *field)
6991 MonoClass *klass = field->parent;
6994 mono_class_setup_fields_locking (klass);
6999 for (i = 0; i < klass->field.count; ++i) {
7000 if (&klass->fields [i] == field) {
7001 int idx = klass->field.first + i + 1;
7003 if (klass->image->uncompressed_metadata)
7004 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7005 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7008 klass = klass->parent;
7011 g_assert_not_reached ();
7016 mono_field_get_index (MonoClassField *field)
7018 int index = field - field->parent->fields;
7020 g_assert (index >= 0 && index < field->parent->field.count);
7026 * mono_class_get_field_default_value:
7028 * Return the default value of the field as a pointer into the metadata blob.
7031 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7034 guint32 constant_cols [MONO_CONSTANT_SIZE];
7036 MonoClass *klass = field->parent;
7038 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7040 if (!klass->ext || !klass->ext->field_def_values) {
7041 MonoFieldDefaultValue *def_values;
7043 mono_class_alloc_ext (klass);
7045 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7047 mono_image_lock (klass->image);
7048 mono_memory_barrier ();
7049 if (!klass->ext->field_def_values)
7050 klass->ext->field_def_values = def_values;
7051 mono_image_unlock (klass->image);
7054 field_index = mono_field_get_index (field);
7056 if (!klass->ext->field_def_values [field_index].data) {
7057 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7061 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7063 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7064 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7065 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7068 *def_type = klass->ext->field_def_values [field_index].def_type;
7069 return klass->ext->field_def_values [field_index].data;
7073 mono_property_get_index (MonoProperty *prop)
7075 int index = prop - prop->parent->ext->properties;
7077 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7083 * mono_class_get_property_default_value:
7085 * Return the default value of the field as a pointer into the metadata blob.
7088 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7091 guint32 constant_cols [MONO_CONSTANT_SIZE];
7092 MonoClass *klass = property->parent;
7094 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7096 * We don't cache here because it is not used by C# so it's quite rare, but
7097 * we still do the lookup in klass->ext because that is where the data
7098 * is stored for dynamic assemblies.
7101 if (image_is_dynamic (klass->image)) {
7102 int prop_index = mono_property_get_index (property);
7103 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7104 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7105 return klass->ext->prop_def_values [prop_index].data;
7109 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7113 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7114 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7115 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7119 mono_class_get_event_token (MonoEvent *event)
7121 MonoClass *klass = event->parent;
7126 for (i = 0; i < klass->ext->event.count; ++i) {
7127 if (&klass->ext->events [i] == event)
7128 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7131 klass = klass->parent;
7134 g_assert_not_reached ();
7139 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7143 gpointer iter = NULL;
7144 while ((p = mono_class_get_properties (klass, &iter))) {
7145 if (! strcmp (name, p->name))
7148 klass = klass->parent;
7154 mono_class_get_property_token (MonoProperty *prop)
7156 MonoClass *klass = prop->parent;
7160 gpointer iter = NULL;
7161 while ((p = mono_class_get_properties (klass, &iter))) {
7162 if (&klass->ext->properties [i] == prop)
7163 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7167 klass = klass->parent;
7170 g_assert_not_reached ();
7175 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7177 const char *name, *nspace;
7178 if (image_is_dynamic (image))
7179 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7181 switch (type_token & 0xff000000){
7182 case MONO_TOKEN_TYPE_DEF: {
7183 guint32 cols [MONO_TYPEDEF_SIZE];
7184 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7185 guint tidx = mono_metadata_token_index (type_token);
7187 if (tidx > tt->rows)
7188 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7190 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7191 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7192 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7193 if (strlen (nspace) == 0)
7194 return g_strdup_printf ("%s", name);
7196 return g_strdup_printf ("%s.%s", nspace, name);
7199 case MONO_TOKEN_TYPE_REF: {
7201 guint32 cols [MONO_TYPEREF_SIZE];
7202 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7203 guint tidx = mono_metadata_token_index (type_token);
7206 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7208 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7209 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7210 mono_error_cleanup (&error);
7214 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7215 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7216 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7217 if (strlen (nspace) == 0)
7218 return g_strdup_printf ("%s", name);
7220 return g_strdup_printf ("%s.%s", nspace, name);
7223 case MONO_TOKEN_TYPE_SPEC:
7224 return g_strdup_printf ("Typespec 0x%08x", type_token);
7226 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7231 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7233 if (image_is_dynamic (image))
7234 return g_strdup_printf ("DynamicAssembly %s", image->name);
7236 switch (type_token & 0xff000000){
7237 case MONO_TOKEN_TYPE_DEF:
7238 if (image->assembly)
7239 return mono_stringify_assembly_name (&image->assembly->aname);
7240 else if (image->assembly_name)
7241 return g_strdup (image->assembly_name);
7242 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7243 case MONO_TOKEN_TYPE_REF: {
7245 MonoAssemblyName aname;
7246 guint32 cols [MONO_TYPEREF_SIZE];
7247 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7248 guint32 idx = mono_metadata_token_index (type_token);
7251 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7253 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7254 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7255 mono_error_cleanup (&error);
7258 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7260 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7261 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7262 case MONO_RESOLUTION_SCOPE_MODULE:
7264 return g_strdup ("");
7265 case MONO_RESOLUTION_SCOPE_MODULEREF:
7267 return g_strdup ("");
7268 case MONO_RESOLUTION_SCOPE_TYPEREF:
7270 return g_strdup ("");
7271 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7272 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7273 return mono_stringify_assembly_name (&aname);
7275 g_assert_not_reached ();
7279 case MONO_TOKEN_TYPE_SPEC:
7281 return g_strdup ("");
7283 g_assert_not_reached ();
7290 * mono_class_get_full:
7291 * @image: the image where the class resides
7292 * @type_token: the token for the class
7293 * @context: the generic context used to evaluate generic instantiations in
7294 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7296 * Returns: the MonoClass that represents @type_token in @image
7299 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7303 class = mono_class_get_checked (image, type_token, &error);
7305 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7306 class = mono_class_inflate_generic_class_checked (class, context, &error);
7308 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7314 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7318 mono_error_init (error);
7319 class = mono_class_get_checked (image, type_token, error);
7321 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7322 class = mono_class_inflate_generic_class_checked (class, context, error);
7327 * mono_class_get_checked:
7328 * @image: the image where the class resides
7329 * @type_token: the token for the class
7330 * @error: error object to return any error
7332 * Returns: the MonoClass that represents @type_token in @image
7335 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7337 MonoClass *class = NULL;
7339 mono_error_init (error);
7341 if (image_is_dynamic (image)) {
7342 int table = mono_metadata_token_table (type_token);
7344 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7345 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7348 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7352 switch (type_token & 0xff000000){
7353 case MONO_TOKEN_TYPE_DEF:
7354 class = mono_class_create_from_typedef (image, type_token, error);
7356 case MONO_TOKEN_TYPE_REF:
7357 class = mono_class_from_typeref_checked (image, type_token, error);
7359 case MONO_TOKEN_TYPE_SPEC:
7360 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7363 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7367 /* Generic case, should be avoided for when a better error is possible. */
7368 if (!class && mono_error_ok (error)) {
7369 char *name = mono_class_name_from_token (image, type_token);
7370 char *assembly = mono_assembly_name_from_token (image, type_token);
7371 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7379 * mono_type_get_checked:
7380 * @image: the image where the type resides
7381 * @type_token: the token for the type
7382 * @context: the generic context used to evaluate generic instantiations in
7383 * @error: Error handling context
7385 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7387 * Returns: the MonoType that represents @type_token in @image
7390 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7392 MonoType *type = NULL;
7393 gboolean inflated = FALSE;
7395 mono_error_init (error);
7397 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7398 if (image_is_dynamic (image))
7399 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7401 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7402 MonoClass *class = mono_class_get_checked (image, type_token, error);
7405 g_assert (!mono_loader_get_last_error ());
7410 return mono_class_get_type (class);
7413 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7416 g_assert (!mono_loader_get_last_error ());
7421 MonoType *tmp = type;
7422 type = mono_class_get_type (mono_class_from_mono_type (type));
7423 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7424 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7425 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7427 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7429 if (type->type != tmp->type)
7432 mono_metadata_free_type (tmp);
7439 mono_class_get (MonoImage *image, guint32 type_token)
7441 return mono_class_get_full (image, type_token, NULL);
7445 * mono_image_init_name_cache:
7447 * Initializes the class name cache stored in image->name_cache.
7449 * LOCKING: Acquires the corresponding image lock.
7452 mono_image_init_name_cache (MonoImage *image)
7454 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7455 guint32 cols [MONO_TYPEDEF_SIZE];
7458 guint32 i, visib, nspace_index;
7459 GHashTable *name_cache2, *nspace_table;
7461 mono_image_lock (image);
7463 if (image->name_cache) {
7464 mono_image_unlock (image);
7468 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7470 if (image_is_dynamic (image)) {
7471 mono_image_unlock (image);
7475 /* Temporary hash table to avoid lookups in the nspace_table */
7476 name_cache2 = g_hash_table_new (NULL, NULL);
7478 for (i = 1; i <= t->rows; ++i) {
7479 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7480 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7482 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7483 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7485 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7487 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7488 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7490 nspace_index = cols [MONO_TYPEDEF_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 (i));
7501 /* Load type names from EXPORTEDTYPES table */
7503 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7504 guint32 cols [MONO_EXP_TYPE_SIZE];
7507 for (i = 0; i < t->rows; ++i) {
7508 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7509 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7510 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7512 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7513 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7514 if (!nspace_table) {
7515 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7516 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7517 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7520 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7524 g_hash_table_destroy (name_cache2);
7525 mono_image_unlock (image);
7528 /*FIXME Only dynamic assemblies should allow this operation.*/
7530 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7531 const char *name, guint32 index)
7533 GHashTable *nspace_table;
7534 GHashTable *name_cache;
7537 mono_image_lock (image);
7539 if (!image->name_cache)
7540 mono_image_init_name_cache (image);
7542 name_cache = image->name_cache;
7543 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7544 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7545 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7548 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7549 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7551 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7553 mono_image_unlock (image);
7562 find_nocase (gpointer key, gpointer value, gpointer user_data)
7564 char *name = (char*)key;
7565 FindUserData *data = (FindUserData*)user_data;
7567 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7568 data->value = value;
7572 * mono_class_from_name_case:
7573 * @image: The MonoImage where the type is looked up in
7574 * @name_space: the type namespace
7575 * @name: the type short name.
7576 * @deprecated: use the _checked variant
7578 * Obtains a MonoClass with a given namespace and a given name which
7579 * is located in the given MonoImage. The namespace and name
7580 * lookups are case insensitive.
7583 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7586 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7587 g_assert (!mono_error_ok (&error));
7592 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7594 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7595 guint32 cols [MONO_TYPEDEF_SIZE];
7600 mono_error_init (error);
7602 if (image_is_dynamic (image)) {
7604 FindUserData user_data;
7606 mono_image_lock (image);
7608 if (!image->name_cache)
7609 mono_image_init_name_cache (image);
7611 user_data.key = name_space;
7612 user_data.value = NULL;
7613 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7615 if (user_data.value) {
7616 GHashTable *nspace_table = (GHashTable*)user_data.value;
7618 user_data.key = name;
7619 user_data.value = NULL;
7621 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7623 if (user_data.value)
7624 token = GPOINTER_TO_UINT (user_data.value);
7627 mono_image_unlock (image);
7630 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7636 /* add a cache if needed */
7637 for (i = 1; i <= t->rows; ++i) {
7638 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7639 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7641 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7642 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7644 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7646 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7647 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7648 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7649 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7655 return_nested_in (MonoClass *class, char *nested)
7658 char *s = strchr (nested, '/');
7659 gpointer iter = NULL;
7666 while ((found = mono_class_get_nested_types (class, &iter))) {
7667 if (strcmp (found->name, nested) == 0) {
7669 return return_nested_in (found, s);
7677 search_modules (MonoImage *image, const char *name_space, const char *name)
7679 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7680 MonoImage *file_image;
7685 * The EXPORTEDTYPES table only contains public types, so have to search the
7687 * Note: image->modules contains the contents of the MODULEREF table, while
7688 * the real module list is in the FILE table.
7690 for (i = 0; i < file_table->rows; i++) {
7691 guint32 cols [MONO_FILE_SIZE];
7692 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7693 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7696 file_image = mono_image_load_file_for_image (image, i + 1);
7698 class = mono_class_from_name (file_image, name_space, name);
7708 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7710 GHashTable *nspace_table;
7711 MonoImage *loaded_image;
7718 mono_error_init (error);
7720 if ((nested = strchr (name, '/'))) {
7721 int pos = nested - name;
7722 int len = strlen (name);
7725 memcpy (buf, name, len + 1);
7727 nested = buf + pos + 1;
7731 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7732 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7733 gboolean res = get_class_from_name (image, name_space, name, &class);
7736 class = search_modules (image, name_space, name);
7738 return class ? return_nested_in (class, nested) : NULL;
7744 mono_image_lock (image);
7746 if (!image->name_cache)
7747 mono_image_init_name_cache (image);
7749 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7752 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7754 mono_image_unlock (image);
7756 if (!token && image_is_dynamic (image) && image->modules) {
7757 /* Search modules as well */
7758 for (i = 0; i < image->module_count; ++i) {
7759 MonoImage *module = image->modules [i];
7761 class = mono_class_from_name (module, name_space, name);
7768 class = search_modules (image, name_space, name);
7776 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7777 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7778 guint32 cols [MONO_EXP_TYPE_SIZE];
7781 idx = mono_metadata_token_index (token);
7783 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7785 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7786 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7787 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7790 class = mono_class_from_name (loaded_image, name_space, name);
7792 return return_nested_in (class, nested);
7794 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7795 guint32 assembly_idx;
7797 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7799 mono_assembly_load_reference (image, assembly_idx - 1);
7800 g_assert (image->references [assembly_idx - 1]);
7801 if (image->references [assembly_idx - 1] == (gpointer)-1)
7804 /* FIXME: Cycle detection */
7805 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7807 g_error ("not yet implemented");
7811 token = MONO_TOKEN_TYPE_DEF | token;
7813 class = mono_class_get_checked (image, token, error);
7815 return return_nested_in (class, nested);
7820 * mono_class_from_name:
7821 * @image: The MonoImage where the type is looked up in
7822 * @name_space: the type namespace
7823 * @name: the type short name.
7825 * Obtains a MonoClass with a given namespace and a given name which
7826 * is located in the given MonoImage.
7828 * To reference nested classes, use the "/" character as a separator.
7829 * For example use "Foo/Bar" to reference the class Bar that is nested
7830 * inside Foo, like this: "class Foo { class Bar {} }".
7833 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7838 klass = mono_class_from_name_checked (image, name_space, name, &error);
7839 if (!mono_error_ok (&error)) {
7840 mono_loader_set_error_from_mono_error (&error);
7841 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7847 * mono_class_is_subclass_of:
7848 * @klass: class to probe if it is a subclass of another one
7849 * @klassc: the class we suspect is the base class
7850 * @check_interfaces: whether we should perform interface checks
7852 * This method determines whether @klass is a subclass of @klassc.
7854 * If the @check_interfaces flag is set, then if @klassc is an interface
7855 * this method return true if the @klass implements the interface or
7856 * if @klass is an interface, if one of its base classes is @klass.
7858 * If @check_interfaces is false then, then if @klass is not an interface
7859 * then it returns true if the @klass is a subclass of @klassc.
7861 * if @klass is an interface and @klassc is System.Object, then this function
7866 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7867 gboolean check_interfaces)
7869 /*FIXME test for interfaces with variant generic arguments*/
7871 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7872 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7874 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7877 for (i = 0; i < klass->interface_count; i ++) {
7878 MonoClass *ic = klass->interfaces [i];
7883 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7888 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7891 if (klassc == mono_defaults.object_class)
7898 mono_type_is_generic_argument (MonoType *type)
7900 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7904 mono_class_has_variant_generic_params (MonoClass *klass)
7907 MonoGenericContainer *container;
7909 if (!klass->generic_class)
7912 container = klass->generic_class->container_class->generic_container;
7914 for (i = 0; i < container->type_argc; ++i)
7915 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7922 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7924 if (target == candidate)
7927 if (check_for_reference_conv &&
7928 mono_type_is_generic_argument (&target->byval_arg) &&
7929 mono_type_is_generic_argument (&candidate->byval_arg)) {
7930 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7931 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7933 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7936 if (!mono_class_is_assignable_from (target, candidate))
7942 * @container the generic container from the GTD
7943 * @klass: the class to be assigned to
7944 * @oklass: the source class
7946 * Both klass and oklass must be instances of the same generic interface.
7947 * Return true if @klass can be assigned to a @klass variable
7950 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7953 MonoType **klass_argv, **oklass_argv;
7954 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7955 MonoGenericContainer *container = klass_gtd->generic_container;
7957 if (klass == oklass)
7960 /*Viable candidates are instances of the same generic interface*/
7961 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7964 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7965 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7967 for (j = 0; j < container->type_argc; ++j) {
7968 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7969 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7971 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7975 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7976 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7978 if (param1_class != param2_class) {
7979 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7980 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7982 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7983 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7993 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7995 MonoGenericParam *gparam, *ogparam;
7996 MonoGenericParamInfo *tinfo, *cinfo;
7997 MonoClass **candidate_class;
7998 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8001 if (target == candidate)
8003 if (target->byval_arg.type != candidate->byval_arg.type)
8006 gparam = target->byval_arg.data.generic_param;
8007 ogparam = candidate->byval_arg.data.generic_param;
8008 tinfo = mono_generic_param_info (gparam);
8009 cinfo = mono_generic_param_info (ogparam);
8011 class_constraint_satisfied = FALSE;
8012 valuetype_constraint_satisfied = FALSE;
8014 /*candidate must have a super set of target's special constraints*/
8015 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8016 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8018 if (cinfo->constraints) {
8019 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8020 MonoClass *cc = *candidate_class;
8022 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8023 class_constraint_satisfied = TRUE;
8024 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8025 valuetype_constraint_satisfied = TRUE;
8028 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8029 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8031 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8033 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8035 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8036 valuetype_constraint_satisfied)) {
8041 /*candidate type constraints must be a superset of target's*/
8042 if (tinfo->constraints) {
8043 MonoClass **target_class;
8044 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8045 MonoClass *tc = *target_class;
8048 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8049 * check it's constraints since it satisfy the constraint by itself.
8051 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8054 if (!cinfo->constraints)
8057 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8058 MonoClass *cc = *candidate_class;
8060 if (mono_class_is_assignable_from (tc, cc))
8064 * This happens when we have the following:
8066 * Bar<K> where K : IFace
8067 * Foo<T, U> where T : U where U : IFace
8069 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8072 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8073 if (mono_gparam_is_assignable_from (target, cc))
8077 if (!*candidate_class)
8082 /*candidate itself must have a constraint that satisfy target*/
8083 if (cinfo->constraints) {
8084 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8085 MonoClass *cc = *candidate_class;
8086 if (mono_class_is_assignable_from (target, cc))
8094 * mono_class_is_assignable_from:
8095 * @klass: the class to be assigned to
8096 * @oklass: the source class
8098 * Return: true if an instance of object oklass can be assigned to an
8099 * instance of object @klass
8102 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8104 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8106 mono_class_init (klass);
8108 if (!oklass->inited)
8109 mono_class_init (oklass);
8111 if (klass->exception_type || oklass->exception_type)
8114 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8115 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8117 return mono_gparam_is_assignable_from (klass, oklass);
8120 if (MONO_CLASS_IS_INTERFACE (klass)) {
8121 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8122 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8123 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8127 for (i = 0; constraints [i]; ++i) {
8128 if (mono_class_is_assignable_from (klass, constraints [i]))
8136 /* interface_offsets might not be set for dynamic classes */
8137 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8139 * oklass might be a generic type parameter but they have
8140 * interface_offsets set.
8142 return mono_reflection_call_is_assignable_to (oklass, klass);
8143 if (!oklass->interface_bitmap)
8144 /* Happens with generic instances of not-yet created dynamic types */
8146 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8149 if (mono_class_has_variant_generic_params (klass)) {
8152 mono_class_setup_interfaces (oklass, &error);
8153 if (!mono_error_ok (&error)) {
8154 mono_error_cleanup (&error);
8158 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8159 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8160 MonoClass *iface = oklass->interfaces_packed [i];
8162 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8167 } else if (klass->delegate) {
8168 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8170 }else if (klass->rank) {
8171 MonoClass *eclass, *eoclass;
8173 if (oklass->rank != klass->rank)
8176 /* vectors vs. one dimensional arrays */
8177 if (oklass->byval_arg.type != klass->byval_arg.type)
8180 eclass = klass->cast_class;
8181 eoclass = oklass->cast_class;
8184 * a is b does not imply a[] is b[] when a is a valuetype, and
8185 * b is a reference type.
8188 if (eoclass->valuetype) {
8189 if ((eclass == mono_defaults.enum_class) ||
8190 (eclass == mono_defaults.enum_class->parent) ||
8191 (eclass == mono_defaults.object_class))
8195 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8196 } else if (mono_class_is_nullable (klass)) {
8197 if (mono_class_is_nullable (oklass))
8198 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8200 return mono_class_is_assignable_from (klass->cast_class, oklass);
8201 } else if (klass == mono_defaults.object_class)
8204 return mono_class_has_parent (oklass, klass);
8207 /*Check if @oklass is variant compatible with @klass.*/
8209 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8212 MonoType **klass_argv, **oklass_argv;
8213 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8214 MonoGenericContainer *container = klass_gtd->generic_container;
8216 /*Viable candidates are instances of the same generic interface*/
8217 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8220 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8221 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8223 for (j = 0; j < container->type_argc; ++j) {
8224 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8225 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8227 if (param1_class->valuetype != param2_class->valuetype)
8231 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8232 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8234 if (param1_class != param2_class) {
8235 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8236 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8238 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8239 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8247 /*Check if @candidate implements the interface @target*/
8249 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8253 gboolean is_variant = mono_class_has_variant_generic_params (target);
8255 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8256 if (mono_class_is_variant_compatible_slow (target, candidate))
8261 if (candidate == target)
8264 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8265 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8266 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8268 if (tb && tb->interfaces) {
8269 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8270 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8271 MonoClass *iface_class;
8273 /* we can't realize the type here since it can do pretty much anything. */
8276 iface_class = mono_class_from_mono_type (iface->type);
8277 if (iface_class == target)
8279 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8281 if (mono_class_implement_interface_slow (target, iface_class))
8286 /*setup_interfaces don't mono_class_init anything*/
8287 /*FIXME this doesn't handle primitive type arrays.
8288 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8289 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8291 mono_class_setup_interfaces (candidate, &error);
8292 if (!mono_error_ok (&error)) {
8293 mono_error_cleanup (&error);
8297 for (i = 0; i < candidate->interface_count; ++i) {
8298 if (candidate->interfaces [i] == target)
8301 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8304 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8308 candidate = candidate->parent;
8309 } while (candidate);
8315 * Check if @oklass can be assigned to @klass.
8316 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8319 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8321 if (candidate == target)
8323 if (target == mono_defaults.object_class)
8326 if (mono_class_has_parent (candidate, target))
8329 /*If target is not an interface there is no need to check them.*/
8330 if (MONO_CLASS_IS_INTERFACE (target))
8331 return mono_class_implement_interface_slow (target, candidate);
8333 if (target->delegate && mono_class_has_variant_generic_params (target))
8334 return mono_class_is_variant_compatible (target, candidate, FALSE);
8337 MonoClass *eclass, *eoclass;
8339 if (target->rank != candidate->rank)
8342 /* vectors vs. one dimensional arrays */
8343 if (target->byval_arg.type != candidate->byval_arg.type)
8346 eclass = target->cast_class;
8347 eoclass = candidate->cast_class;
8350 * a is b does not imply a[] is b[] when a is a valuetype, and
8351 * b is a reference type.
8354 if (eoclass->valuetype) {
8355 if ((eclass == mono_defaults.enum_class) ||
8356 (eclass == mono_defaults.enum_class->parent) ||
8357 (eclass == mono_defaults.object_class))
8361 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8363 /*FIXME properly handle nullables */
8364 /*FIXME properly handle (M)VAR */
8369 * mono_class_get_cctor:
8370 * @klass: A MonoClass pointer
8372 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8375 mono_class_get_cctor (MonoClass *klass)
8377 MonoCachedClassInfo cached_info;
8379 if (image_is_dynamic (klass->image)) {
8381 * has_cctor is not set for these classes because mono_class_init () is
8384 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8387 if (!klass->has_cctor)
8390 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8392 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8393 if (!mono_error_ok (&error))
8394 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8398 if (klass->generic_class && !klass->methods)
8399 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8401 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8405 * mono_class_get_finalizer:
8406 * @klass: The MonoClass pointer
8408 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8411 mono_class_get_finalizer (MonoClass *klass)
8413 MonoCachedClassInfo cached_info;
8416 mono_class_init (klass);
8417 if (!mono_class_has_finalizer (klass))
8420 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8422 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8423 if (!mono_error_ok (&error))
8424 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8427 mono_class_setup_vtable (klass);
8428 return klass->vtable [finalize_slot];
8433 * mono_class_needs_cctor_run:
8434 * @klass: the MonoClass pointer
8435 * @caller: a MonoMethod describing the caller
8437 * Determines whenever the class has a static constructor and whenever it
8438 * needs to be called when executing CALLER.
8441 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8445 method = mono_class_get_cctor (klass);
8447 return (method == caller) ? FALSE : TRUE;
8453 * mono_class_array_element_size:
8456 * Returns: the number of bytes an element of type @klass
8457 * uses when stored into an array.
8460 mono_class_array_element_size (MonoClass *klass)
8462 MonoType *type = &klass->byval_arg;
8465 switch (type->type) {
8468 case MONO_TYPE_BOOLEAN:
8472 case MONO_TYPE_CHAR:
8481 case MONO_TYPE_CLASS:
8482 case MONO_TYPE_STRING:
8483 case MONO_TYPE_OBJECT:
8484 case MONO_TYPE_SZARRAY:
8485 case MONO_TYPE_ARRAY:
8486 return sizeof (gpointer);
8491 case MONO_TYPE_VALUETYPE:
8492 if (type->data.klass->enumtype) {
8493 type = mono_class_enum_basetype (type->data.klass);
8494 klass = klass->element_class;
8497 return mono_class_instance_size (klass) - sizeof (MonoObject);
8498 case MONO_TYPE_GENERICINST:
8499 type = &type->data.generic_class->container_class->byval_arg;
8502 case MONO_TYPE_MVAR: {
8505 return mono_type_size (type, &align);
8507 case MONO_TYPE_VOID:
8511 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8517 * mono_array_element_size:
8518 * @ac: pointer to a #MonoArrayClass
8520 * Returns: the size of single array element.
8523 mono_array_element_size (MonoClass *ac)
8525 g_assert (ac->rank);
8526 return ac->sizes.element_size;
8530 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8531 MonoGenericContext *context)
8534 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8535 g_assert (mono_error_ok (&error));
8540 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8541 MonoGenericContext *context, MonoError *error)
8543 mono_error_init (error);
8545 if (image_is_dynamic (image)) {
8546 MonoClass *tmp_handle_class;
8547 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8549 g_assert (tmp_handle_class);
8551 *handle_class = tmp_handle_class;
8553 if (tmp_handle_class == mono_defaults.typehandle_class)
8554 return &((MonoClass*)obj)->byval_arg;
8559 switch (token & 0xff000000) {
8560 case MONO_TOKEN_TYPE_DEF:
8561 case MONO_TOKEN_TYPE_REF:
8562 case MONO_TOKEN_TYPE_SPEC: {
8565 *handle_class = mono_defaults.typehandle_class;
8566 type = mono_type_get_checked (image, token, context, error);
8570 mono_class_init (mono_class_from_mono_type (type));
8571 /* We return a MonoType* as handle */
8574 case MONO_TOKEN_FIELD_DEF: {
8576 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8578 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8582 *handle_class = mono_defaults.fieldhandle_class;
8583 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8587 mono_class_init (class);
8588 return mono_class_get_field (class, token);
8590 case MONO_TOKEN_METHOD_DEF:
8591 case MONO_TOKEN_METHOD_SPEC: {
8593 meth = mono_get_method_checked (image, token, NULL, context, error);
8595 *handle_class = mono_defaults.methodhandle_class;
8601 case MONO_TOKEN_MEMBER_REF: {
8602 guint32 cols [MONO_MEMBERREF_SIZE];
8604 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8605 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8606 mono_metadata_decode_blob_size (sig, &sig);
8607 if (*sig == 0x6) { /* it's a field */
8609 MonoClassField *field;
8610 field = mono_field_from_token_checked (image, token, &klass, context, error);
8612 *handle_class = mono_defaults.fieldhandle_class;
8616 meth = mono_get_method_checked (image, token, NULL, context, error);
8618 *handle_class = mono_defaults.methodhandle_class;
8623 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8629 * This function might need to call runtime functions so it can't be part
8630 * of the metadata library.
8632 static MonoLookupDynamicToken lookup_dynamic = NULL;
8635 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8637 lookup_dynamic = func;
8641 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8643 MonoClass *handle_class;
8645 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8649 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8651 return lookup_dynamic (image, token, valid_token, handle_class, context);
8654 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8657 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8659 get_cached_class_info = func;
8663 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8665 if (!get_cached_class_info)
8668 return get_cached_class_info (klass, res);
8672 mono_install_get_class_from_name (MonoGetClassFromName func)
8674 get_class_from_name = func;
8678 mono_class_get_image (MonoClass *klass)
8680 return klass->image;
8684 * mono_class_get_element_class:
8685 * @klass: the MonoClass to act on
8687 * Returns: the element class of an array or an enumeration.
8690 mono_class_get_element_class (MonoClass *klass)
8692 return klass->element_class;
8696 * mono_class_is_valuetype:
8697 * @klass: the MonoClass to act on
8699 * Returns: true if the MonoClass represents a ValueType.
8702 mono_class_is_valuetype (MonoClass *klass)
8704 return klass->valuetype;
8708 * mono_class_is_enum:
8709 * @klass: the MonoClass to act on
8711 * Returns: true if the MonoClass represents an enumeration.
8714 mono_class_is_enum (MonoClass *klass)
8716 return klass->enumtype;
8720 * mono_class_enum_basetype:
8721 * @klass: the MonoClass to act on
8723 * Returns: the underlying type representation for an enumeration.
8726 mono_class_enum_basetype (MonoClass *klass)
8728 if (klass->element_class == klass)
8729 /* SRE or broken types */
8732 return &klass->element_class->byval_arg;
8736 * mono_class_get_parent
8737 * @klass: the MonoClass to act on
8739 * Returns: the parent class for this class.
8742 mono_class_get_parent (MonoClass *klass)
8744 return klass->parent;
8748 * mono_class_get_nesting_type;
8749 * @klass: the MonoClass to act on
8751 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8754 mono_class_get_nesting_type (MonoClass *klass)
8756 return klass->nested_in;
8760 * mono_class_get_rank:
8761 * @klass: the MonoClass to act on
8763 * Returns: the rank for the array (the number of dimensions).
8766 mono_class_get_rank (MonoClass *klass)
8772 * mono_class_get_flags:
8773 * @klass: the MonoClass to act on
8775 * The type flags from the TypeDef table from the metadata.
8776 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8779 * Returns: the flags from the TypeDef table.
8782 mono_class_get_flags (MonoClass *klass)
8784 return klass->flags;
8788 * mono_class_get_name
8789 * @klass: the MonoClass to act on
8791 * Returns: the name of the class.
8794 mono_class_get_name (MonoClass *klass)
8800 * mono_class_get_namespace:
8801 * @klass: the MonoClass to act on
8803 * Returns: the namespace of the class.
8806 mono_class_get_namespace (MonoClass *klass)
8808 return klass->name_space;
8812 * mono_class_get_type:
8813 * @klass: the MonoClass to act on
8815 * This method returns the internal Type representation for the class.
8817 * Returns: the MonoType from the class.
8820 mono_class_get_type (MonoClass *klass)
8822 return &klass->byval_arg;
8826 * mono_class_get_type_token
8827 * @klass: the MonoClass to act on
8829 * This method returns type token for the class.
8831 * Returns: the type token for the class.
8834 mono_class_get_type_token (MonoClass *klass)
8836 return klass->type_token;
8840 * mono_class_get_byref_type:
8841 * @klass: the MonoClass to act on
8846 mono_class_get_byref_type (MonoClass *klass)
8848 return &klass->this_arg;
8852 * mono_class_num_fields:
8853 * @klass: the MonoClass to act on
8855 * Returns: the number of static and instance fields in the class.
8858 mono_class_num_fields (MonoClass *klass)
8860 return klass->field.count;
8864 * mono_class_num_methods:
8865 * @klass: the MonoClass to act on
8867 * Returns: the number of methods in the class.
8870 mono_class_num_methods (MonoClass *klass)
8872 return klass->method.count;
8876 * mono_class_num_properties
8877 * @klass: the MonoClass to act on
8879 * Returns: the number of properties in the class.
8882 mono_class_num_properties (MonoClass *klass)
8884 mono_class_setup_properties (klass);
8886 return klass->ext->property.count;
8890 * mono_class_num_events:
8891 * @klass: the MonoClass to act on
8893 * Returns: the number of events in the class.
8896 mono_class_num_events (MonoClass *klass)
8898 mono_class_setup_events (klass);
8900 return klass->ext->event.count;
8904 * mono_class_get_fields:
8905 * @klass: the MonoClass to act on
8907 * This routine is an iterator routine for retrieving the fields in a class.
8909 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8910 * iterate over all of the elements. When no more values are
8911 * available, the return value is NULL.
8913 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8916 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8918 MonoClassField* field;
8922 mono_class_setup_fields_locking (klass);
8923 if (klass->exception_type)
8925 /* start from the first */
8926 if (klass->field.count) {
8927 return *iter = &klass->fields [0];
8935 if (field < &klass->fields [klass->field.count]) {
8936 return *iter = field;
8942 * mono_class_get_methods
8943 * @klass: the MonoClass to act on
8945 * This routine is an iterator routine for retrieving the fields in a class.
8947 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8948 * iterate over all of the elements. When no more values are
8949 * available, the return value is NULL.
8951 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8954 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8956 MonoMethod** method;
8960 mono_class_setup_methods (klass);
8963 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8964 * FIXME we should better report this error to the caller
8966 if (!klass->methods)
8968 /* start from the first */
8969 if (klass->method.count) {
8970 *iter = &klass->methods [0];
8971 return klass->methods [0];
8979 if (method < &klass->methods [klass->method.count]) {
8987 * mono_class_get_virtual_methods:
8989 * Iterate over the virtual methods of KLASS.
8991 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8994 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8996 MonoMethod** method;
8999 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9001 mono_class_setup_methods (klass);
9003 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9004 * FIXME we should better report this error to the caller
9006 if (!klass->methods)
9008 /* start from the first */
9009 method = &klass->methods [0];
9014 while (method < &klass->methods [klass->method.count]) {
9015 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9019 if (method < &klass->methods [klass->method.count]) {
9026 /* Search directly in metadata to avoid calling setup_methods () */
9027 MonoMethod *res = NULL;
9033 start_index = GPOINTER_TO_UINT (*iter);
9036 for (i = start_index; i < klass->method.count; ++i) {
9039 /* class->method.first points into the methodptr table */
9040 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9042 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9046 if (i < klass->method.count) {
9048 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9049 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9051 /* Add 1 here so the if (*iter) check fails */
9052 *iter = GUINT_TO_POINTER (i + 1);
9061 * mono_class_get_properties:
9062 * @klass: the MonoClass to act on
9064 * This routine is an iterator routine for retrieving the properties in a class.
9066 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9067 * iterate over all of the elements. When no more values are
9068 * available, the return value is NULL.
9070 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9073 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9075 MonoProperty* property;
9079 mono_class_setup_properties (klass);
9080 /* start from the first */
9081 if (klass->ext->property.count) {
9082 return *iter = &klass->ext->properties [0];
9090 if (property < &klass->ext->properties [klass->ext->property.count]) {
9091 return *iter = property;
9097 * mono_class_get_events:
9098 * @klass: the MonoClass to act on
9100 * This routine is an iterator routine for retrieving the properties in a class.
9102 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9103 * iterate over all of the elements. When no more values are
9104 * available, the return value is NULL.
9106 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9109 mono_class_get_events (MonoClass* klass, gpointer *iter)
9115 mono_class_setup_events (klass);
9116 /* start from the first */
9117 if (klass->ext->event.count) {
9118 return *iter = &klass->ext->events [0];
9126 if (event < &klass->ext->events [klass->ext->event.count]) {
9127 return *iter = event;
9133 * mono_class_get_interfaces
9134 * @klass: the MonoClass to act on
9136 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9138 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9139 * iterate over all of the elements. When no more values are
9140 * available, the return value is NULL.
9142 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9145 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9153 mono_class_init (klass);
9154 if (!klass->interfaces_inited) {
9155 mono_class_setup_interfaces (klass, &error);
9156 if (!mono_error_ok (&error)) {
9157 mono_error_cleanup (&error);
9161 /* start from the first */
9162 if (klass->interface_count) {
9163 *iter = &klass->interfaces [0];
9164 return klass->interfaces [0];
9172 if (iface < &klass->interfaces [klass->interface_count]) {
9180 setup_nested_types (MonoClass *klass)
9183 GList *classes, *nested_classes, *l;
9186 if (klass->nested_classes_inited)
9189 if (!klass->type_token)
9190 klass->nested_classes_inited = TRUE;
9192 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9196 guint32 cols [MONO_NESTED_CLASS_SIZE];
9197 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9198 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9199 if (!mono_error_ok (&error)) {
9200 /*FIXME don't swallow the error message*/
9201 mono_error_cleanup (&error);
9203 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9207 classes = g_list_prepend (classes, nclass);
9209 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9212 mono_class_alloc_ext (klass);
9214 nested_classes = NULL;
9215 for (l = classes; l; l = l->next)
9216 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9217 g_list_free (classes);
9219 mono_image_lock (klass->image);
9221 mono_memory_barrier ();
9222 if (!klass->nested_classes_inited) {
9223 klass->ext->nested_classes = nested_classes;
9224 mono_memory_barrier ();
9225 klass->nested_classes_inited = TRUE;
9228 mono_image_unlock (klass->image);
9232 * mono_class_get_nested_types
9233 * @klass: the MonoClass to act on
9235 * This routine is an iterator routine for retrieving the nested types of a class.
9236 * This works only if @klass is non-generic, or a generic type definition.
9238 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9239 * iterate over all of the elements. When no more values are
9240 * available, the return value is NULL.
9242 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9245 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9251 if (!klass->nested_classes_inited)
9252 setup_nested_types (klass);
9255 /* start from the first */
9256 if (klass->ext && klass->ext->nested_classes) {
9257 *iter = klass->ext->nested_classes;
9258 return klass->ext->nested_classes->data;
9260 /* no nested types */
9275 * mono_class_is_delegate
9276 * @klass: the MonoClass to act on
9278 * Returns: true if the MonoClass represents a System.Delegate.
9281 mono_class_is_delegate (MonoClass *klass)
9283 return klass->delegate;
9287 * mono_class_implements_interface
9288 * @klass: The MonoClass to act on
9289 * @interface: The interface to check if @klass implements.
9291 * Returns: true if @klass implements @interface.
9294 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9296 return mono_class_is_assignable_from (iface, klass);
9300 * mono_field_get_name:
9301 * @field: the MonoClassField to act on
9303 * Returns: the name of the field.
9306 mono_field_get_name (MonoClassField *field)
9312 * mono_field_get_type:
9313 * @field: the MonoClassField to act on
9315 * Returns: MonoType of the field.
9318 mono_field_get_type (MonoClassField *field)
9321 MonoType *type = mono_field_get_type_checked (field, &error);
9322 if (!mono_error_ok (&error)) {
9323 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9324 mono_error_cleanup (&error);
9331 * mono_field_get_type_checked:
9332 * @field: the MonoClassField to act on
9333 * @error: used to return any erro found while retrieving @field type
9335 * Returns: MonoType of the field.
9338 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9340 mono_error_init (error);
9342 mono_field_resolve_type (field, error);
9347 * mono_field_get_parent:
9348 * @field: the MonoClassField to act on
9350 * Returns: MonoClass where the field was defined.
9353 mono_field_get_parent (MonoClassField *field)
9355 return field->parent;
9359 * mono_field_get_flags;
9360 * @field: the MonoClassField to act on
9362 * The metadata flags for a field are encoded using the
9363 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9365 * Returns: the flags for the field.
9368 mono_field_get_flags (MonoClassField *field)
9371 return mono_field_resolve_flags (field);
9372 return field->type->attrs;
9376 * mono_field_get_offset;
9377 * @field: the MonoClassField to act on
9379 * Returns: the field offset.
9382 mono_field_get_offset (MonoClassField *field)
9384 return field->offset;
9388 mono_field_get_rva (MonoClassField *field)
9392 MonoClass *klass = field->parent;
9393 MonoFieldDefaultValue *field_def_values;
9395 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9397 if (!klass->ext || !klass->ext->field_def_values) {
9398 mono_class_alloc_ext (klass);
9400 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9402 mono_image_lock (klass->image);
9403 if (!klass->ext->field_def_values)
9404 klass->ext->field_def_values = field_def_values;
9405 mono_image_unlock (klass->image);
9408 field_index = mono_field_get_index (field);
9410 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9411 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9413 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9414 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9417 return klass->ext->field_def_values [field_index].data;
9421 * mono_field_get_data;
9422 * @field: the MonoClassField to act on
9424 * Returns: pointer to the metadata constant value or to the field
9425 * data if it has an RVA flag.
9428 mono_field_get_data (MonoClassField *field)
9430 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9431 MonoTypeEnum def_type;
9433 return mono_class_get_field_default_value (field, &def_type);
9434 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9435 return mono_field_get_rva (field);
9442 * mono_property_get_name:
9443 * @prop: the MonoProperty to act on
9445 * Returns: the name of the property
9448 mono_property_get_name (MonoProperty *prop)
9454 * mono_property_get_set_method
9455 * @prop: the MonoProperty to act on.
9457 * Returns: the setter method of the property (A MonoMethod)
9460 mono_property_get_set_method (MonoProperty *prop)
9466 * mono_property_get_get_method
9467 * @prop: the MonoProperty to act on.
9469 * Returns: the setter method of the property (A MonoMethod)
9472 mono_property_get_get_method (MonoProperty *prop)
9478 * mono_property_get_parent:
9479 * @prop: the MonoProperty to act on.
9481 * Returns: the MonoClass where the property was defined.
9484 mono_property_get_parent (MonoProperty *prop)
9486 return prop->parent;
9490 * mono_property_get_flags:
9491 * @prop: the MonoProperty to act on.
9493 * The metadata flags for a property are encoded using the
9494 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9496 * Returns: the flags for the property.
9499 mono_property_get_flags (MonoProperty *prop)
9505 * mono_event_get_name:
9506 * @event: the MonoEvent to act on
9508 * Returns: the name of the event.
9511 mono_event_get_name (MonoEvent *event)
9517 * mono_event_get_add_method:
9518 * @event: The MonoEvent to act on.
9520 * Returns: the @add' method for the event (a MonoMethod).
9523 mono_event_get_add_method (MonoEvent *event)
9529 * mono_event_get_remove_method:
9530 * @event: The MonoEvent to act on.
9532 * Returns: the @remove method for the event (a MonoMethod).
9535 mono_event_get_remove_method (MonoEvent *event)
9537 return event->remove;
9541 * mono_event_get_raise_method:
9542 * @event: The MonoEvent to act on.
9544 * Returns: the @raise method for the event (a MonoMethod).
9547 mono_event_get_raise_method (MonoEvent *event)
9549 return event->raise;
9553 * mono_event_get_parent:
9554 * @event: the MonoEvent to act on.
9556 * Returns: the MonoClass where the event is defined.
9559 mono_event_get_parent (MonoEvent *event)
9561 return event->parent;
9565 * mono_event_get_flags
9566 * @event: the MonoEvent to act on.
9568 * The metadata flags for an event are encoded using the
9569 * EVENT_* constants. See the tabledefs.h file for details.
9571 * Returns: the flags for the event.
9574 mono_event_get_flags (MonoEvent *event)
9576 return event->attrs;
9580 * mono_class_get_method_from_name:
9581 * @klass: where to look for the method
9582 * @name: name of the method
9583 * @param_count: number of parameters. -1 for any number.
9585 * Obtains a MonoMethod with a given name and number of parameters.
9586 * It only works if there are no multiple signatures for any given method name.
9589 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9591 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9595 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9597 MonoMethod *res = NULL;
9600 /* Search directly in the metadata to avoid calling setup_methods () */
9601 for (i = 0; i < klass->method.count; ++i) {
9603 guint32 cols [MONO_METHOD_SIZE];
9605 MonoMethodSignature *sig;
9607 /* class->method.first points into the methodptr table */
9608 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9610 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9611 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9613 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9616 if (param_count == -1) {
9620 sig = mono_method_signature_checked (method, &error);
9622 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9625 if (sig->param_count == param_count) {
9636 * mono_class_get_method_from_name_flags:
9637 * @klass: where to look for the method
9638 * @name_space: name of the method
9639 * @param_count: number of parameters. -1 for any number.
9640 * @flags: flags which must be set in the method
9642 * Obtains a MonoMethod with a given name and number of parameters.
9643 * It only works if there are no multiple signatures for any given method name.
9646 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9648 MonoMethod *res = NULL;
9651 mono_class_init (klass);
9653 if (klass->generic_class && !klass->methods) {
9654 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9657 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9658 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9663 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9664 mono_class_setup_methods (klass);
9666 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9667 See mono/tests/array_load_exception.il
9668 FIXME we should better report this error to the caller
9670 if (!klass->methods)
9672 for (i = 0; i < klass->method.count; ++i) {
9673 MonoMethod *method = klass->methods [i];
9675 if (method->name[0] == name [0] &&
9676 !strcmp (name, method->name) &&
9677 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9678 ((method->flags & flags) == flags)) {
9685 res = find_method_in_metadata (klass, name, param_count, flags);
9692 * mono_class_set_failure:
9693 * @klass: class in which the failure was detected
9694 * @ex_type: the kind of exception/error to be thrown (later)
9695 * @ex_data: exception data (specific to each type of exception/error)
9697 * Keep a detected failure informations in the class for later processing.
9698 * Note that only the first failure is kept.
9700 * LOCKING: Acquires the loader lock.
9703 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9705 if (klass->exception_type)
9708 mono_loader_lock ();
9709 klass->exception_type = ex_type;
9711 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9712 mono_loader_unlock ();
9718 * mono_class_get_exception_data:
9720 * Return the exception_data property of KLASS.
9722 * LOCKING: Acquires the loader lock.
9725 mono_class_get_exception_data (MonoClass *klass)
9727 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9731 * mono_classes_init:
9733 * Initialize the resources used by this module.
9736 mono_classes_init (void)
9738 mono_mutex_init (&classes_mutex);
9740 mono_counters_register ("Inflated methods size",
9741 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9742 mono_counters_register ("Inflated classes",
9743 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9744 mono_counters_register ("Inflated classes size",
9745 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9746 mono_counters_register ("MonoClass size",
9747 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9748 mono_counters_register ("MonoClassExt size",
9749 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9753 * mono_classes_cleanup:
9755 * Free the resources used by this module.
9758 mono_classes_cleanup (void)
9760 if (global_interface_bitset)
9761 mono_bitset_free (global_interface_bitset);
9762 global_interface_bitset = NULL;
9763 mono_mutex_destroy (&classes_mutex);
9767 * mono_class_get_exception_for_failure:
9768 * @klass: class in which the failure was detected
9770 * Return a constructed MonoException than the caller can then throw
9771 * using mono_raise_exception - or NULL if no failure is present (or
9772 * doesn't result in an exception).
9775 mono_class_get_exception_for_failure (MonoClass *klass)
9777 gpointer exception_data = mono_class_get_exception_data (klass);
9779 switch (klass->exception_type) {
9780 #ifndef DISABLE_SECURITY
9781 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9782 MonoDomain *domain = mono_domain_get ();
9783 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9784 MonoMethod *method = exception_data;
9785 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9786 MonoObject *exc = NULL;
9790 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9791 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9792 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9794 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9795 return (MonoException*) exc;
9798 case MONO_EXCEPTION_TYPE_LOAD: {
9801 char *str = mono_type_get_full_name (klass);
9802 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9803 name = mono_string_new (mono_domain_get (), str);
9805 ex = mono_get_exception_type_load (name, astr);
9809 case MONO_EXCEPTION_MISSING_METHOD: {
9810 char *class_name = exception_data;
9811 char *assembly_name = class_name + strlen (class_name) + 1;
9813 return mono_get_exception_missing_method (class_name, assembly_name);
9815 case MONO_EXCEPTION_MISSING_FIELD: {
9816 char *class_name = exception_data;
9817 char *member_name = class_name + strlen (class_name) + 1;
9819 return mono_get_exception_missing_field (class_name, member_name);
9821 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9822 char *msg_format = exception_data;
9823 char *assembly_name = msg_format + strlen (msg_format) + 1;
9824 char *msg = g_strdup_printf (msg_format, assembly_name);
9827 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9833 case MONO_EXCEPTION_BAD_IMAGE: {
9834 return mono_get_exception_bad_image_format (exception_data);
9837 MonoLoaderError *error;
9840 error = mono_loader_get_last_error ();
9842 ex = mono_loader_error_prepare_exception (error);
9846 /* TODO - handle other class related failures */
9853 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9855 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9856 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9858 if (outer_klass == inner_klass)
9860 inner_klass = inner_klass->nested_in;
9861 } while (inner_klass);
9866 mono_class_get_generic_type_definition (MonoClass *klass)
9868 return klass->generic_class ? klass->generic_class->container_class : klass;
9872 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9874 * Generic instantiations are ignored for all super types of @klass.
9876 * Visibility checks ignoring generic instantiations.
9879 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9882 klass = mono_class_get_generic_type_definition (klass);
9883 parent = mono_class_get_generic_type_definition (parent);
9884 mono_class_setup_supertypes (klass);
9886 for (i = 0; i < klass->idepth; ++i) {
9887 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9893 * Subtype can only access parent members with family protection if the site object
9894 * is subclass of Subtype. For example:
9895 * class A { protected int x; }
9897 * void valid_access () {
9901 * void invalid_access () {
9908 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9910 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9913 if (context_klass == NULL)
9915 /*if access_klass is not member_klass context_klass must be type compat*/
9916 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9922 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9925 if (accessing == accessed)
9927 if (!accessed || !accessing)
9930 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9931 * anywhere so untrusted friends are not safe to access platform's code internals */
9932 if (mono_security_core_clr_enabled ()) {
9933 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9937 mono_assembly_load_friends (accessed);
9938 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9939 MonoAssemblyName *friend = tmp->data;
9940 /* Be conservative with checks */
9943 if (strcmp (accessing->aname.name, friend->name))
9945 if (friend->public_key_token [0]) {
9946 if (!accessing->aname.public_key_token [0])
9948 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9957 * If klass is a generic type or if it is derived from a generic type, return the
9958 * MonoClass of the generic definition
9959 * Returns NULL if not found
9962 get_generic_definition_class (MonoClass *klass)
9965 if (klass->generic_class && klass->generic_class->container_class)
9966 return klass->generic_class->container_class;
9967 klass = klass->parent;
9973 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9976 for (i = 0; i < ginst->type_argc; ++i) {
9977 MonoType *type = ginst->type_argv[i];
9978 switch (type->type) {
9979 case MONO_TYPE_SZARRAY:
9980 if (!can_access_type (access_klass, type->data.klass))
9983 case MONO_TYPE_ARRAY:
9984 if (!can_access_type (access_klass, type->data.array->eklass))
9988 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9991 case MONO_TYPE_CLASS:
9992 case MONO_TYPE_VALUETYPE:
9993 case MONO_TYPE_GENERICINST:
9994 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10004 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10008 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10011 if (access_klass->element_class && !access_klass->enumtype)
10012 access_klass = access_klass->element_class;
10014 if (member_klass->element_class && !member_klass->enumtype)
10015 member_klass = member_klass->element_class;
10017 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10019 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10022 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10025 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10028 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10031 /*Non nested type with nested visibility. We just fail it.*/
10032 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10035 switch (access_level) {
10036 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10037 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10039 case TYPE_ATTRIBUTE_PUBLIC:
10042 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10045 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10046 return is_nesting_type (member_klass, access_klass);
10048 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10049 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10051 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10052 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10054 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10055 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10056 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10058 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10059 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10060 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10065 /* FIXME: check visibility of type, too */
10067 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10069 MonoClass *member_generic_def;
10070 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10073 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10074 access_klass->generic_container) &&
10075 (member_generic_def = get_generic_definition_class (member_klass))) {
10076 MonoClass *access_container;
10078 if (access_klass->generic_container)
10079 access_container = access_klass;
10081 access_container = access_klass->generic_class->container_class;
10083 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10087 /* Partition I 8.5.3.2 */
10088 /* the access level values are the same for fields and methods */
10089 switch (access_level) {
10090 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10091 /* same compilation unit */
10092 return access_klass->image == member_klass->image;
10093 case FIELD_ATTRIBUTE_PRIVATE:
10094 return access_klass == member_klass;
10095 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10096 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10097 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10100 case FIELD_ATTRIBUTE_ASSEMBLY:
10101 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10102 case FIELD_ATTRIBUTE_FAMILY:
10103 if (is_valid_family_access (access_klass, member_klass, context_klass))
10106 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10107 if (is_valid_family_access (access_klass, member_klass, context_klass))
10109 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10110 case FIELD_ATTRIBUTE_PUBLIC:
10117 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10119 /* FIXME: check all overlapping fields */
10120 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10122 MonoClass *nested = method->klass->nested_in;
10124 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10127 nested = nested->nested_in;
10134 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10136 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10138 MonoClass *nested = method->klass->nested_in;
10140 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10143 nested = nested->nested_in;
10148 * with generics calls to explicit interface implementations can be expressed
10149 * directly: the method is private, but we must allow it. This may be opening
10150 * a hole or the generics code should handle this differently.
10151 * Maybe just ensure the interface type is public.
10153 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10159 * mono_method_can_access_method_full:
10160 * @method: The caller method
10161 * @called: The called method
10162 * @context_klass: The static type on stack of the owner @called object used
10164 * This function must be used with instance calls, as they have more strict family accessibility.
10165 * It can be used with static methods, but context_klass should be NULL.
10167 * Returns: TRUE if caller have proper visibility and acessibility to @called
10170 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10172 MonoClass *access_class = method->klass;
10173 MonoClass *member_class = called->klass;
10174 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10176 MonoClass *nested = access_class->nested_in;
10178 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10181 nested = nested->nested_in;
10188 can = can_access_type (access_class, member_class);
10190 MonoClass *nested = access_class->nested_in;
10192 can = can_access_type (nested, member_class);
10195 nested = nested->nested_in;
10202 if (called->is_inflated) {
10203 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10204 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10213 * mono_method_can_access_field_full:
10214 * @method: The caller method
10215 * @field: The accessed field
10216 * @context_klass: The static type on stack of the owner @field object used
10218 * This function must be used with instance fields, as they have more strict family accessibility.
10219 * It can be used with static fields, but context_klass should be NULL.
10221 * Returns: TRUE if caller have proper visibility and acessibility to @field
10224 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10226 MonoClass *access_class = method->klass;
10227 MonoClass *member_class = field->parent;
10228 /* FIXME: check all overlapping fields */
10229 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10231 MonoClass *nested = access_class->nested_in;
10233 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10236 nested = nested->nested_in;
10243 can = can_access_type (access_class, member_class);
10245 MonoClass *nested = access_class->nested_in;
10247 can = can_access_type (nested, member_class);
10250 nested = nested->nested_in;
10260 * mono_class_can_access_class:
10261 * @source_class: The source class
10262 * @target_class: The accessed class
10264 * This function returns is @target_class is visible to @source_class
10266 * Returns: TRUE if source have proper visibility and acessibility to target
10269 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10271 return can_access_type (source_class, target_class);
10275 * mono_type_is_valid_enum_basetype:
10276 * @type: The MonoType to check
10278 * Returns: TRUE if the type can be used as the basetype of an enum
10280 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10281 switch (type->type) {
10284 case MONO_TYPE_BOOLEAN:
10287 case MONO_TYPE_CHAR:
10301 * mono_class_is_valid_enum:
10302 * @klass: An enum class to be validated
10304 * This method verify the required properties an enum should have.
10306 * Returns: TRUE if the informed enum class is valid
10308 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10309 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10310 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10312 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10313 MonoClassField * field;
10314 gpointer iter = NULL;
10315 gboolean found_base_field = FALSE;
10317 g_assert (klass->enumtype);
10318 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10319 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10323 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10326 while ((field = mono_class_get_fields (klass, &iter))) {
10327 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10328 if (found_base_field)
10330 found_base_field = TRUE;
10331 if (!mono_type_is_valid_enum_basetype (field->type))
10336 if (!found_base_field)
10339 if (klass->method.count > 0)
10346 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10348 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10352 * mono_class_setup_interface_id:
10354 * Initializes MonoClass::interface_id if required.
10356 * LOCKING: Acquires the loader lock.
10359 mono_class_setup_interface_id (MonoClass *class)
10361 mono_loader_lock ();
10362 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10363 class->interface_id = mono_get_unique_iid (class);
10364 mono_loader_unlock ();
10368 * mono_class_alloc_ext:
10370 * Allocate klass->ext if not already done.
10373 mono_class_alloc_ext (MonoClass *klass)
10380 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10381 mono_image_lock (klass->image);
10382 mono_memory_barrier ();
10385 class_ext_size += sizeof (MonoClassExt);
10386 mono_image_unlock (klass->image);
10390 * mono_class_setup_interfaces:
10392 * Initialize class->interfaces/interfaces_count.
10393 * LOCKING: Acquires the loader lock.
10394 * This function can fail the type.
10397 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10399 int i, interface_count;
10400 MonoClass **interfaces;
10402 mono_error_init (error);
10404 if (klass->interfaces_inited)
10407 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10408 MonoType *args [1];
10410 /* generic IList, ICollection, IEnumerable */
10411 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10412 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10414 args [0] = &klass->element_class->byval_arg;
10415 interfaces [0] = mono_class_bind_generic_parameters (
10416 mono_defaults.generic_ilist_class, 1, args, FALSE);
10417 if (interface_count > 1)
10418 interfaces [1] = mono_class_bind_generic_parameters (
10419 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10420 } else if (klass->generic_class) {
10421 MonoClass *gklass = klass->generic_class->container_class;
10423 mono_class_setup_interfaces (gklass, error);
10424 if (!mono_error_ok (error)) {
10425 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10429 interface_count = gklass->interface_count;
10430 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10431 for (i = 0; i < interface_count; i++) {
10432 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10433 if (!mono_error_ok (error)) {
10434 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10439 interface_count = 0;
10443 mono_image_lock (klass->image);
10445 if (!klass->interfaces_inited) {
10446 klass->interface_count = interface_count;
10447 klass->interfaces = interfaces;
10449 mono_memory_barrier ();
10451 klass->interfaces_inited = TRUE;
10454 mono_image_unlock (klass->image);
10458 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10460 MonoClass *class = field->parent;
10461 MonoImage *image = class->image;
10462 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10463 int field_idx = field - class->fields;
10465 mono_error_init (error);
10468 MonoClassField *gfield = >d->fields [field_idx];
10469 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10470 if (!mono_error_ok (error)) {
10471 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10472 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10476 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10477 if (!mono_error_ok (error)) {
10478 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10479 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10484 guint32 cols [MONO_FIELD_SIZE];
10485 MonoGenericContainer *container = NULL;
10486 int idx = class->field.first + field_idx;
10488 /*FIXME, in theory we do not lazy load SRE fields*/
10489 g_assert (!image_is_dynamic (image));
10491 if (class->generic_container) {
10492 container = class->generic_container;
10494 container = gtd->generic_container;
10495 g_assert (container);
10498 /* class->field.first and idx points into the fieldptr table */
10499 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10501 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10502 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10503 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10507 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10509 mono_metadata_decode_value (sig, &sig);
10510 /* FIELD signature == 0x06 */
10511 g_assert (*sig == 0x06);
10512 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10514 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10519 mono_field_resolve_flags (MonoClassField *field)
10521 MonoClass *class = field->parent;
10522 MonoImage *image = class->image;
10523 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10524 int field_idx = field - class->fields;
10528 MonoClassField *gfield = >d->fields [field_idx];
10529 return mono_field_get_flags (gfield);
10531 int idx = class->field.first + field_idx;
10533 /*FIXME, in theory we do not lazy load SRE fields*/
10534 g_assert (!image_is_dynamic (image));
10536 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10541 * mono_class_setup_basic_field_info:
10542 * @class: The class to initialize
10544 * Initializes the class->fields array of fields.
10545 * Aquires the loader lock.
10548 mono_class_setup_basic_field_info_locking (MonoClass *class)
10550 mono_loader_lock ();
10551 mono_class_setup_basic_field_info (class);
10552 mono_loader_unlock ();
10556 * mono_class_get_fields_lazy:
10557 * @klass: the MonoClass to act on
10559 * This routine is an iterator routine for retrieving the fields in a class.
10560 * Only minimal information about fields are loaded. Accessors must be used
10561 * for all MonoClassField returned.
10563 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10564 * iterate over all of the elements. When no more values are
10565 * available, the return value is NULL.
10567 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10570 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10572 MonoClassField* field;
10576 mono_class_setup_basic_field_info_locking (klass);
10577 if (!klass->fields)
10579 /* start from the first */
10580 if (klass->field.count) {
10581 return *iter = &klass->fields [0];
10589 if (field < &klass->fields [klass->field.count]) {
10590 return *iter = field;
10596 mono_class_full_name (MonoClass *klass)
10598 return mono_type_full_name (&klass->byval_arg);