2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* Low level lock which protects data structures in this module */
56 static mono_mutex_t classes_mutex;
58 /* Function supplied by the runtime to find classes by name using information from the AOT file */
59 static MonoGetClassFromName get_class_from_name = NULL;
61 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
62 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
63 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
64 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
65 static int generic_array_methods (MonoClass *class);
66 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
68 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
69 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
70 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
71 static guint32 mono_field_resolve_flags (MonoClassField *field);
72 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
73 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
76 We use gclass recording to allow recursive system f types to be referenced by a parent.
78 Given the following type hierarchy:
80 class TextBox : TextBoxBase<TextBox> {}
81 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
82 class TextInput<T> : Input<T> where T: TextInput<T> {}
85 The runtime tries to load TextBoxBase<>.
86 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
87 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
88 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
90 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
91 at this point, iow, both are registered in the type map and both and a NULL parent. This means
92 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
94 To fix that what we do is to record all generic instantes created while resolving the parent of
95 any generic type definition and, after resolved, correct the parent field if needed.
98 static int record_gclass_instantiation;
99 static GSList *gclass_recorded_list;
100 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
105 mono_locks_acquire (&classes_mutex, ClassesLock);
109 classes_unlock (void)
111 mono_locks_release (&classes_mutex, ClassesLock);
115 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
118 enable_gclass_recording (void)
120 ++record_gclass_instantiation;
124 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
127 disable_gclass_recording (gclass_record_func func, void *user_data)
129 GSList **head = &gclass_recorded_list;
131 g_assert (record_gclass_instantiation > 0);
132 --record_gclass_instantiation;
135 GSList *node = *head;
136 if (func ((MonoClass*)node->data, user_data)) {
138 g_slist_free_1 (node);
144 /* We automatically discard all recorded gclasses when disabled. */
145 if (!record_gclass_instantiation && gclass_recorded_list) {
146 g_slist_free (gclass_recorded_list);
147 gclass_recorded_list = NULL;
152 * mono_class_from_typeref:
153 * @image: a MonoImage
154 * @type_token: a TypeRef token
156 * Creates the MonoClass* structure representing the type defined by
157 * the typeref token valid inside @image.
158 * Returns: the MonoClass* representing the typeref token, NULL ifcould
162 mono_class_from_typeref (MonoImage *image, guint32 type_token)
165 MonoClass *class = mono_class_from_typeref_checked (image, type_token, &error);
166 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
171 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
173 guint32 cols [MONO_TYPEREF_SIZE];
174 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
176 const char *name, *nspace;
177 MonoClass *res = NULL;
180 mono_error_init (error);
182 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
185 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
187 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
188 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
190 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
191 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
192 case MONO_RESOLUTION_SCOPE_MODULE:
194 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
195 This is not the observed behavior of existing implementations.
196 The defacto behavior is that it's just a typedef in disguise.
198 /* a typedef in disguise */
199 res = mono_class_from_name (image, nspace, name); /*FIXME proper error handling*/
202 case MONO_RESOLUTION_SCOPE_MODULEREF:
203 module = mono_image_load_module (image, idx);
205 res = mono_class_from_name (module, nspace, name); /*FIXME proper error handling*/
208 case MONO_RESOLUTION_SCOPE_TYPEREF: {
209 MonoClass *enclosing;
212 if (idx == mono_metadata_token_index (type_token)) {
213 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
217 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
218 if (!mono_error_ok (error))
221 if (enclosing->nested_classes_inited && enclosing->ext) {
222 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
223 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
225 if (strcmp (res->name, name) == 0)
229 /* Don't call mono_class_init as we might've been called by it recursively */
230 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
232 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
233 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
234 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
236 if (strcmp (nname, name) == 0)
237 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
239 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
242 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
245 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
249 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
250 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
254 if (!image->references || !image->references [idx - 1])
255 mono_assembly_load_reference (image, idx - 1);
256 g_assert (image->references [idx - 1]);
258 /* If the assembly did not load, register this as a type load exception */
259 if (image->references [idx - 1] == REFERENCE_MISSING){
260 MonoAssemblyName aname;
263 mono_assembly_get_assemblyref (image, idx - 1, &aname);
264 human_name = mono_stringify_assembly_name (&aname);
265 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
269 res = mono_class_from_name (image->references [idx - 1]->image, nspace, name);
272 /* Generic case, should be avoided for when a better error is possible. */
273 if (!res && mono_error_ok (error)) {
274 char *name = mono_class_name_from_token (image, type_token);
275 char *assembly = mono_assembly_name_from_token (image, type_token);
276 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
283 mono_image_memdup (MonoImage *image, void *data, guint size)
285 void *res = mono_image_alloc (image, size);
286 memcpy (res, data, size);
290 /* Copy everything mono_metadata_free_array free. */
292 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
295 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
297 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
299 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
301 a = g_memdup (a, sizeof (MonoArrayType));
303 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
305 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
310 /* Copy everything mono_metadata_free_method_signature free. */
312 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
316 sig = mono_metadata_signature_dup_full (image, sig);
318 sig->ret = mono_metadata_type_dup (image, sig->ret);
319 for (i = 0; i < sig->param_count; ++i)
320 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
326 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
328 MonoAssembly *ta = klass->image->assembly;
331 name = mono_stringify_assembly_name (&ta->aname);
332 g_string_append_printf (str, ", %s", name);
337 mono_type_name_check_byref (MonoType *type, GString *str)
340 g_string_append_c (str, '&');
344 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
345 MonoTypeNameFormat format)
349 switch (type->type) {
350 case MONO_TYPE_ARRAY: {
351 int i, rank = type->data.array->rank;
352 MonoTypeNameFormat nested_format;
354 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
355 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
357 mono_type_get_name_recurse (
358 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
359 g_string_append_c (str, '[');
361 g_string_append_c (str, '*');
362 for (i = 1; i < rank; i++)
363 g_string_append_c (str, ',');
364 g_string_append_c (str, ']');
366 mono_type_name_check_byref (type, str);
368 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
369 _mono_type_get_assembly_name (type->data.array->eklass, str);
372 case MONO_TYPE_SZARRAY: {
373 MonoTypeNameFormat nested_format;
375 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
376 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
378 mono_type_get_name_recurse (
379 &type->data.klass->byval_arg, str, FALSE, nested_format);
380 g_string_append (str, "[]");
382 mono_type_name_check_byref (type, str);
384 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
385 _mono_type_get_assembly_name (type->data.klass, str);
388 case MONO_TYPE_PTR: {
389 MonoTypeNameFormat nested_format;
391 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
392 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
394 mono_type_get_name_recurse (
395 type->data.type, str, FALSE, nested_format);
396 g_string_append_c (str, '*');
398 mono_type_name_check_byref (type, str);
400 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
401 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
406 if (!mono_generic_param_info (type->data.generic_param))
407 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
409 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
411 mono_type_name_check_byref (type, str);
415 klass = mono_class_from_mono_type (type);
416 if (klass->nested_in) {
417 mono_type_get_name_recurse (
418 &klass->nested_in->byval_arg, str, TRUE, format);
419 if (format == MONO_TYPE_NAME_FORMAT_IL)
420 g_string_append_c (str, '.');
422 g_string_append_c (str, '+');
423 } else if (*klass->name_space) {
424 g_string_append (str, klass->name_space);
425 g_string_append_c (str, '.');
427 if (format == MONO_TYPE_NAME_FORMAT_IL) {
428 char *s = strchr (klass->name, '`');
429 int len = s ? s - klass->name : strlen (klass->name);
431 g_string_append_len (str, klass->name, len);
433 g_string_append (str, klass->name);
436 if (klass->generic_class) {
437 MonoGenericClass *gclass = klass->generic_class;
438 MonoGenericInst *inst = gclass->context.class_inst;
439 MonoTypeNameFormat nested_format;
442 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
443 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
445 if (format == MONO_TYPE_NAME_FORMAT_IL)
446 g_string_append_c (str, '<');
448 g_string_append_c (str, '[');
449 for (i = 0; i < inst->type_argc; i++) {
450 MonoType *t = inst->type_argv [i];
453 g_string_append_c (str, ',');
454 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
455 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
456 g_string_append_c (str, '[');
457 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
458 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
459 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
460 g_string_append_c (str, ']');
462 if (format == MONO_TYPE_NAME_FORMAT_IL)
463 g_string_append_c (str, '>');
465 g_string_append_c (str, ']');
466 } else if (klass->generic_container &&
467 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
468 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
471 if (format == MONO_TYPE_NAME_FORMAT_IL)
472 g_string_append_c (str, '<');
474 g_string_append_c (str, '[');
475 for (i = 0; i < klass->generic_container->type_argc; i++) {
477 g_string_append_c (str, ',');
478 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
480 if (format == MONO_TYPE_NAME_FORMAT_IL)
481 g_string_append_c (str, '>');
483 g_string_append_c (str, ']');
486 mono_type_name_check_byref (type, str);
488 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
489 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
490 _mono_type_get_assembly_name (klass, str);
496 * mono_type_get_name_full:
498 * @format: the format for the return string.
501 * Returns: the string representation in a number of formats:
503 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
504 * returned in the formatrequired by System.Reflection, this is the
505 * inverse of mono_reflection_parse_type ().
507 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
508 * be used by the IL assembler.
510 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
512 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
515 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
519 result = g_string_new ("");
521 mono_type_get_name_recurse (type, result, FALSE, format);
523 return g_string_free (result, FALSE);
527 * mono_type_get_full_name:
530 * Returns: the string representation for type as required by System.Reflection.
531 * The inverse of mono_reflection_parse_type ().
534 mono_type_get_full_name (MonoClass *class)
536 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
540 * mono_type_get_name:
543 * Returns: the string representation for type as it would be represented in IL code.
546 mono_type_get_name (MonoType *type)
548 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
552 * mono_type_get_underlying_type:
555 * Returns: the MonoType for the underlying integer type if @type
556 * is an enum and byref is false, otherwise the type itself.
559 mono_type_get_underlying_type (MonoType *type)
561 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
562 return mono_class_enum_basetype (type->data.klass);
563 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
564 return mono_class_enum_basetype (type->data.generic_class->container_class);
569 * mono_class_is_open_constructed_type:
572 * Returns TRUE if type represents a generics open constructed type.
573 * IOW, not all type parameters required for the instantiation have
574 * been provided or it's a generic type definition.
576 * An open constructed type means it's a non realizable type. Not to
577 * be mixed up with an abstract type - we can't cast or dispatch to
578 * an open type, for example.
581 mono_class_is_open_constructed_type (MonoType *t)
587 case MONO_TYPE_SZARRAY:
588 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
589 case MONO_TYPE_ARRAY:
590 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
592 return mono_class_is_open_constructed_type (t->data.type);
593 case MONO_TYPE_GENERICINST:
594 return t->data.generic_class->context.class_inst->is_open;
595 case MONO_TYPE_CLASS:
596 case MONO_TYPE_VALUETYPE:
597 return t->data.klass->generic_container != NULL;
604 This is a simple function to catch the most common bad instances of generic types.
605 Specially those that might lead to further failures in the runtime.
608 is_valid_generic_argument (MonoType *type)
610 switch (type->type) {
612 //case MONO_TYPE_TYPEDBYREF:
619 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
621 mono_error_init (error);
623 switch (type->type) {
624 case MONO_TYPE_MVAR: {
626 int num = mono_type_get_generic_param_num (type);
627 MonoGenericInst *inst = context->method_inst;
628 if (!inst || !inst->type_argv)
630 if (num >= inst->type_argc) {
631 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
632 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
633 num, info ? info->name : "", inst->type_argc);
637 if (!is_valid_generic_argument (inst->type_argv [num])) {
638 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
639 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
640 num, info ? info->name : "", inst->type_argv [num]->type);
644 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
645 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
646 * ->byref and ->attrs from @type are propagated to the returned type.
648 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
649 nt->byref = type->byref;
650 nt->attrs = type->attrs;
653 case MONO_TYPE_VAR: {
655 int num = mono_type_get_generic_param_num (type);
656 MonoGenericInst *inst = context->class_inst;
659 if (num >= inst->type_argc) {
660 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
661 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
662 num, info ? info->name : "", inst->type_argc);
665 if (!is_valid_generic_argument (inst->type_argv [num])) {
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 with type 0x%x",
668 num, info ? info->name : "", inst->type_argv [num]->type);
671 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
672 nt->byref = type->byref;
673 nt->attrs = type->attrs;
676 case MONO_TYPE_SZARRAY: {
677 MonoClass *eclass = type->data.klass;
678 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
679 if (!inflated || !mono_error_ok (error))
681 nt = mono_metadata_type_dup (image, type);
682 nt->data.klass = mono_class_from_mono_type (inflated);
683 mono_metadata_free_type (inflated);
686 case MONO_TYPE_ARRAY: {
687 MonoClass *eclass = type->data.array->eklass;
688 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
689 if (!inflated || !mono_error_ok (error))
691 nt = mono_metadata_type_dup (image, type);
692 nt->data.array->eklass = mono_class_from_mono_type (inflated);
693 mono_metadata_free_type (inflated);
696 case MONO_TYPE_GENERICINST: {
697 MonoGenericClass *gclass = type->data.generic_class;
698 MonoGenericInst *inst;
700 if (!gclass->context.class_inst->is_open)
703 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
704 if (!mono_error_ok (error))
706 if (inst != gclass->context.class_inst)
707 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
709 if (gclass == type->data.generic_class)
712 nt = mono_metadata_type_dup (image, type);
713 nt->data.generic_class = gclass;
716 case MONO_TYPE_CLASS:
717 case MONO_TYPE_VALUETYPE: {
718 MonoClass *klass = type->data.klass;
719 MonoGenericContainer *container = klass->generic_container;
720 MonoGenericInst *inst;
721 MonoGenericClass *gclass = NULL;
727 /* We can't use context->class_inst directly, since it can have more elements */
728 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
729 if (!mono_error_ok (error))
731 if (inst == container->context.class_inst)
734 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
736 nt = mono_metadata_type_dup (image, type);
737 nt->type = MONO_TYPE_GENERICINST;
738 nt->data.generic_class = gclass;
748 mono_generic_class_get_context (MonoGenericClass *gclass)
750 return &gclass->context;
754 mono_class_get_context (MonoClass *class)
756 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
760 * mono_class_get_generic_container:
762 * Return the generic container of KLASS which should be a generic type definition.
764 MonoGenericContainer*
765 mono_class_get_generic_container (MonoClass *klass)
767 g_assert (klass->is_generic);
769 return klass->generic_container;
773 * mono_class_get_generic_class:
775 * Return the MonoGenericClass of KLASS, which should be a generic instance.
778 mono_class_get_generic_class (MonoClass *klass)
780 g_assert (klass->is_inflated);
782 return klass->generic_class;
786 * mono_class_inflate_generic_type_with_mempool:
787 * @mempool: a mempool
789 * @context: a generics context
790 * @error: error context
792 * The same as mono_class_inflate_generic_type, but allocates the MonoType
793 * from mempool if it is non-NULL. If it is NULL, the MonoType is
794 * allocated on the heap and is owned by the caller.
795 * The returned type can potentially be the same as TYPE, so it should not be
796 * modified by the caller, and it should be freed using mono_metadata_free_type ().
799 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
801 MonoType *inflated = NULL;
802 mono_error_init (error);
805 inflated = inflate_generic_type (image, type, context, error);
806 if (!mono_error_ok (error))
810 MonoType *shared = mono_metadata_get_shared_type (type);
815 return mono_metadata_type_dup (image, type);
819 mono_stats.inflated_type_count++;
824 * mono_class_inflate_generic_type:
826 * @context: a generics context
828 * If @type is a generic type and @context is not NULL, instantiate it using the
829 * generics context @context.
831 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
832 * on the heap and is owned by the caller. Returns NULL on error.
834 * @deprecated Please use mono_class_inflate_generic_type_checked instead
837 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
841 result = mono_class_inflate_generic_type_checked (type, context, &error);
843 if (!mono_error_ok (&error)) {
844 mono_error_cleanup (&error);
851 * mono_class_inflate_generic_type:
853 * @context: a generics context
854 * @error: error context to use
856 * If @type is a generic type and @context is not NULL, instantiate it using the
857 * generics context @context.
859 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
860 * on the heap and is owned by the caller.
863 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
865 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
869 * mono_class_inflate_generic_type_no_copy:
871 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
875 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
877 MonoType *inflated = NULL;
879 mono_error_init (error);
881 inflated = inflate_generic_type (image, type, context, error);
882 if (!mono_error_ok (error))
889 mono_stats.inflated_type_count++;
894 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
899 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
900 if (!mono_error_ok (error))
903 res = mono_class_from_mono_type (inflated);
904 mono_metadata_free_type (inflated);
909 * mono_class_inflate_generic_class:
911 * Inflate the class GKLASS with CONTEXT.
914 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
919 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
920 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
927 static MonoGenericContext
928 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
930 MonoGenericInst *class_inst = NULL;
931 MonoGenericInst *method_inst = NULL;
932 MonoGenericContext res = { NULL, NULL };
934 mono_error_init (error);
936 if (context->class_inst) {
937 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
938 if (!mono_error_ok (error))
942 if (context->method_inst) {
943 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
944 if (!mono_error_ok (error))
948 res.class_inst = class_inst;
949 res.method_inst = method_inst;
955 * mono_class_inflate_generic_method:
956 * @method: a generic method
957 * @context: a generics context
959 * Instantiate the generic method @method using the generics context @context.
961 * Returns: the new instantiated method
964 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
966 return mono_class_inflate_generic_method_full (method, NULL, context);
970 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
972 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
976 * mono_class_inflate_generic_method_full:
978 * Instantiate method @method with the generic context @context.
979 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
980 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
983 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
986 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
987 if (!mono_error_ok (&error))
988 /*FIXME do proper error handling - on this case, kill this function. */
989 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
995 * mono_class_inflate_generic_method_full_checked:
996 * Same as mono_class_inflate_generic_method_full but return failure using @error.
999 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1002 MonoMethodInflated *iresult, *cached;
1003 MonoMethodSignature *sig;
1004 MonoGenericContext tmp_context;
1005 gboolean is_mb_open = FALSE;
1007 mono_error_init (error);
1009 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1010 while (method->is_inflated) {
1011 MonoGenericContext *method_context = mono_method_get_context (method);
1012 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1014 tmp_context = inflate_generic_context (method_context, context, error);
1015 if (!mono_error_ok (error))
1017 context = &tmp_context;
1019 if (mono_metadata_generic_context_equal (method_context, context))
1022 method = imethod->declaring;
1026 * A method only needs to be inflated if the context has argument for which it is
1029 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1030 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1033 if (!((method->is_generic && context->method_inst) ||
1034 (method->klass->generic_container && context->class_inst)))
1038 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1039 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1040 * This is opposite to the way non-SRE MethodInfos behave.
1042 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1044 * void Example<T> () {
1048 * In Example, the method token must be encoded as: "void Example<!!0>()"
1050 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1051 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1053 * On the other hand, inflating a non-SRE generic method with its own arguments should
1054 * return itself. For example:
1056 * MethodInfo m = ... //m is a generic method definition
1057 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1060 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1061 * what happens with regular methods.
1063 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1064 * everything should behave like a regular type or method.
1067 is_mb_open = method->is_generic &&
1068 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1069 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1071 iresult = g_new0 (MonoMethodInflated, 1);
1072 iresult->context = *context;
1073 iresult->declaring = method;
1074 iresult->method.method.is_mb_open = is_mb_open;
1076 if (!context->method_inst && method->is_generic)
1077 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1079 if (!context->class_inst) {
1080 g_assert (!iresult->declaring->klass->generic_class);
1081 if (iresult->declaring->klass->generic_container)
1082 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1083 else if (iresult->declaring->klass->generic_class)
1084 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1087 cached = mono_method_inflated_lookup (iresult, FALSE);
1090 return (MonoMethod*)cached;
1093 mono_stats.inflated_method_count++;
1095 inflated_methods_size += sizeof (MonoMethodInflated);
1097 sig = mono_method_signature (method);
1099 char *name = mono_type_get_full_name (method->klass);
1100 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1106 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1108 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1111 result = (MonoMethod *) iresult;
1112 result->is_inflated = TRUE;
1113 result->is_generic = FALSE;
1114 result->sre_method = FALSE;
1115 result->signature = NULL;
1116 result->is_mb_open = is_mb_open;
1118 if (!context->method_inst) {
1119 /* Set the generic_container of the result to the generic_container of method */
1120 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1122 if (generic_container) {
1123 result->is_generic = 1;
1124 mono_method_set_generic_container (result, generic_container);
1128 if (!klass_hint || !klass_hint->generic_class ||
1129 klass_hint->generic_class->container_class != method->klass ||
1130 klass_hint->generic_class->context.class_inst != context->class_inst)
1133 if (method->klass->generic_container)
1134 result->klass = klass_hint;
1136 if (!result->klass) {
1137 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1138 if (!mono_error_ok (error))
1141 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1143 mono_metadata_free_type (inflated);
1147 * FIXME: This should hold, but it doesn't:
1149 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1150 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1151 * g_assert (result->is_generic);
1154 * Fixing this here causes other things to break, hence a very
1155 * ugly hack in mini-trampolines.c - see
1156 * is_generic_method_definition().
1159 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1167 * mono_get_inflated_method:
1169 * Obsolete. We keep it around since it's mentioned in the public API.
1172 mono_get_inflated_method (MonoMethod *method)
1178 * mono_method_get_context_general:
1180 * @uninflated: handle uninflated methods?
1182 * Returns the generic context of a method or NULL if it doesn't have
1183 * one. For an inflated method that's the context stored in the
1184 * method. Otherwise it's in the method's generic container or in the
1185 * generic container of the method's class.
1188 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1190 if (method->is_inflated) {
1191 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1192 return &imethod->context;
1196 if (method->is_generic)
1197 return &(mono_method_get_generic_container (method)->context);
1198 if (method->klass->generic_container)
1199 return &method->klass->generic_container->context;
1204 * mono_method_get_context:
1207 * Returns the generic context for method if it's inflated, otherwise
1211 mono_method_get_context (MonoMethod *method)
1213 return mono_method_get_context_general (method, FALSE);
1217 * mono_method_get_generic_container:
1219 * Returns the generic container of METHOD, which should be a generic method definition.
1220 * Returns NULL if METHOD is not a generic method definition.
1221 * LOCKING: Acquires the loader lock.
1223 MonoGenericContainer*
1224 mono_method_get_generic_container (MonoMethod *method)
1226 MonoGenericContainer *container;
1228 if (!method->is_generic)
1231 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1232 g_assert (container);
1238 * mono_method_set_generic_container:
1240 * Sets the generic container of METHOD to CONTAINER.
1241 * LOCKING: Acquires the image lock.
1244 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1246 g_assert (method->is_generic);
1248 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1252 * mono_class_find_enum_basetype:
1253 * @class: The enum class
1255 * Determine the basetype of an enum by iterating through its fields. We do this
1256 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1259 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1261 MonoGenericContainer *container = NULL;
1262 MonoImage *m = class->image;
1263 const int top = class->field.count;
1266 g_assert (class->enumtype);
1268 mono_error_init (error);
1270 if (class->generic_container)
1271 container = class->generic_container;
1272 else if (class->generic_class) {
1273 MonoClass *gklass = class->generic_class->container_class;
1275 container = gklass->generic_container;
1276 g_assert (container);
1280 * Fetch all the field information.
1282 for (i = 0; i < top; i++){
1284 guint32 cols [MONO_FIELD_SIZE];
1285 int idx = class->field.first + i;
1288 /* class->field.first and idx points into the fieldptr table */
1289 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1291 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1294 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1295 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1299 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1300 mono_metadata_decode_value (sig, &sig);
1301 /* FIELD signature == 0x06 */
1303 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1307 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1309 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1310 mono_error_set_from_loader_error (error);
1312 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1315 if (class->generic_class) {
1316 //FIXME do we leak here?
1317 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1318 if (!mono_error_ok (error))
1320 ftype->attrs = cols [MONO_FIELD_FLAGS];
1325 mono_error_set_type_load_class (error, class, "Could not find base type");
1328 g_assert (!mono_loader_get_last_error ());
1333 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1336 mono_type_has_exceptions (MonoType *type)
1338 switch (type->type) {
1339 case MONO_TYPE_CLASS:
1340 case MONO_TYPE_VALUETYPE:
1341 case MONO_TYPE_SZARRAY:
1342 return type->data.klass->exception_type;
1343 case MONO_TYPE_ARRAY:
1344 return type->data.array->eklass->exception_type;
1345 case MONO_TYPE_GENERICINST:
1346 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1354 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1358 mono_class_alloc (MonoClass *class, int size)
1360 if (class->generic_class)
1361 return mono_image_set_alloc (class->generic_class->owner, size);
1363 return mono_image_alloc (class->image, size);
1367 mono_class_alloc0 (MonoClass *class, int size)
1371 res = mono_class_alloc (class, size);
1372 memset (res, 0, size);
1376 #define mono_class_new0(class,struct_type, n_structs) \
1377 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1380 * mono_class_setup_basic_field_info:
1381 * @class: The class to initialize
1383 * Initializes the class->fields.
1384 * LOCKING: Assumes the loader lock is held.
1387 mono_class_setup_basic_field_info (MonoClass *class)
1389 MonoClassField *field;
1397 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1398 image = class->image;
1399 top = class->field.count;
1401 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1403 * This happens when a generic instance of an unfinished generic typebuilder
1404 * is used as an element type for creating an array type. We can't initialize
1405 * the fields of this class using the fields of gklass, since gklass is not
1406 * finished yet, fields could be added to it later.
1412 mono_class_setup_basic_field_info (gtd);
1414 top = gtd->field.count;
1415 class->field.first = gtd->field.first;
1416 class->field.count = gtd->field.count;
1419 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1422 * Fetch all the field information.
1424 for (i = 0; i < top; i++){
1425 field = &class->fields [i];
1426 field->parent = class;
1429 field->name = mono_field_get_name (>d->fields [i]);
1431 int idx = class->field.first + i;
1432 /* class->field.first and idx points into the fieldptr table */
1433 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1434 /* The name is needed for fieldrefs */
1435 field->name = mono_metadata_string_heap (image, name_idx);
1441 * mono_class_setup_fields:
1442 * @class: The class to initialize
1444 * Initializes the class->fields.
1445 * LOCKING: Assumes the loader lock is held.
1448 mono_class_setup_fields (MonoClass *class)
1451 MonoImage *m = class->image;
1453 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1454 int i, blittable = TRUE;
1455 guint32 real_size = 0;
1456 guint32 packing_size = 0;
1457 gboolean explicit_size;
1458 MonoClassField *field;
1459 MonoGenericContainer *container = NULL;
1460 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1463 * FIXME: We have a race condition here. It's possible that this function returns
1464 * to its caller with `instance_size` set to `0` instead of the actual size. This
1465 * is not a problem when the function is called recursively on the same class,
1466 * because the size will be initialized by the outer invocation. What follows is a
1467 * description of how it can occur in other cases, too. There it is a problem,
1468 * because it can lead to the GC being asked to allocate an object of size `0`,
1469 * which SGen chokes on. The race condition is triggered infrequently by
1470 * `tests/sgen-suspend.cs`.
1472 * This function is called for a class whenever one of its subclasses is inited.
1473 * For example, it's called for every subclass of Object. What it does is this:
1475 * if (class->setup_fields_called)
1478 * class->instance_size = 0;
1480 * class->setup_fields_called = 1;
1481 * ... critical point
1482 * class->instance_size = actual_instance_size;
1484 * The last two steps are sometimes reversed, but that only changes the way in which
1485 * the race condition works.
1487 * Assume thread A goes through this function and makes it to the critical point.
1488 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1489 * immediately, but `instance_size` is incorrect.
1491 * The other case looks like this:
1493 * if (class->setup_fields_called)
1495 * ... critical point X
1496 * class->instance_size = 0;
1497 * ... critical point Y
1498 * class->instance_size = actual_instance_size;
1500 * class->setup_fields_called = 1;
1502 * Assume thread A goes through the function and makes it to critical point X. Now
1503 * thread B runs through the whole of the function, returning, assuming
1504 * `instance_size` is set. At that point thread A gets to run and makes it to
1505 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1508 if (class->setup_fields_called)
1511 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1513 * This happens when a generic instance of an unfinished generic typebuilder
1514 * is used as an element type for creating an array type. We can't initialize
1515 * the fields of this class using the fields of gklass, since gklass is not
1516 * finished yet, fields could be added to it later.
1521 mono_class_setup_basic_field_info (class);
1522 top = class->field.count;
1525 mono_class_setup_fields (gtd);
1526 if (gtd->exception_type) {
1527 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1532 class->instance_size = 0;
1534 class->sizes.class_size = 0;
1536 if (class->parent) {
1537 /* For generic instances, class->parent might not have been initialized */
1538 mono_class_init (class->parent);
1539 if (!class->parent->size_inited) {
1540 mono_class_setup_fields (class->parent);
1541 if (class->parent->exception_type) {
1542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1546 class->instance_size += class->parent->instance_size;
1547 class->min_align = class->parent->min_align;
1548 /* we use |= since it may have been set already */
1549 class->has_references |= class->parent->has_references;
1550 blittable = class->parent->blittable;
1552 class->instance_size = sizeof (MonoObject);
1553 class->min_align = 1;
1556 /* We can't really enable 16 bytes alignment until the GC supports it.
1557 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1558 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1559 Bug #506144 is an example of this issue.
1561 if (class->simd_type)
1562 class->min_align = 16;
1564 /* Get the real size */
1565 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1567 if (explicit_size) {
1568 if ((packing_size & 0xffffff00) != 0) {
1569 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", class->name, packing_size);
1570 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1573 class->packing_size = packing_size;
1574 real_size += class->instance_size;
1578 if (explicit_size && real_size) {
1579 class->instance_size = MAX (real_size, class->instance_size);
1581 class->blittable = blittable;
1582 mono_memory_barrier ();
1583 class->size_inited = 1;
1584 class->fields_inited = 1;
1585 class->setup_fields_called = 1;
1589 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1592 /* Prevent infinite loops if the class references itself */
1593 class->setup_fields_called = 1;
1595 if (class->generic_container) {
1596 container = class->generic_container;
1598 container = gtd->generic_container;
1599 g_assert (container);
1603 * Fetch all the field information.
1605 for (i = 0; i < top; i++){
1606 int idx = class->field.first + i;
1607 field = &class->fields [i];
1609 field->parent = class;
1612 mono_field_resolve_type (field, &error);
1613 if (!mono_error_ok (&error)) {
1614 /*mono_field_resolve_type already failed class*/
1615 mono_error_cleanup (&error);
1619 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1620 g_assert (field->type);
1623 if (mono_field_is_deleted (field))
1626 MonoClassField *gfield = >d->fields [i];
1627 field->offset = gfield->offset;
1629 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1631 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1632 field->offset = offset;
1634 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1635 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1638 if (field->offset < -1) { /*-1 is used to encode special static fields */
1639 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1642 if (class->generic_container) {
1643 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1649 /* Only do these checks if we still think this type is blittable */
1650 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1651 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1654 MonoClass *field_class = mono_class_from_mono_type (field->type);
1656 mono_class_setup_fields (field_class);
1657 if (field_class->exception_type) {
1658 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1662 if (!field_class || !field_class->blittable)
1667 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1668 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1669 blittable = class->element_class->blittable;
1672 if (mono_type_has_exceptions (field->type)) {
1673 char *class_name = mono_type_get_full_name (class);
1674 char *type_name = mono_type_full_name (field->type);
1676 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1677 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1678 g_free (class_name);
1682 /* The def_value of fields is compute lazily during vtable creation */
1685 if (class == mono_defaults.string_class)
1688 class->blittable = blittable;
1690 if (class->enumtype && !mono_class_enum_basetype (class)) {
1691 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1694 if (explicit_size && real_size) {
1695 class->instance_size = MAX (real_size, class->instance_size);
1698 if (class->exception_type)
1700 mono_class_layout_fields (class);
1702 /*valuetypes can't be neither bigger than 1Mb or empty. */
1703 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1704 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1706 mono_memory_barrier ();
1707 class->fields_inited = 1;
1711 * mono_class_setup_fields_locking:
1712 * @class: The class to initialize
1714 * Initializes the class->fields array of fields.
1715 * Aquires the loader lock.
1718 mono_class_setup_fields_locking (MonoClass *class)
1720 /* This can be checked without locks */
1721 if (class->fields_inited)
1723 mono_loader_lock ();
1724 mono_class_setup_fields (class);
1725 mono_loader_unlock ();
1729 * mono_class_has_references:
1731 * Returns whenever @klass->has_references is set, initializing it if needed.
1732 * Aquires the loader lock.
1735 mono_class_has_references (MonoClass *klass)
1737 if (klass->init_pending) {
1738 /* Be conservative */
1741 mono_class_init (klass);
1743 return klass->has_references;
1748 * mono_type_get_basic_type_from_generic:
1751 * Returns a closed type corresponding to the possibly open type
1755 mono_type_get_basic_type_from_generic (MonoType *type)
1757 /* When we do generic sharing we let type variables stand for reference types. */
1758 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1759 return &mono_defaults.object_class->byval_arg;
1764 * mono_class_layout_fields:
1767 * Compute the placement of fields inside an object or struct, according to
1768 * the layout rules and set the following fields in @class:
1769 * - has_references (if the class contains instance references firled or structs that contain references)
1770 * - has_static_refs (same, but for static fields)
1771 * - instance_size (size of the object in memory)
1772 * - class_size (size needed for the static fields)
1773 * - size_inited (flag set when the instance_size is set)
1775 * LOCKING: this is supposed to be called with the loader lock held.
1778 mono_class_layout_fields (MonoClass *class)
1781 const int top = class->field.count;
1782 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1783 guint32 pass, passes, real_size;
1784 gboolean gc_aware_layout = FALSE;
1785 gboolean has_static_fields = FALSE;
1786 MonoClassField *field;
1789 * When we do generic sharing we need to have layout
1790 * information for open generic classes (either with a generic
1791 * context containing type variables or with a generic
1792 * container), so we don't return in that case anymore.
1796 * Enable GC aware auto layout: in this mode, reference
1797 * fields are grouped together inside objects, increasing collector
1799 * Requires that all classes whose layout is known to native code be annotated
1800 * with [StructLayout (LayoutKind.Sequential)]
1801 * Value types have gc_aware_layout disabled by default, as per
1802 * what the default is for other runtimes.
1804 /* corlib is missing [StructLayout] directives in many places */
1805 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1806 if (!class->valuetype)
1807 gc_aware_layout = TRUE;
1810 /* Compute klass->has_references */
1812 * Process non-static fields first, since static fields might recursively
1813 * refer to the class itself.
1815 for (i = 0; i < top; i++) {
1818 field = &class->fields [i];
1820 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1821 ftype = mono_type_get_underlying_type (field->type);
1822 ftype = mono_type_get_basic_type_from_generic (ftype);
1823 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1824 class->has_references = TRUE;
1828 for (i = 0; i < top; i++) {
1831 field = &class->fields [i];
1833 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1834 ftype = mono_type_get_underlying_type (field->type);
1835 ftype = mono_type_get_basic_type_from_generic (ftype);
1836 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1837 class->has_static_refs = TRUE;
1841 for (i = 0; i < top; i++) {
1844 field = &class->fields [i];
1846 ftype = mono_type_get_underlying_type (field->type);
1847 ftype = mono_type_get_basic_type_from_generic (ftype);
1848 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1849 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1850 class->has_static_refs = TRUE;
1852 class->has_references = TRUE;
1857 * Compute field layout and total size (not considering static fields)
1861 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1862 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1864 if (gc_aware_layout)
1869 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1872 if (class->parent) {
1873 mono_class_setup_fields (class->parent);
1874 if (class->parent->exception_type) {
1875 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1878 real_size = class->parent->instance_size;
1880 real_size = sizeof (MonoObject);
1883 for (pass = 0; pass < passes; ++pass) {
1884 for (i = 0; i < top; i++){
1889 field = &class->fields [i];
1891 if (mono_field_is_deleted (field))
1893 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1896 ftype = mono_type_get_underlying_type (field->type);
1897 ftype = mono_type_get_basic_type_from_generic (ftype);
1898 if (gc_aware_layout) {
1899 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1908 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1909 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1910 /* This field is a hack inserted by MCS to empty structures */
1914 size = mono_type_size (field->type, &align);
1916 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1917 align = class->packing_size ? MIN (class->packing_size, align): align;
1918 /* if the field has managed references, we need to force-align it
1921 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1922 align = MAX (align, sizeof (gpointer));
1924 class->min_align = MAX (align, class->min_align);
1925 field->offset = real_size;
1927 field->offset += align - 1;
1928 field->offset &= ~(align - 1);
1930 /*TypeBuilders produce all sort of weird things*/
1931 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1932 real_size = field->offset + size;
1935 class->instance_size = MAX (real_size, class->instance_size);
1937 if (class->instance_size & (class->min_align - 1)) {
1938 class->instance_size += class->min_align - 1;
1939 class->instance_size &= ~(class->min_align - 1);
1943 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1947 for (i = 0; i < top; i++) {
1952 field = &class->fields [i];
1955 * There must be info about all the fields in a type if it
1956 * uses explicit layout.
1958 if (mono_field_is_deleted (field))
1960 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1963 size = mono_type_size (field->type, &align);
1964 align = class->packing_size ? MIN (class->packing_size, align): align;
1965 class->min_align = MAX (align, class->min_align);
1968 * When we get here, field->offset is already set by the
1969 * loader (for either runtime fields or fields loaded from metadata).
1970 * The offset is from the start of the object: this works for both
1971 * classes and valuetypes.
1973 field->offset += sizeof (MonoObject);
1974 ftype = mono_type_get_underlying_type (field->type);
1975 ftype = mono_type_get_basic_type_from_generic (ftype);
1976 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1977 if (field->offset % sizeof (gpointer)) {
1978 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1985 real_size = MAX (real_size, size + field->offset);
1988 if (class->has_references) {
1989 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1991 /* Check for overlapping reference and non-reference fields */
1992 for (i = 0; i < top; i++) {
1995 field = &class->fields [i];
1997 if (mono_field_is_deleted (field))
1999 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2001 ftype = mono_type_get_underlying_type (field->type);
2002 if (MONO_TYPE_IS_REFERENCE (ftype))
2003 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2005 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)
2013 // FIXME: Too much code does this
2015 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2016 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);
2017 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2021 g_free (ref_bitmap);
2024 class->instance_size = MAX (real_size, class->instance_size);
2025 if (class->instance_size & (class->min_align - 1)) {
2026 class->instance_size += class->min_align - 1;
2027 class->instance_size &= ~(class->min_align - 1);
2033 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2035 * For small structs, set min_align to at least the struct size to improve
2036 * performance, and since the JIT memset/memcpy code assumes this and generates
2037 * unaligned accesses otherwise. See #78990 for a testcase.
2039 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2040 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2043 mono_memory_barrier ();
2044 class->size_inited = 1;
2047 * Compute static field layout and size
2049 for (i = 0; i < top; i++){
2053 field = &class->fields [i];
2055 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2057 if (mono_field_is_deleted (field))
2060 if (mono_type_has_exceptions (field->type)) {
2061 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2065 has_static_fields = TRUE;
2067 size = mono_type_size (field->type, &align);
2068 field->offset = class->sizes.class_size;
2069 /*align is always non-zero here*/
2070 field->offset += align - 1;
2071 field->offset &= ~(align - 1);
2072 class->sizes.class_size = field->offset + size;
2075 if (has_static_fields && class->sizes.class_size == 0)
2076 /* Simplify code which depends on class_size != 0 if the class has static fields */
2077 class->sizes.class_size = 8;
2081 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2085 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2086 method->klass = class;
2087 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2088 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2089 method->signature = sig;
2090 method->name = name;
2093 if (name [0] == '.') {
2094 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2096 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2102 * mono_class_setup_methods:
2105 * Initializes the 'methods' array in CLASS.
2106 * Calling this method should be avoided if possible since it allocates a lot
2107 * of long-living MonoMethod structures.
2108 * Methods belonging to an interface are assigned a sequential slot starting
2111 * On failure this function sets class->exception_type
2114 mono_class_setup_methods (MonoClass *class)
2117 MonoMethod **methods;
2122 if (class->generic_class) {
2124 MonoClass *gklass = class->generic_class->container_class;
2126 mono_class_init (gklass);
2127 if (!gklass->exception_type)
2128 mono_class_setup_methods (gklass);
2129 if (gklass->exception_type) {
2130 /* FIXME make exception_data less opaque so it's possible to dup it here */
2131 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2135 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2136 count = gklass->method.count;
2137 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2139 for (i = 0; i < count; i++) {
2140 methods [i] = mono_class_inflate_generic_method_full_checked (
2141 gklass->methods [i], class, mono_class_get_context (class), &error);
2142 if (!mono_error_ok (&error)) {
2143 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2144 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)));
2147 mono_error_cleanup (&error);
2151 } else if (class->rank) {
2153 MonoMethod *amethod;
2154 MonoMethodSignature *sig;
2155 int count_generic = 0, first_generic = 0;
2157 gboolean jagged_ctor = FALSE;
2159 count = 3 + (class->rank > 1? 2: 1);
2161 mono_class_setup_interfaces (class, &error);
2162 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2164 if (class->rank == 1 && class->element_class->rank) {
2166 class->method.count ++;
2169 if (class->interface_count) {
2170 count_generic = generic_array_methods (class);
2171 first_generic = count;
2172 count += class->interface_count * count_generic;
2175 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2177 sig = mono_metadata_signature_alloc (class->image, class->rank);
2178 sig->ret = &mono_defaults.void_class->byval_arg;
2179 sig->pinvoke = TRUE;
2180 sig->hasthis = TRUE;
2181 for (i = 0; i < class->rank; ++i)
2182 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2184 amethod = create_array_method (class, ".ctor", sig);
2185 methods [method_num++] = amethod;
2186 if (class->rank > 1) {
2187 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2188 sig->ret = &mono_defaults.void_class->byval_arg;
2189 sig->pinvoke = TRUE;
2190 sig->hasthis = TRUE;
2191 for (i = 0; i < class->rank * 2; ++i)
2192 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2194 amethod = create_array_method (class, ".ctor", sig);
2195 methods [method_num++] = amethod;
2199 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2200 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2201 sig->ret = &mono_defaults.void_class->byval_arg;
2202 sig->pinvoke = TRUE;
2203 sig->hasthis = TRUE;
2204 for (i = 0; i < class->rank + 1; ++i)
2205 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2206 amethod = create_array_method (class, ".ctor", sig);
2207 methods [method_num++] = amethod;
2210 /* element Get (idx11, [idx2, ...]) */
2211 sig = mono_metadata_signature_alloc (class->image, class->rank);
2212 sig->ret = &class->element_class->byval_arg;
2213 sig->pinvoke = TRUE;
2214 sig->hasthis = TRUE;
2215 for (i = 0; i < class->rank; ++i)
2216 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2217 amethod = create_array_method (class, "Get", sig);
2218 methods [method_num++] = amethod;
2219 /* element& Address (idx11, [idx2, ...]) */
2220 sig = mono_metadata_signature_alloc (class->image, class->rank);
2221 sig->ret = &class->element_class->this_arg;
2222 sig->pinvoke = TRUE;
2223 sig->hasthis = TRUE;
2224 for (i = 0; i < class->rank; ++i)
2225 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2226 amethod = create_array_method (class, "Address", sig);
2227 methods [method_num++] = amethod;
2228 /* void Set (idx11, [idx2, ...], element) */
2229 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2230 sig->ret = &mono_defaults.void_class->byval_arg;
2231 sig->pinvoke = TRUE;
2232 sig->hasthis = TRUE;
2233 for (i = 0; i < class->rank; ++i)
2234 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2235 sig->params [i] = &class->element_class->byval_arg;
2236 amethod = create_array_method (class, "Set", sig);
2237 methods [method_num++] = amethod;
2239 for (i = 0; i < class->interface_count; i++)
2240 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2242 count = class->method.count;
2243 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2244 for (i = 0; i < count; ++i) {
2245 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2246 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2250 if (MONO_CLASS_IS_INTERFACE (class)) {
2252 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2253 for (i = 0; i < count; ++i) {
2254 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2255 methods [i]->slot = slot++;
2259 mono_image_lock (class->image);
2261 if (!class->methods) {
2262 class->method.count = count;
2264 /* Needed because of the double-checking locking pattern */
2265 mono_memory_barrier ();
2267 class->methods = methods;
2270 mono_image_unlock (class->image);
2274 * mono_class_get_method_by_index:
2276 * Returns class->methods [index], initializing class->methods if neccesary.
2278 * LOCKING: Acquires the loader lock.
2281 mono_class_get_method_by_index (MonoClass *class, int index)
2284 /* Avoid calling setup_methods () if possible */
2285 if (class->generic_class && !class->methods) {
2286 MonoClass *gklass = class->generic_class->container_class;
2289 m = mono_class_inflate_generic_method_full_checked (
2290 gklass->methods [index], class, mono_class_get_context (class), &error);
2291 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2293 * If setup_methods () is called later for this class, no duplicates are created,
2294 * since inflate_generic_method guarantees that only one instance of a method
2295 * is created for each context.
2298 mono_class_setup_methods (class);
2299 g_assert (m == class->methods [index]);
2303 mono_class_setup_methods (class);
2304 if (class->exception_type) /*FIXME do proper error handling*/
2306 g_assert (index >= 0 && index < class->method.count);
2307 return class->methods [index];
2312 * mono_class_get_inflated_method:
2314 * Given an inflated class CLASS and a method METHOD which should be a method of
2315 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2318 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2320 MonoClass *gklass = class->generic_class->container_class;
2323 g_assert (method->klass == gklass);
2325 mono_class_setup_methods (gklass);
2326 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2328 for (i = 0; i < gklass->method.count; ++i) {
2329 if (gklass->methods [i] == method) {
2330 if (class->methods) {
2331 return class->methods [i];
2334 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], class, mono_class_get_context (class), &error);
2335 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2345 * mono_class_get_vtable_entry:
2347 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2348 * LOCKING: Acquires the loader lock.
2351 mono_class_get_vtable_entry (MonoClass *class, int offset)
2355 if (class->rank == 1) {
2357 * szarrays do not overwrite any methods of Array, so we can avoid
2358 * initializing their vtables in some cases.
2360 mono_class_setup_vtable (class->parent);
2361 if (offset < class->parent->vtable_size)
2362 return class->parent->vtable [offset];
2365 if (class->generic_class) {
2367 MonoClass *gklass = class->generic_class->container_class;
2368 mono_class_setup_vtable (gklass);
2369 m = gklass->vtable [offset];
2371 m = mono_class_inflate_generic_method_full_checked (m, class, mono_class_get_context (class), &error);
2372 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2374 mono_class_setup_vtable (class);
2375 if (class->exception_type)
2377 m = class->vtable [offset];
2384 * mono_class_get_vtable_size:
2386 * Return the vtable size for KLASS.
2389 mono_class_get_vtable_size (MonoClass *klass)
2391 mono_class_setup_vtable (klass);
2393 return klass->vtable_size;
2397 * mono_class_setup_properties:
2399 * Initialize class->ext.property and class->ext.properties.
2401 * This method can fail the class.
2404 mono_class_setup_properties (MonoClass *class)
2406 guint startm, endm, i, j;
2407 guint32 cols [MONO_PROPERTY_SIZE];
2408 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2409 MonoProperty *properties;
2413 if (class->ext && class->ext->properties)
2416 if (class->generic_class) {
2417 MonoClass *gklass = class->generic_class->container_class;
2419 mono_class_init (gklass);
2420 mono_class_setup_properties (gklass);
2421 if (gklass->exception_type) {
2422 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2426 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2428 for (i = 0; i < gklass->ext->property.count; i++) {
2430 MonoProperty *prop = &properties [i];
2432 *prop = gklass->ext->properties [i];
2435 prop->get = mono_class_inflate_generic_method_full_checked (
2436 prop->get, class, mono_class_get_context (class), &error);
2438 prop->set = mono_class_inflate_generic_method_full_checked (
2439 prop->set, class, mono_class_get_context (class), &error);
2441 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2442 prop->parent = class;
2445 first = gklass->ext->property.first;
2446 count = gklass->ext->property.count;
2448 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2449 count = last - first;
2452 mono_class_setup_methods (class);
2453 if (class->exception_type)
2457 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2458 for (i = first; i < last; ++i) {
2459 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2460 properties [i - first].parent = class;
2461 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2462 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2464 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2465 for (j = startm; j < endm; ++j) {
2468 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2470 if (class->image->uncompressed_metadata)
2471 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2472 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2474 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2476 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2477 case METHOD_SEMANTIC_SETTER:
2478 properties [i - first].set = method;
2480 case METHOD_SEMANTIC_GETTER:
2481 properties [i - first].get = method;
2490 mono_class_alloc_ext (class);
2492 mono_image_lock (class->image);
2494 if (class->ext->properties) {
2495 /* We leak 'properties' which was allocated from the image mempool */
2496 mono_image_unlock (class->image);
2500 class->ext->property.first = first;
2501 class->ext->property.count = count;
2503 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2504 mono_memory_barrier ();
2506 /* Leave this assignment as the last op in the function */
2507 class->ext->properties = properties;
2509 mono_image_unlock (class->image);
2513 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2515 MonoMethod **om, **retval;
2518 for (om = methods, count = 0; *om; ++om, ++count)
2521 retval = g_new0 (MonoMethod*, count + 1);
2523 for (om = methods, count = 0; *om; ++om, ++count) {
2525 retval [count] = mono_class_inflate_generic_method_full_checked (*om, class, context, &error);
2526 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2532 /*This method can fail the class.*/
2534 mono_class_setup_events (MonoClass *class)
2537 guint startm, endm, i, j;
2538 guint32 cols [MONO_EVENT_SIZE];
2539 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2543 if (class->ext && class->ext->events)
2546 if (class->generic_class) {
2547 MonoClass *gklass = class->generic_class->container_class;
2548 MonoGenericContext *context = NULL;
2550 mono_class_setup_events (gklass);
2551 if (gklass->exception_type) {
2552 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2556 first = gklass->ext->event.first;
2557 count = gklass->ext->event.count;
2559 events = mono_class_new0 (class, MonoEvent, count);
2562 context = mono_class_get_context (class);
2564 for (i = 0; i < count; i++) {
2566 MonoEvent *event = &events [i];
2567 MonoEvent *gevent = &gklass->ext->events [i];
2569 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2571 event->parent = class;
2572 event->name = gevent->name;
2573 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, class, context, &error) : NULL;
2574 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2575 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, class, context, &error) : NULL;
2576 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2577 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, class, context, &error) : NULL;
2578 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2580 #ifndef MONO_SMALL_CONFIG
2581 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2583 event->attrs = gevent->attrs;
2586 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2587 count = last - first;
2590 mono_class_setup_methods (class);
2591 if (class->exception_type) {
2592 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2597 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2598 for (i = first; i < last; ++i) {
2599 MonoEvent *event = &events [i - first];
2601 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2602 event->parent = class;
2603 event->attrs = cols [MONO_EVENT_FLAGS];
2604 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2606 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2607 for (j = startm; j < endm; ++j) {
2610 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2612 if (class->image->uncompressed_metadata)
2613 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2614 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2616 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2618 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2619 case METHOD_SEMANTIC_ADD_ON:
2620 event->add = method;
2622 case METHOD_SEMANTIC_REMOVE_ON:
2623 event->remove = method;
2625 case METHOD_SEMANTIC_FIRE:
2626 event->raise = method;
2628 case METHOD_SEMANTIC_OTHER: {
2629 #ifndef MONO_SMALL_CONFIG
2632 if (event->other == NULL) {
2633 event->other = g_new0 (MonoMethod*, 2);
2635 while (event->other [n])
2637 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2639 event->other [n] = method;
2640 /* NULL terminated */
2641 event->other [n + 1] = NULL;
2652 mono_class_alloc_ext (class);
2654 mono_image_lock (class->image);
2656 if (class->ext->events) {
2657 mono_image_unlock (class->image);
2661 class->ext->event.first = first;
2662 class->ext->event.count = count;
2664 /* Flush any pending writes as we do double checked locking on class->ext.events */
2665 mono_memory_barrier ();
2667 /* Leave this assignment as the last op in the function */
2668 class->ext->events = events;
2670 mono_image_unlock (class->image);
2674 * Global pool of interface IDs, represented as a bitset.
2675 * LOCKING: Protected by the classes lock.
2677 static MonoBitSet *global_interface_bitset = NULL;
2680 * mono_unload_interface_ids:
2681 * @bitset: bit set of interface IDs
2683 * When an image is unloaded, the interface IDs associated with
2684 * the image are put back in the global pool of IDs so the numbers
2688 mono_unload_interface_ids (MonoBitSet *bitset)
2691 mono_bitset_sub (global_interface_bitset, bitset);
2696 mono_unload_interface_id (MonoClass *class)
2698 if (global_interface_bitset && class->interface_id) {
2700 mono_bitset_clear (global_interface_bitset, class->interface_id);
2706 * mono_get_unique_iid:
2709 * Assign a unique integer ID to the interface represented by @class.
2710 * The ID will positive and as small as possible.
2711 * LOCKING: Acquires the classes lock.
2712 * Returns: the new ID.
2715 mono_get_unique_iid (MonoClass *class)
2719 g_assert (MONO_CLASS_IS_INTERFACE (class));
2723 if (!global_interface_bitset) {
2724 global_interface_bitset = mono_bitset_new (128, 0);
2727 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2729 int old_size = mono_bitset_size (global_interface_bitset);
2730 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2731 mono_bitset_free (global_interface_bitset);
2732 global_interface_bitset = new_set;
2735 mono_bitset_set (global_interface_bitset, iid);
2736 /* set the bit also in the per-image set */
2737 if (!class->generic_class) {
2738 if (class->image->interface_bitset) {
2739 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2740 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2741 mono_bitset_free (class->image->interface_bitset);
2742 class->image->interface_bitset = new_set;
2745 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2747 mono_bitset_set (class->image->interface_bitset, iid);
2752 #ifndef MONO_SMALL_CONFIG
2753 if (mono_print_vtable) {
2755 char *type_name = mono_type_full_name (&class->byval_arg);
2756 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2757 generic_id = class->generic_class->context.class_inst->id;
2758 g_assert (generic_id != 0);
2762 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2767 g_assert (iid <= 65535);
2772 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2777 mono_class_setup_interfaces (klass, error);
2778 if (!mono_error_ok (error))
2781 for (i = 0; i < klass->interface_count; i++) {
2782 ic = klass->interfaces [i];
2785 *res = g_ptr_array_new ();
2786 g_ptr_array_add (*res, ic);
2787 mono_class_init (ic);
2788 if (ic->exception_type) {
2789 mono_error_set_type_load_class (error, ic, "Error Loading class");
2793 collect_implemented_interfaces_aux (ic, res, error);
2794 if (!mono_error_ok (error))
2800 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2802 GPtrArray *res = NULL;
2804 collect_implemented_interfaces_aux (klass, &res, error);
2805 if (!mono_error_ok (error)) {
2807 g_ptr_array_free (res, TRUE);
2814 compare_interface_ids (const void *p_key, const void *p_element) {
2815 const MonoClass *key = p_key;
2816 const MonoClass *element = *(MonoClass**) p_element;
2818 return (key->interface_id - element->interface_id);
2821 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2823 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2824 MonoClass **result = mono_binary_search (
2826 klass->interfaces_packed,
2827 klass->interface_offsets_count,
2828 sizeof (MonoClass *),
2829 compare_interface_ids);
2831 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2838 * mono_class_interface_offset_with_variance:
2840 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2841 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2843 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2845 * FIXME figure out MS disambiguation rules and fix this function.
2848 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2849 int i = mono_class_interface_offset (klass, itf);
2850 *non_exact_match = FALSE;
2854 if (!mono_class_has_variant_generic_params (itf))
2857 for (i = 0; i < klass->interface_offsets_count; i++) {
2858 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2859 *non_exact_match = TRUE;
2860 return klass->interface_offsets_packed [i];
2868 print_implemented_interfaces (MonoClass *klass) {
2871 GPtrArray *ifaces = NULL;
2873 int ancestor_level = 0;
2875 name = mono_type_get_full_name (klass);
2876 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2879 for (i = 0; i < klass->interface_offsets_count; i++)
2880 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2881 klass->interfaces_packed [i]->interface_id,
2882 klass->interface_offsets_packed [i],
2883 klass->interfaces_packed [i]->method.count,
2884 klass->interfaces_packed [i]->name_space,
2885 klass->interfaces_packed [i]->name );
2886 printf ("Interface flags: ");
2887 for (i = 0; i <= klass->max_interface_id; i++)
2888 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2889 printf ("(%d,T)", i);
2891 printf ("(%d,F)", i);
2893 printf ("Dump interface flags:");
2894 #ifdef COMPRESSED_INTERFACE_BITMAP
2896 const uint8_t* p = klass->interface_bitmap;
2897 i = klass->max_interface_id;
2899 printf (" %d x 00 %02X", p [0], p [1]);
2905 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2906 printf (" %02X", klass->interface_bitmap [i]);
2909 while (klass != NULL) {
2910 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2911 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2912 if (!mono_error_ok (&error)) {
2913 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2914 mono_error_cleanup (&error);
2915 } else if (ifaces) {
2916 for (i = 0; i < ifaces->len; i++) {
2917 MonoClass *ic = g_ptr_array_index (ifaces, i);
2918 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2919 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2921 mono_class_interface_offset (klass, ic),
2926 g_ptr_array_free (ifaces, TRUE);
2929 klass = klass->parent;
2934 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2937 args [0] = &arg0->byval_arg;
2939 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2943 array_class_get_if_rank (MonoClass *class, guint rank)
2945 return rank ? mono_array_class_get (class, rank) : class;
2949 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2951 valuetype_types [0] = eclass;
2952 if (eclass == mono_defaults.int16_class)
2953 valuetype_types [1] = mono_defaults.uint16_class;
2954 else if (eclass == mono_defaults.uint16_class)
2955 valuetype_types [1] = mono_defaults.int16_class;
2956 else if (eclass == mono_defaults.int32_class)
2957 valuetype_types [1] = mono_defaults.uint32_class;
2958 else if (eclass == mono_defaults.uint32_class)
2959 valuetype_types [1] = mono_defaults.int32_class;
2960 else if (eclass == mono_defaults.int64_class)
2961 valuetype_types [1] = mono_defaults.uint64_class;
2962 else if (eclass == mono_defaults.uint64_class)
2963 valuetype_types [1] = mono_defaults.int64_class;
2964 else if (eclass == mono_defaults.byte_class)
2965 valuetype_types [1] = mono_defaults.sbyte_class;
2966 else if (eclass == mono_defaults.sbyte_class)
2967 valuetype_types [1] = mono_defaults.byte_class;
2968 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2969 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2972 /* this won't be needed once bug #325495 is completely fixed
2973 * though we'll need something similar to know which interfaces to allow
2974 * in arrays when they'll be lazyly created
2976 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2977 * MS returns diferrent types based on which instance is called. For example:
2978 * object obj = new byte[10][];
2979 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2980 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2983 * Fixing this should kill quite some code, save some bits and improve compatibility.
2986 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2988 MonoClass *eclass = class->element_class;
2989 static MonoClass* generic_icollection_class = NULL;
2990 static MonoClass* generic_ienumerable_class = NULL;
2991 static MonoClass* generic_ienumerator_class = NULL;
2992 static MonoClass* generic_ireadonlylist_class = NULL;
2993 static MonoClass* generic_ireadonlycollection_class = NULL;
2994 MonoClass *valuetype_types[2] = { NULL, NULL };
2995 MonoClass **interfaces = NULL;
2996 int i, nifaces, interface_count, real_count, original_rank;
2998 gboolean internal_enumerator;
2999 gboolean eclass_is_valuetype;
3001 if (!mono_defaults.generic_ilist_class) {
3005 internal_enumerator = FALSE;
3006 eclass_is_valuetype = FALSE;
3007 original_rank = eclass->rank;
3008 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
3009 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
3011 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3013 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
3014 original_rank = eclass->rank;
3016 eclass = eclass->element_class;
3017 internal_enumerator = TRUE;
3018 *is_enumerator = TRUE;
3026 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3027 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3029 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3031 if (!generic_icollection_class) {
3032 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3033 "System.Collections.Generic", "ICollection`1");
3034 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3035 "System.Collections.Generic", "IEnumerable`1");
3036 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3037 "System.Collections.Generic", "IEnumerator`1");
3038 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3039 "System.Collections.Generic", "IReadOnlyList`1");
3040 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3041 "System.Collections.Generic", "IReadOnlyCollection`1");
3044 mono_class_init (eclass);
3047 * Arrays in 2.0 need to implement a number of generic interfaces
3048 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3049 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3050 * We collect the types needed to build the
3051 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3052 * the generic interfaces needed to implement.
3054 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3055 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3057 if (eclass->valuetype) {
3058 nifaces = generic_ireadonlylist_class ? 5 : 3;
3059 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3061 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3062 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3063 if (internal_enumerator) {
3065 if (valuetype_types [1])
3069 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3070 interfaces [0] = valuetype_types [0];
3071 if (valuetype_types [1])
3072 interfaces [nifaces] = valuetype_types [1];
3074 eclass_is_valuetype = TRUE;
3077 int idepth = eclass->idepth;
3078 if (!internal_enumerator)
3080 nifaces = generic_ireadonlylist_class ? 2 : 3;
3082 // FIXME: This doesn't seem to work/required for generic params
3083 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3084 mono_class_setup_interface_offsets (eclass);
3086 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3087 /* we add object for interfaces and the supertypes for the other
3088 * types. The last of the supertypes is the element class itself which we
3089 * already created the explicit interfaces for (so we include it for IEnumerator
3090 * and exclude it for arrays).
3092 if (MONO_CLASS_IS_INTERFACE (eclass))
3095 interface_count += idepth;
3096 if (eclass->rank && eclass->element_class->valuetype) {
3097 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3098 if (valuetype_types [1])
3101 /* IList, ICollection, IEnumerable, IReadOnlyList */
3102 interface_count *= nifaces;
3103 real_count = interface_count;
3104 if (internal_enumerator) {
3105 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3106 if (valuetype_types [1])
3109 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3110 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3111 interfaces [0] = mono_defaults.object_class;
3115 for (i = 0; i < idepth; i++) {
3116 mono_class_init (eclass->supertypes [i]);
3117 interfaces [j] = eclass->supertypes [i];
3121 if (all_interfaces) {
3122 for (i = 0; i < eclass->interface_offsets_count; i++) {
3123 interfaces [j] = eclass->interfaces_packed [i];
3127 for (i = 0; i < eclass->interface_count; i++) {
3128 interfaces [j] = eclass->interfaces [i];
3132 if (valuetype_types [1]) {
3133 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3138 /* instantiate the generic interfaces */
3139 for (i = 0; i < interface_count; i += nifaces) {
3140 MonoClass *iface = interfaces [i];
3142 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3143 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3145 if (eclass->valuetype) {
3146 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3147 if (generic_ireadonlylist_class) {
3148 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3149 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3152 if (!generic_ireadonlylist_class)
3153 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3156 if (internal_enumerator) {
3158 /* instantiate IEnumerator<iface> */
3159 for (i = 0; i < interface_count; i++) {
3160 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3162 j = interface_count;
3163 if (!eclass_is_valuetype) {
3164 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3165 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3168 for (i = 0; i < eclass->idepth; i++) {
3169 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3173 for (i = 0; i < eclass->interface_offsets_count; i++) {
3174 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3178 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3180 if (valuetype_types [1])
3181 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3185 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3186 for (i = 0; i < real_count; ++i) {
3187 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3188 g_print ("%s implements %s\n", type_name, name);
3199 find_array_interface (MonoClass *klass, const char *name)
3202 for (i = 0; i < klass->interface_count; ++i) {
3203 if (strcmp (klass->interfaces [i]->name, name) == 0)
3210 * Return the number of virtual methods.
3211 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3212 * Return -1 on failure.
3213 * FIXME It would be nice if this information could be cached somewhere.
3216 count_virtual_methods (MonoClass *class)
3220 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3222 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3223 mono_class_setup_methods (class);
3224 if (class->exception_type)
3227 for (i = 0; i < class->method.count; ++i) {
3228 flags = class->methods [i]->flags;
3229 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3233 for (i = 0; i < class->method.count; ++i) {
3234 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3236 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3244 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3252 m = (l + num_ifaces) / 2;
3253 if (interfaces_full [m] == ic)
3255 if (l == num_ifaces)
3257 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3266 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3268 int i = find_interface (num_ifaces, interfaces_full, ic);
3270 return interface_offsets_full [i];
3275 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3277 int i = find_interface (num_ifaces, interfaces_full, ic);
3281 interface_offsets_full [i] = offset;
3284 for (i = 0; i < num_ifaces; ++i) {
3285 if (interfaces_full [i]) {
3287 if (interfaces_full [i]->interface_id < ic->interface_id)
3290 while (end < num_ifaces && interfaces_full [end]) end++;
3291 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3292 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3294 interfaces_full [i] = ic;
3295 interface_offsets_full [i] = offset;
3301 #ifdef COMPRESSED_INTERFACE_BITMAP
3304 * Compressed interface bitmap design.
3306 * Interface bitmaps take a large amount of memory, because their size is
3307 * linear with the maximum interface id assigned in the process (each interface
3308 * is assigned a unique id as it is loaded). The number of interface classes
3309 * is high because of the many implicit interfaces implemented by arrays (we'll
3310 * need to lazy-load them in the future).
3311 * Most classes implement a very small number of interfaces, so the bitmap is
3312 * sparse. This bitmap needs to be checked by interface casts, so access to the
3313 * needed bit must be fast and doable with few jit instructions.
3315 * The current compression format is as follows:
3316 * *) it is a sequence of one or more two-byte elements
3317 * *) the first byte in the element is the count of empty bitmap bytes
3318 * at the current bitmap position
3319 * *) the second byte in the element is an actual bitmap byte at the current
3322 * As an example, the following compressed bitmap bytes:
3323 * 0x07 0x01 0x00 0x7
3324 * correspond to the following bitmap:
3325 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3327 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3328 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3329 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3333 * mono_compress_bitmap:
3334 * @dest: destination buffer
3335 * @bitmap: bitmap buffer
3336 * @size: size of @bitmap in bytes
3338 * This is a mono internal function.
3339 * The @bitmap data is compressed into a format that is small but
3340 * still searchable in few instructions by the JIT and runtime.
3341 * The compressed data is stored in the buffer pointed to by the
3342 * @dest array. Passing a #NULL value for @dest allows to just compute
3343 * the size of the buffer.
3344 * This compression algorithm assumes the bits set in the bitmap are
3345 * few and far between, like in interface bitmaps.
3346 * Returns: the size of the compressed bitmap in bytes.
3349 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3353 const uint8_t *end = bitmap + size;
3354 while (bitmap < end) {
3355 if (*bitmap || numz == 255) {
3379 * mono_class_interface_match:
3380 * @bitmap: a compressed bitmap buffer
3381 * @id: the index to check in the bitmap
3383 * This is a mono internal function.
3384 * Checks if a bit is set in a compressed interface bitmap. @id must
3385 * be already checked for being smaller than the maximum id encoded in the
3388 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3392 mono_class_interface_match (const uint8_t *bitmap, int id)
3395 id -= bitmap [0] * 8;
3399 return bitmap [1] & (1 << id);
3408 * LOCKING: this is supposed to be called with the loader lock held.
3409 * Return -1 on failure and set exception_type
3412 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3416 int i, j, max_iid, num_ifaces;
3417 MonoClass **interfaces_full = NULL;
3418 int *interface_offsets_full = NULL;
3420 GPtrArray **ifaces_array = NULL;
3421 int interface_offsets_count;
3422 MonoClass **array_interfaces = NULL;
3423 int num_array_interfaces;
3424 int is_enumerator = FALSE;
3426 mono_class_setup_supertypes (class);
3428 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3429 * implicit interfaces have the property that they are assigned the same slot in the
3430 * vtables for compatible interfaces
3432 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3434 /* compute maximum number of slots and maximum interface id */
3436 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3437 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3438 for (j = 0; j < class->idepth; j++) {
3439 k = class->supertypes [j];
3440 num_ifaces += k->interface_count;
3441 for (i = 0; i < k->interface_count; i++) {
3442 ic = k->interfaces [i];
3445 mono_class_init (ic);
3447 if (max_iid < ic->interface_id)
3448 max_iid = ic->interface_id;
3450 ifaces = mono_class_get_implemented_interfaces (k, &error);
3451 if (!mono_error_ok (&error)) {
3452 char *name = mono_type_get_full_name (k);
3453 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)));
3455 mono_error_cleanup (&error);
3460 num_ifaces += ifaces->len;
3461 for (i = 0; i < ifaces->len; ++i) {
3462 ic = g_ptr_array_index (ifaces, i);
3463 if (max_iid < ic->interface_id)
3464 max_iid = ic->interface_id;
3466 ifaces_array [j] = ifaces;
3470 for (i = 0; i < num_array_interfaces; ++i) {
3471 ic = array_interfaces [i];
3472 mono_class_init (ic);
3473 if (max_iid < ic->interface_id)
3474 max_iid = ic->interface_id;
3477 if (MONO_CLASS_IS_INTERFACE (class)) {
3479 if (max_iid < class->interface_id)
3480 max_iid = class->interface_id;
3482 class->max_interface_id = max_iid;
3483 /* compute vtable offset for interfaces */
3484 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3485 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3487 for (i = 0; i < num_ifaces; i++) {
3488 interface_offsets_full [i] = -1;
3491 /* skip the current class */
3492 for (j = 0; j < class->idepth - 1; j++) {
3493 k = class->supertypes [j];
3494 ifaces = ifaces_array [j];
3497 for (i = 0; i < ifaces->len; ++i) {
3499 ic = g_ptr_array_index (ifaces, i);
3501 /*Force the sharing of interface offsets between parent and subtypes.*/
3502 io = mono_class_interface_offset (k, ic);
3504 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3509 g_assert (class == class->supertypes [class->idepth - 1]);
3510 ifaces = ifaces_array [class->idepth - 1];
3512 for (i = 0; i < ifaces->len; ++i) {
3514 ic = g_ptr_array_index (ifaces, i);
3515 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3517 count = count_virtual_methods (ic);
3519 char *name = mono_type_get_full_name (ic);
3520 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3529 if (MONO_CLASS_IS_INTERFACE (class))
3530 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3532 if (num_array_interfaces) {
3533 if (is_enumerator) {
3534 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3535 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3536 g_assert (ienumerator_offset >= 0);
3537 for (i = 0; i < num_array_interfaces; ++i) {
3538 ic = array_interfaces [i];
3539 if (strcmp (ic->name, "IEnumerator`1") == 0)
3540 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3542 g_assert_not_reached ();
3543 /*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);*/
3546 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3547 int ilist_iface_idx = find_array_interface (class, "IList`1");
3548 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3549 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3550 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3551 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3552 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3553 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3554 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3555 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3556 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3557 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3558 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3559 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3560 for (i = 0; i < num_array_interfaces; ++i) {
3562 ic = array_interfaces [i];
3563 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3564 offset = ilist_offset;
3565 else if (strcmp (ic->name, "ICollection`1") == 0)
3566 offset = icollection_offset;
3567 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3568 offset = ienumerable_offset;
3569 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3570 offset = ireadonlylist_offset;
3571 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3572 offset = ireadonlycollection_offset;
3574 g_assert_not_reached ();
3575 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3576 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3581 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3582 if (interface_offsets_full [i] != -1) {
3583 interface_offsets_count ++;
3588 * We might get called multiple times:
3589 * - mono_class_init ()
3590 * - mono_class_setup_vtable ().
3591 * - mono_class_setup_interface_offsets ().
3592 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3593 * means we have to overwrite those when called from other places (#4440).
3595 if (class->interfaces_packed && !overwrite) {
3596 g_assert (class->interface_offsets_count == interface_offsets_count);
3600 class->interface_offsets_count = interface_offsets_count;
3601 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3602 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3603 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3604 #ifdef COMPRESSED_INTERFACE_BITMAP
3605 bitmap = g_malloc0 (bsize);
3607 bitmap = mono_class_alloc0 (class, bsize);
3609 for (i = 0; i < interface_offsets_count; i++) {
3610 int id = interfaces_full [i]->interface_id;
3611 bitmap [id >> 3] |= (1 << (id & 7));
3612 class->interfaces_packed [i] = interfaces_full [i];
3613 class->interface_offsets_packed [i] = interface_offsets_full [i];
3614 /*if (num_array_interfaces)
3615 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]);*/
3617 #ifdef COMPRESSED_INTERFACE_BITMAP
3618 i = mono_compress_bitmap (NULL, bitmap, bsize);
3619 class->interface_bitmap = mono_class_alloc0 (class, i);
3620 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3623 class->interface_bitmap = bitmap;
3628 g_free (interfaces_full);
3629 g_free (interface_offsets_full);
3630 g_free (array_interfaces);
3631 for (i = 0; i < class->idepth; i++) {
3632 ifaces = ifaces_array [i];
3634 g_ptr_array_free (ifaces, TRUE);
3636 g_free (ifaces_array);
3638 //printf ("JUST DONE: ");
3639 //print_implemented_interfaces (class);
3645 * Setup interface offsets for interfaces.
3647 * - class->max_interface_id
3648 * - class->interface_offsets_count
3649 * - class->interfaces_packed
3650 * - class->interface_offsets_packed
3651 * - class->interface_bitmap
3653 * This function can fail @class.
3656 mono_class_setup_interface_offsets (MonoClass *class)
3658 mono_loader_lock ();
3660 setup_interface_offsets (class, 0, FALSE);
3662 mono_loader_unlock ();
3665 /*Checks if @klass has @parent as one of it's parents type gtd
3669 * Bar<T> : Foo<Bar<Bar<T>>>
3673 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3675 klass = mono_class_get_generic_type_definition (klass);
3676 parent = mono_class_get_generic_type_definition (parent);
3677 mono_class_setup_supertypes (klass);
3678 mono_class_setup_supertypes (parent);
3680 return klass->idepth >= parent->idepth &&
3681 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3685 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3687 MonoGenericInst *ginst;
3689 if (!class->generic_class) {
3690 mono_class_setup_vtable_full (class, in_setup);
3691 return class->exception_type == 0;
3694 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3695 if (class->generic_class->container_class->exception_type) {
3696 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3700 ginst = class->generic_class->context.class_inst;
3701 for (i = 0; i < ginst->type_argc; ++i) {
3703 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3705 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3706 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3707 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3709 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3710 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3718 * mono_class_setup_vtable:
3720 * Creates the generic vtable of CLASS.
3721 * Initializes the following fields in MonoClass:
3724 * Plus all the fields initialized by setup_interface_offsets ().
3725 * If there is an error during vtable construction, class->exception_type is set.
3727 * LOCKING: Acquires the loader lock.
3730 mono_class_setup_vtable (MonoClass *class)
3732 mono_class_setup_vtable_full (class, NULL);
3736 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3738 MonoMethod **overrides;
3739 MonoGenericContext *context;
3747 if (MONO_CLASS_IS_INTERFACE (class)) {
3748 /* This sets method->slot for all methods if this is an interface */
3749 mono_class_setup_methods (class);
3753 if (class->exception_type)
3756 if (g_list_find (in_setup, class))
3759 mono_loader_lock ();
3761 if (class->vtable) {
3762 mono_loader_unlock ();
3766 mono_stats.generic_vtable_count ++;
3767 in_setup = g_list_prepend (in_setup, class);
3769 if (class->generic_class) {
3770 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3771 mono_loader_unlock ();
3772 g_list_remove (in_setup, class);
3776 context = mono_class_get_context (class);
3777 type_token = class->generic_class->container_class->type_token;
3779 context = (MonoGenericContext *) class->generic_container;
3780 type_token = class->type_token;
3783 if (image_is_dynamic (class->image)) {
3784 /* Generic instances can have zero method overrides without causing any harm.
3785 * This is true since we don't do layout all over again for them, we simply inflate
3786 * the layout of the parent.
3788 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3790 /* The following call fails if there are missing methods in the type */
3791 /* FIXME it's probably a good idea to avoid this for generic instances. */
3792 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3796 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3798 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3802 mono_loader_unlock ();
3803 g_list_remove (in_setup, class);
3808 #define DEBUG_INTERFACE_VTABLE_CODE 0
3809 #define TRACE_INTERFACE_VTABLE_CODE 0
3810 #define VERIFY_INTERFACE_VTABLE_CODE 0
3811 #define VTABLE_SELECTOR (1)
3813 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3814 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3815 if (!(VTABLE_SELECTOR)) break; \
3819 #define DEBUG_INTERFACE_VTABLE(stmt)
3822 #if TRACE_INTERFACE_VTABLE_CODE
3823 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3824 if (!(VTABLE_SELECTOR)) break; \
3828 #define TRACE_INTERFACE_VTABLE(stmt)
3831 #if VERIFY_INTERFACE_VTABLE_CODE
3832 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3833 if (!(VTABLE_SELECTOR)) break; \
3837 #define VERIFY_INTERFACE_VTABLE(stmt)
3841 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3843 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3847 GString *res = g_string_new ("");
3849 g_string_append_c (res, '(');
3850 for (i = 0; i < sig->param_count; ++i) {
3852 g_string_append_c (res, ',');
3853 mono_type_get_desc (res, sig->params [i], include_namespace);
3855 g_string_append (res, ")=>");
3856 if (sig->ret != NULL) {
3857 mono_type_get_desc (res, sig->ret, include_namespace);
3859 g_string_append (res, "NULL");
3862 g_string_free (res, FALSE);
3866 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3867 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3868 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3869 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3877 is_wcf_hack_disabled (void)
3879 static gboolean disabled;
3880 static gboolean inited = FALSE;
3882 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3889 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) {
3890 MonoMethodSignature *cmsig, *imsig;
3891 if (strcmp (im->name, cm->name) == 0) {
3892 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3893 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3896 if (! slot_is_empty) {
3897 if (require_newslot) {
3898 if (! interface_is_explicitly_implemented_by_class) {
3899 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3902 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3903 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3907 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3910 cmsig = mono_method_signature (cm);
3911 imsig = mono_method_signature (im);
3912 if (!cmsig || !imsig) {
3913 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3917 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3918 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3919 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3920 TRACE_INTERFACE_VTABLE (printf ("]"));
3923 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3924 /* CAS - SecurityAction.InheritanceDemand on interface */
3925 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3926 mono_secman_inheritancedemand_method (cm, im);
3929 if (mono_security_core_clr_enabled ())
3930 mono_security_core_clr_check_override (class, cm, im);
3932 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3933 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3934 char *body_name = mono_method_full_name (cm, TRUE);
3935 char *decl_name = mono_method_full_name (im, TRUE);
3936 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));
3944 MonoClass *ic = im->klass;
3945 const char *ic_name_space = ic->name_space;
3946 const char *ic_name = ic->name;
3949 if (! require_newslot) {
3950 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3953 if (cm->klass->rank == 0) {
3954 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3957 cmsig = mono_method_signature (cm);
3958 imsig = mono_method_signature (im);
3959 if (!cmsig || !imsig) {
3960 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3964 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3965 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3966 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3967 TRACE_INTERFACE_VTABLE (printf ("]"));
3970 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3971 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3974 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3975 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3978 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))) {
3979 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3983 subname = strstr (cm->name, ic_name_space);
3984 if (subname != cm->name) {
3985 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3988 subname += strlen (ic_name_space);
3989 if (subname [0] != '.') {
3990 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3994 if (strstr (subname, ic_name) != subname) {
3995 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3998 subname += strlen (ic_name);
3999 if (subname [0] != '.') {
4000 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4004 if (strcmp (subname, im->name) != 0) {
4005 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4009 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4010 /* CAS - SecurityAction.InheritanceDemand on interface */
4011 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4012 mono_secman_inheritancedemand_method (cm, im);
4015 if (mono_security_core_clr_enabled ())
4016 mono_security_core_clr_check_override (class, cm, im);
4018 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4019 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4020 char *body_name = mono_method_full_name (cm, TRUE);
4021 char *decl_name = mono_method_full_name (im, TRUE);
4022 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));
4032 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4034 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4035 MonoMethod *method = key;
4036 MonoMethod *override = value;
4037 MonoClass *method_class = mono_method_get_class (method);
4038 MonoClass *override_class = mono_method_get_class (override);
4040 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4041 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4042 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4045 print_overrides (GHashTable *override_map, const char *message) {
4047 printf ("Override map \"%s\" START:\n", message);
4048 g_hash_table_foreach (override_map, foreach_override, NULL);
4049 printf ("Override map \"%s\" END.\n", message);
4051 printf ("Override map \"%s\" EMPTY.\n", message);
4055 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4056 char *full_name = mono_type_full_name (&class->byval_arg);
4060 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4062 if (print_interfaces) {
4063 print_implemented_interfaces (class);
4064 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4067 if (class->parent) {
4068 parent_size = class->parent->vtable_size;
4072 for (i = 0; i < size; ++i) {
4073 MonoMethod *cm = vtable [i];
4074 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4075 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4077 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4085 #if VERIFY_INTERFACE_VTABLE_CODE
4087 mono_method_try_get_vtable_index (MonoMethod *method)
4089 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4090 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4091 if (imethod->declaring->is_generic)
4092 return imethod->declaring->slot;
4094 return method->slot;
4098 mono_class_verify_vtable (MonoClass *class)
4101 char *full_name = mono_type_full_name (&class->byval_arg);
4103 printf ("*** Verifying VTable of class '%s' \n", full_name);
4107 if (!class->methods)
4110 for (i = 0; i < class->method.count; ++i) {
4111 MonoMethod *cm = class->methods [i];
4114 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4118 full_name = mono_method_full_name (cm, TRUE);
4120 slot = mono_method_try_get_vtable_index (cm);
4122 if (slot >= class->vtable_size) {
4123 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4127 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4128 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4129 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4130 g_free (other_name);
4133 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4140 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4142 char *method_signature;
4145 for (index = 0; index < onum; ++index) {
4146 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4147 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4149 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4150 type_name = mono_type_full_name (&class->byval_arg);
4151 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4152 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4153 g_free (method_signature);
4155 mono_class_setup_methods (class);
4156 if (class->exception_type) {
4157 char *name = mono_type_get_full_name (class);
4158 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4162 for (index = 0; index < class->method.count; ++index) {
4163 MonoMethod *cm = class->methods [index];
4164 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4166 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4167 g_free (method_signature);
4172 mono_method_get_method_definition (MonoMethod *method)
4174 while (method->is_inflated)
4175 method = ((MonoMethodInflated*)method)->declaring;
4180 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4184 for (i = 0; i < onum; ++i) {
4185 MonoMethod *decl = overrides [i * 2];
4186 MonoMethod *body = overrides [i * 2 + 1];
4188 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4189 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4193 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4194 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4195 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4197 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4201 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4202 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4203 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4205 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4209 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4210 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4214 body = mono_method_get_method_definition (body);
4215 decl = mono_method_get_method_definition (decl);
4217 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4218 char *body_name = mono_method_full_name (body, TRUE);
4219 char *decl_name = mono_method_full_name (decl, TRUE);
4220 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));
4230 mono_class_need_stelemref_method (MonoClass *class)
4232 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4236 * LOCKING: this is supposed to be called with the loader lock held.
4239 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4243 MonoMethod **vtable;
4244 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4245 GPtrArray *ifaces = NULL;
4246 GHashTable *override_map = NULL;
4247 gboolean security_enabled = mono_security_enabled ();
4249 gpointer class_iter;
4250 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4251 int first_non_interface_slot;
4253 GSList *virt_methods = NULL, *l;
4254 int stelemref_slot = 0;
4259 if (overrides && !verify_class_overrides (class, overrides, onum))
4262 ifaces = mono_class_get_implemented_interfaces (class, &error);
4263 if (!mono_error_ok (&error)) {
4264 char *name = mono_type_get_full_name (class);
4265 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)));
4267 mono_error_cleanup (&error);
4269 } else if (ifaces) {
4270 for (i = 0; i < ifaces->len; i++) {
4271 MonoClass *ic = g_ptr_array_index (ifaces, i);
4272 max_vtsize += ic->method.count;
4274 g_ptr_array_free (ifaces, TRUE);
4278 if (class->parent) {
4279 mono_class_init (class->parent);
4280 mono_class_setup_vtable_full (class->parent, in_setup);
4282 if (class->parent->exception_type) {
4283 char *name = mono_type_get_full_name (class->parent);
4284 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4289 max_vtsize += class->parent->vtable_size;
4290 cur_slot = class->parent->vtable_size;
4293 max_vtsize += class->method.count;
4295 /*Array have a slot for stelemref*/
4296 if (mono_class_need_stelemref_method (class)) {
4297 stelemref_slot = cur_slot;
4302 vtable = alloca (sizeof (gpointer) * max_vtsize);
4303 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4305 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4307 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4308 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4311 max_iid = class->max_interface_id;
4312 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4314 /* Optimized version for generic instances */
4315 if (class->generic_class) {
4317 MonoClass *gklass = class->generic_class->container_class;
4320 mono_class_setup_vtable_full (gklass, in_setup);
4321 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4322 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4326 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4327 class->vtable_size = gklass->vtable_size;
4328 for (i = 0; i < gklass->vtable_size; ++i)
4329 if (gklass->vtable [i]) {
4330 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4331 if (!mono_error_ok (&error)) {
4332 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4333 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4335 mono_error_cleanup (&error);
4339 tmp [i]->slot = gklass->vtable [i]->slot;
4341 mono_memory_barrier ();
4342 class->vtable = tmp;
4344 /* Have to set method->slot for abstract virtual methods */
4345 if (class->methods && gklass->methods) {
4346 for (i = 0; i < class->method.count; ++i)
4347 if (class->methods [i]->slot == -1)
4348 class->methods [i]->slot = gklass->methods [i]->slot;
4354 if (class->parent && class->parent->vtable_size) {
4355 MonoClass *parent = class->parent;
4358 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4360 // Also inherit parent interface vtables, just as a starting point.
4361 // This is needed otherwise bug-77127.exe fails when the property methods
4362 // have different names in the iterface and the class, because for child
4363 // classes the ".override" information is not used anymore.
4364 for (i = 0; i < parent->interface_offsets_count; i++) {
4365 MonoClass *parent_interface = parent->interfaces_packed [i];
4366 int interface_offset = mono_class_interface_offset (class, parent_interface);
4367 /*FIXME this is now dead code as this condition will never hold true.
4368 Since interface offsets are inherited then the offset of an interface implemented
4369 by a parent will never be the out of it's vtable boundary.
4371 if (interface_offset >= parent->vtable_size) {
4372 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4375 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4376 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4377 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4378 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4379 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4380 parent_interface_offset + j, parent_interface_offset, j,
4381 interface_offset + j, interface_offset, j));
4388 /*Array have a slot for stelemref*/
4389 if (mono_class_need_stelemref_method (class)) {
4390 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4392 method->slot = stelemref_slot;
4394 g_assert (method->slot == stelemref_slot);
4396 vtable [stelemref_slot] = method;
4399 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4400 /* override interface methods */
4401 for (i = 0; i < onum; i++) {
4402 MonoMethod *decl = overrides [i*2];
4403 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4405 dslot = mono_method_get_vtable_slot (decl);
4407 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4411 dslot += mono_class_interface_offset (class, decl->klass);
4412 vtable [dslot] = overrides [i*2 + 1];
4413 vtable [dslot]->slot = dslot;
4415 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4417 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4419 if (mono_security_core_clr_enabled ())
4420 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4423 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4424 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4427 * Create a list of virtual methods to avoid calling
4428 * mono_class_get_virtual_methods () which is slow because of the metadata
4432 gpointer iter = NULL;
4435 virt_methods = NULL;
4436 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4437 virt_methods = g_slist_prepend (virt_methods, cm);
4439 if (class->exception_type)
4443 // Loop on all implemented interfaces...
4444 for (i = 0; i < class->interface_offsets_count; i++) {
4445 MonoClass *parent = class->parent;
4447 gboolean interface_is_explicitly_implemented_by_class;
4450 ic = class->interfaces_packed [i];
4451 ic_offset = mono_class_interface_offset (class, ic);
4453 mono_class_setup_methods (ic);
4454 if (ic->exception_type)
4457 // Check if this interface is explicitly implemented (instead of just inherited)
4458 if (parent != NULL) {
4459 int implemented_interfaces_index;
4460 interface_is_explicitly_implemented_by_class = FALSE;
4461 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4462 if (ic == class->interfaces [implemented_interfaces_index]) {
4463 interface_is_explicitly_implemented_by_class = TRUE;
4468 interface_is_explicitly_implemented_by_class = TRUE;
4471 // Loop on all interface methods...
4472 for (im_index = 0; im_index < ic->method.count; im_index++) {
4473 MonoMethod *im = ic->methods [im_index];
4474 int im_slot = ic_offset + im->slot;
4475 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4477 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4480 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4482 // If there is an explicit implementation, just use it right away,
4483 // otherwise look for a matching method
4484 if (override_im == NULL) {
4489 // First look for a suitable method among the class methods
4491 for (l = virt_methods; l; l = l->next) {
4493 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)));
4494 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4495 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4496 vtable [im_slot] = cm;
4497 /* Why do we need this? */
4502 TRACE_INTERFACE_VTABLE (printf ("\n"));
4503 if (class->exception_type) /*Might be set by check_interface_method_override*/
4507 // If the slot is still empty, look in all the inherited virtual methods...
4508 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4509 MonoClass *parent = class->parent;
4510 // Reverse order, so that last added methods are preferred
4511 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4512 MonoMethod *cm = parent->vtable [cm_index];
4514 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));
4515 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4516 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4517 vtable [im_slot] = cm;
4518 /* Why do we need this? */
4524 if (class->exception_type) /*Might be set by check_interface_method_override*/
4526 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4530 g_assert (vtable [im_slot] == override_im);
4535 // If the class is not abstract, check that all its interface slots are full.
4536 // The check is done here and not directly at the end of the loop above because
4537 // it can happen (for injected generic array interfaces) that the same slot is
4538 // processed multiple times (those interfaces have overlapping slots), and it
4539 // will not always be the first pass the one that fills the slot.
4540 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4541 for (i = 0; i < class->interface_offsets_count; i++) {
4545 ic = class->interfaces_packed [i];
4546 ic_offset = mono_class_interface_offset (class, ic);
4548 for (im_index = 0; im_index < ic->method.count; im_index++) {
4549 MonoMethod *im = ic->methods [im_index];
4550 int im_slot = ic_offset + im->slot;
4552 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4555 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4556 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4557 if (vtable [im_slot] == NULL) {
4558 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4565 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4567 for (l = virt_methods; l; l = l->next) {
4570 * If the method is REUSE_SLOT, we must check in the
4571 * base class for a method to override.
4573 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4575 for (k = class->parent; k ; k = k->parent) {
4580 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4581 MonoMethodSignature *cmsig, *m1sig;
4583 cmsig = mono_method_signature (cm);
4584 m1sig = mono_method_signature (m1);
4586 if (!cmsig || !m1sig) {
4587 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4591 if (!strcmp(cm->name, m1->name) &&
4592 mono_metadata_signature_equal (cmsig, m1sig)) {
4594 /* CAS - SecurityAction.InheritanceDemand */
4595 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4596 mono_secman_inheritancedemand_method (cm, m1);
4599 if (mono_security_core_clr_enabled ())
4600 mono_security_core_clr_check_override (class, cm, m1);
4602 slot = mono_method_get_vtable_slot (m1);
4606 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4607 char *body_name = mono_method_full_name (cm, TRUE);
4608 char *decl_name = mono_method_full_name (m1, TRUE);
4609 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));
4615 g_assert (cm->slot < max_vtsize);
4617 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4618 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4619 mono_method_full_name (m1, 1), m1,
4620 mono_method_full_name (cm, 1), cm));
4621 g_hash_table_insert (override_map, m1, cm);
4625 if (k->exception_type)
4635 /*Non final newslot methods must be given a non-interface vtable slot*/
4636 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4640 cm->slot = cur_slot++;
4642 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4643 vtable [cm->slot] = cm;
4646 /* override non interface methods */
4647 for (i = 0; i < onum; i++) {
4648 MonoMethod *decl = overrides [i*2];
4649 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4650 g_assert (decl->slot != -1);
4651 vtable [decl->slot] = overrides [i*2 + 1];
4652 overrides [i * 2 + 1]->slot = decl->slot;
4654 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4655 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4656 mono_method_full_name (decl, 1), decl,
4657 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4658 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4660 if (mono_security_core_clr_enabled ())
4661 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4666 * If a method occupies more than one place in the vtable, and it is
4667 * overriden, then change the other occurances too.
4672 for (i = 0; i < max_vtsize; ++i)
4674 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4676 cm = g_hash_table_lookup (override_map, vtable [i]);
4681 g_hash_table_destroy (override_map);
4682 override_map = NULL;
4685 g_slist_free (virt_methods);
4686 virt_methods = NULL;
4688 /* Ensure that all vtable slots are filled with concrete instance methods */
4689 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4690 for (i = 0; i < cur_slot; ++i) {
4691 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4692 char *type_name = mono_type_get_full_name (class);
4693 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4694 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));
4696 g_free (method_name);
4702 if (class->generic_class) {
4703 MonoClass *gklass = class->generic_class->container_class;
4705 mono_class_init (gklass);
4707 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4709 /* Check that the vtable_size value computed in mono_class_init () is correct */
4710 if (class->vtable_size)
4711 g_assert (cur_slot == class->vtable_size);
4712 class->vtable_size = cur_slot;
4715 /* Try to share the vtable with our parent. */
4716 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4717 mono_memory_barrier ();
4718 class->vtable = class->parent->vtable;
4720 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4721 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4722 mono_memory_barrier ();
4723 class->vtable = tmp;
4726 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4727 if (mono_print_vtable) {
4730 print_implemented_interfaces (class);
4732 for (i = 0; i <= max_iid; i++)
4733 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4736 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4737 class->vtable_size, icount);
4739 for (i = 0; i < cur_slot; ++i) {
4744 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4745 mono_method_full_name (cm, TRUE));
4751 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4752 class->name, max_iid);
4754 for (i = 0; i < class->interface_count; i++) {
4755 ic = class->interfaces [i];
4756 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4757 mono_class_interface_offset (class, ic),
4758 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4761 for (k = class->parent; k ; k = k->parent) {
4762 for (i = 0; i < k->interface_count; i++) {
4763 ic = k->interfaces [i];
4764 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4765 mono_class_interface_offset (class, ic),
4766 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4772 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4777 char *name = mono_type_get_full_name (class);
4778 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4781 g_hash_table_destroy (override_map);
4783 g_slist_free (virt_methods);
4788 * mono_method_get_vtable_slot:
4790 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4791 * LOCKING: Acquires the loader lock.
4793 * FIXME Use proper MonoError machinery here.
4796 mono_method_get_vtable_slot (MonoMethod *method)
4798 if (method->slot == -1) {
4799 mono_class_setup_vtable (method->klass);
4800 if (method->klass->exception_type)
4802 if (method->slot == -1) {
4806 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4807 g_assert (method->klass->generic_class);
4808 gklass = method->klass->generic_class->container_class;
4809 mono_class_setup_methods (method->klass);
4810 g_assert (method->klass->methods);
4811 for (i = 0; i < method->klass->method.count; ++i) {
4812 if (method->klass->methods [i] == method)
4815 g_assert (i < method->klass->method.count);
4816 g_assert (gklass->methods);
4817 method->slot = gklass->methods [i]->slot;
4819 g_assert (method->slot != -1);
4821 return method->slot;
4825 * mono_method_get_vtable_index:
4828 * Returns the index into the runtime vtable to access the method or,
4829 * in the case of a virtual generic method, the virtual generic method
4830 * thunk. Returns -1 on failure.
4832 * FIXME Use proper MonoError machinery here.
4835 mono_method_get_vtable_index (MonoMethod *method)
4837 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4838 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4839 if (imethod->declaring->is_generic)
4840 return mono_method_get_vtable_slot (imethod->declaring);
4842 return mono_method_get_vtable_slot (method);
4845 static MonoMethod *default_ghc = NULL;
4846 static MonoMethod *default_finalize = NULL;
4847 static int finalize_slot = -1;
4848 static int ghc_slot = -1;
4851 initialize_object_slots (MonoClass *class)
4856 if (class == mono_defaults.object_class) {
4857 mono_class_setup_vtable (class);
4858 for (i = 0; i < class->vtable_size; ++i) {
4859 MonoMethod *cm = class->vtable [i];
4861 if (!strcmp (cm->name, "GetHashCode"))
4863 else if (!strcmp (cm->name, "Finalize"))
4867 g_assert (ghc_slot > 0);
4868 default_ghc = class->vtable [ghc_slot];
4870 g_assert (finalize_slot > 0);
4871 default_finalize = class->vtable [finalize_slot];
4876 MonoMethod *array_method;
4878 } GenericArrayMethodInfo;
4880 static int generic_array_method_num = 0;
4881 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4884 generic_array_methods (MonoClass *class)
4886 int i, count_generic = 0;
4887 GList *list = NULL, *tmp;
4888 if (generic_array_method_num)
4889 return generic_array_method_num;
4890 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4891 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4892 for (i = 0; i < class->parent->method.count; i++) {
4893 MonoMethod *m = class->parent->methods [i];
4894 if (!strncmp (m->name, "InternalArray__", 15)) {
4896 list = g_list_prepend (list, m);
4899 list = g_list_reverse (list);
4900 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4902 for (tmp = list; tmp; tmp = tmp->next) {
4903 const char *mname, *iname;
4905 MonoMethod *m = tmp->data;
4906 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4907 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4909 generic_array_method_info [i].array_method = m;
4910 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4911 iname = "System.Collections.Generic.ICollection`1.";
4912 mname = m->name + 27;
4913 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4914 iname = "System.Collections.Generic.IEnumerable`1.";
4915 mname = m->name + 27;
4916 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4917 iname = "System.Collections.Generic.IReadOnlyList`1.";
4918 mname = m->name + strlen (ireadonlylist_prefix);
4919 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4920 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4921 mname = m->name + strlen (ireadonlycollection_prefix);
4922 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4923 iname = "System.Collections.Generic.IList`1.";
4924 mname = m->name + 15;
4926 g_assert_not_reached ();
4929 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4930 strcpy (name, iname);
4931 strcpy (name + strlen (iname), mname);
4932 generic_array_method_info [i].name = name;
4935 /*g_print ("array generic methods: %d\n", count_generic);*/
4937 generic_array_method_num = count_generic;
4939 return generic_array_method_num;
4943 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4945 MonoGenericContext tmp_context;
4948 tmp_context.class_inst = NULL;
4949 tmp_context.method_inst = iface->generic_class->context.class_inst;
4950 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4952 for (i = 0; i < generic_array_method_num; i++) {
4954 MonoMethod *m = generic_array_method_info [i].array_method;
4955 MonoMethod *inflated;
4957 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4958 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4959 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4964 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4966 int null_length = strlen ("(null)");
4967 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4968 char *s = mono_image_alloc (image, len);
4971 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4972 g_assert (result == len - 1);
4978 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4980 gpointer exception_data = NULL;
4982 switch (error->exception_type) {
4983 case MONO_EXCEPTION_TYPE_LOAD:
4984 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4987 case MONO_EXCEPTION_MISSING_METHOD:
4988 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4991 case MONO_EXCEPTION_MISSING_FIELD: {
4992 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4993 const char *class_name;
4996 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4998 class_name = error->klass->name;
5000 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
5003 g_free ((void*)class_name);
5007 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5010 if (error->ref_only)
5011 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.";
5013 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5015 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
5019 case MONO_EXCEPTION_BAD_IMAGE:
5020 exception_data = error->msg;
5024 g_assert_not_reached ();
5027 mono_class_set_failure (class, error->exception_type, exception_data);
5032 * @class: the class to initialize
5034 * Compute the instance_size, class_size and other infos that cannot be
5035 * computed at mono_class_get() time. Also compute vtable_size if possible.
5036 * Returns TRUE on success or FALSE if there was a problem in loading
5037 * the type (incorrect assemblies, missing assemblies, methods, etc).
5039 * LOCKING: Acquires the loader lock.
5042 mono_class_init (MonoClass *class)
5045 MonoCachedClassInfo cached_info;
5046 gboolean has_cached_info;
5050 /* Double-checking locking pattern */
5051 if (class->inited || class->exception_type)
5052 return class->exception_type == MONO_EXCEPTION_NONE;
5054 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5056 /* We do everything inside the lock to prevent races */
5057 mono_loader_lock ();
5059 if (class->inited || class->exception_type) {
5060 mono_loader_unlock ();
5061 /* Somebody might have gotten in before us */
5062 return class->exception_type == MONO_EXCEPTION_NONE;
5065 if (class->init_pending) {
5066 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5070 class->init_pending = 1;
5072 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5073 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5078 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5079 MonoClass *element_class = class->element_class;
5080 if (!element_class->inited)
5081 mono_class_init (element_class);
5082 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5083 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5088 /* CAS - SecurityAction.InheritanceDemand */
5089 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5090 mono_secman_inheritancedemand_class (class, class->parent);
5093 mono_stats.initialized_class_count++;
5095 if (class->generic_class && !class->generic_class->is_dynamic) {
5096 MonoClass *gklass = class->generic_class->container_class;
5098 mono_stats.generic_class_count++;
5100 class->method = gklass->method;
5101 class->field = gklass->field;
5103 mono_class_init (gklass);
5104 // FIXME: Why is this needed ?
5105 if (!gklass->exception_type)
5106 mono_class_setup_methods (gklass);
5107 if (gklass->exception_type) {
5108 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5112 if (MONO_CLASS_IS_INTERFACE (class))
5113 class->interface_id = mono_get_unique_iid (class);
5116 if (class->parent && !class->parent->inited)
5117 mono_class_init (class->parent);
5119 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5121 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5122 class->nested_classes_inited = TRUE;
5125 * Computes the size used by the fields, and their locations
5127 if (has_cached_info) {
5128 class->instance_size = cached_info.instance_size;
5129 class->sizes.class_size = cached_info.class_size;
5130 class->packing_size = cached_info.packing_size;
5131 class->min_align = cached_info.min_align;
5132 class->blittable = cached_info.blittable;
5133 class->has_references = cached_info.has_references;
5134 class->has_static_refs = cached_info.has_static_refs;
5135 class->no_special_static_fields = cached_info.no_special_static_fields;
5138 if (!class->size_inited){
5139 mono_class_setup_fields (class);
5140 if (class->exception_type || mono_loader_get_last_error ())
5144 /* Initialize arrays */
5146 class->method.count = 3 + (class->rank > 1? 2: 1);
5148 if (class->interface_count) {
5149 int count_generic = generic_array_methods (class);
5150 class->method.count += class->interface_count * count_generic;
5154 mono_class_setup_supertypes (class);
5157 initialize_object_slots (class);
5160 * Initialize the rest of the data without creating a generic vtable if possible.
5161 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5162 * also avoid computing a generic vtable.
5164 if (has_cached_info) {
5166 class->vtable_size = cached_info.vtable_size;
5167 class->has_finalize = cached_info.has_finalize;
5168 class->has_finalize_inited = TRUE;
5169 class->ghcimpl = cached_info.ghcimpl;
5170 class->has_cctor = cached_info.has_cctor;
5171 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5172 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5173 * The first slot if for array with.
5175 static int szarray_vtable_size[2] = { 0 };
5177 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5180 if (!szarray_vtable_size [slot]) {
5181 mono_class_setup_vtable (class);
5182 szarray_vtable_size [slot] = class->vtable_size;
5184 class->vtable_size = szarray_vtable_size[slot];
5186 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5187 MonoClass *gklass = class->generic_class->container_class;
5189 /* Generic instance case */
5190 class->ghcimpl = gklass->ghcimpl;
5191 class->has_cctor = gklass->has_cctor;
5193 mono_class_setup_vtable (gklass);
5194 if (gklass->exception_type) {
5195 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5199 class->vtable_size = gklass->vtable_size;
5203 /* ghcimpl is not currently used
5205 if (class->parent) {
5206 MonoMethod *cmethod = class->vtable [ghc_slot];
5207 if (cmethod->is_inflated)
5208 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5209 if (cmethod == default_ghc) {
5215 /* C# doesn't allow interfaces to have cctors */
5216 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5217 MonoMethod *cmethod = NULL;
5219 if (class->type_token) {
5220 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5221 /* The find_method function ignores the 'flags' argument */
5222 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5223 class->has_cctor = 1;
5225 mono_class_setup_methods (class);
5226 if (class->exception_type)
5229 for (i = 0; i < class->method.count; ++i) {
5230 MonoMethod *method = class->methods [i];
5231 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5232 (strcmp (".cctor", method->name) == 0)) {
5233 class->has_cctor = 1;
5241 if (class->parent) {
5242 int first_iface_slot;
5243 /* This will compute class->parent->vtable_size for some classes */
5244 mono_class_init (class->parent);
5245 if (class->parent->exception_type) {
5246 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5249 if (mono_loader_get_last_error ())
5251 if (!class->parent->vtable_size) {
5252 /* FIXME: Get rid of this somehow */
5253 mono_class_setup_vtable (class->parent);
5254 if (class->parent->exception_type) {
5255 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5258 if (mono_loader_get_last_error ())
5261 first_iface_slot = class->parent->vtable_size;
5262 if (mono_class_need_stelemref_method (class))
5264 setup_interface_offsets (class, first_iface_slot, TRUE);
5266 setup_interface_offsets (class, 0, TRUE);
5269 if (mono_security_core_clr_enabled ())
5270 mono_security_core_clr_check_inheritance (class);
5272 if (mono_loader_get_last_error ()) {
5273 if (class->exception_type == MONO_EXCEPTION_NONE) {
5274 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5276 mono_loader_clear_error ();
5279 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5280 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5285 /* Because of the double-checking locking pattern */
5286 mono_memory_barrier ();
5288 class->init_pending = 0;
5290 mono_loader_unlock ();
5292 return class->exception_type == MONO_EXCEPTION_NONE;
5296 * mono_class_has_finalizer:
5298 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5302 mono_class_has_finalizer (MonoClass *klass)
5304 MonoClass *class = klass;
5305 gboolean has_finalize = FALSE;
5307 if (klass->has_finalize_inited)
5308 return klass->has_finalize;
5310 /* Interfaces and valuetypes are not supposed to have finalizers */
5311 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5312 MonoMethod *cmethod = NULL;
5314 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5315 } else if (class->generic_class) {
5316 MonoClass *gklass = class->generic_class->container_class;
5318 has_finalize = mono_class_has_finalizer (gklass);
5319 } else if (class->parent && class->parent->has_finalize) {
5320 has_finalize = TRUE;
5322 if (class->parent) {
5324 * Can't search in metadata for a method named Finalize, because that
5325 * ignores overrides.
5327 mono_class_setup_vtable (class);
5328 if (class->exception_type || mono_loader_get_last_error ())
5331 cmethod = class->vtable [finalize_slot];
5335 g_assert (class->vtable_size > finalize_slot);
5337 if (class->parent) {
5338 if (cmethod->is_inflated)
5339 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5340 if (cmethod != default_finalize)
5341 has_finalize = TRUE;
5347 mono_image_lock (klass->image);
5349 if (!klass->has_finalize_inited) {
5350 klass->has_finalize = has_finalize ? 1 : 0;
5352 mono_memory_barrier ();
5353 klass->has_finalize_inited = TRUE;
5356 mono_image_unlock (klass->image);
5358 return klass->has_finalize;
5362 mono_is_corlib_image (MonoImage *image)
5364 /* FIXME: allow the dynamic case for our compilers and with full trust */
5365 if (image_is_dynamic (image))
5366 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5368 return image == mono_defaults.corlib;
5372 * LOCKING: this assumes the loader lock is held
5375 mono_class_setup_mono_type (MonoClass *class)
5377 const char *name = class->name;
5378 const char *nspace = class->name_space;
5379 gboolean is_corlib = mono_is_corlib_image (class->image);
5381 class->this_arg.byref = 1;
5382 class->this_arg.data.klass = class;
5383 class->this_arg.type = MONO_TYPE_CLASS;
5384 class->byval_arg.data.klass = class;
5385 class->byval_arg.type = MONO_TYPE_CLASS;
5387 if (is_corlib && !strcmp (nspace, "System")) {
5388 if (!strcmp (name, "ValueType")) {
5390 * do not set the valuetype bit for System.ValueType.
5391 * class->valuetype = 1;
5393 class->blittable = TRUE;
5394 } else if (!strcmp (name, "Enum")) {
5396 * do not set the valuetype bit for System.Enum.
5397 * class->valuetype = 1;
5399 class->valuetype = 0;
5400 class->enumtype = 0;
5401 } else if (!strcmp (name, "Object")) {
5402 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5403 } else if (!strcmp (name, "String")) {
5404 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5405 } else if (!strcmp (name, "TypedReference")) {
5406 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5410 if (class->valuetype) {
5411 int t = MONO_TYPE_VALUETYPE;
5413 if (is_corlib && !strcmp (nspace, "System")) {
5416 if (!strcmp (name, "Boolean")) {
5417 t = MONO_TYPE_BOOLEAN;
5418 } else if (!strcmp(name, "Byte")) {
5420 class->blittable = TRUE;
5424 if (!strcmp (name, "Char")) {
5429 if (!strcmp (name, "Double")) {
5431 class->blittable = TRUE;
5435 if (!strcmp (name, "Int32")) {
5437 class->blittable = TRUE;
5438 } else if (!strcmp(name, "Int16")) {
5440 class->blittable = TRUE;
5441 } else if (!strcmp(name, "Int64")) {
5443 class->blittable = TRUE;
5444 } else if (!strcmp(name, "IntPtr")) {
5446 class->blittable = TRUE;
5450 if (!strcmp (name, "Single")) {
5452 class->blittable = TRUE;
5453 } else if (!strcmp(name, "SByte")) {
5455 class->blittable = TRUE;
5459 if (!strcmp (name, "UInt32")) {
5461 class->blittable = TRUE;
5462 } else if (!strcmp(name, "UInt16")) {
5464 class->blittable = TRUE;
5465 } else if (!strcmp(name, "UInt64")) {
5467 class->blittable = TRUE;
5468 } else if (!strcmp(name, "UIntPtr")) {
5470 class->blittable = TRUE;
5474 if (!strcmp (name, "TypedReference")) {
5475 t = MONO_TYPE_TYPEDBYREF;
5476 class->blittable = TRUE;
5480 if (!strcmp (name, "Void")) {
5488 class->this_arg.type = class->byval_arg.type = t;
5491 if (MONO_CLASS_IS_INTERFACE (class))
5492 class->interface_id = mono_get_unique_iid (class);
5498 * COM initialization is delayed until needed.
5499 * However when a [ComImport] attribute is present on a type it will trigger
5500 * the initialization. This is not a problem unless the BCL being executed
5501 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5504 init_com_from_comimport (MonoClass *class)
5506 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5507 if (mono_security_core_clr_enabled ()) {
5508 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5509 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5510 /* but it can not be made available for application (i.e. user code) since all COM calls
5511 * are considered native calls. In this case we fail with a TypeLoadException (just like
5512 * Silverlight 2 does */
5513 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5518 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5520 #endif /*DISABLE_COM*/
5523 * LOCKING: this assumes the loader lock is held
5526 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5528 gboolean system_namespace;
5529 gboolean is_corlib = mono_is_corlib_image (class->image);
5531 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5533 /* if root of the hierarchy */
5534 if (system_namespace && !strcmp (class->name, "Object")) {
5535 class->parent = NULL;
5536 class->instance_size = sizeof (MonoObject);
5539 if (!strcmp (class->name, "<Module>")) {
5540 class->parent = NULL;
5541 class->instance_size = 0;
5545 if (!MONO_CLASS_IS_INTERFACE (class)) {
5546 /* Imported COM Objects always derive from __ComObject. */
5548 if (MONO_CLASS_IS_IMPORT (class)) {
5549 init_com_from_comimport (class);
5550 if (parent == mono_defaults.object_class)
5551 parent = mono_class_get_com_object_class ();
5555 /* set the parent to something useful and safe, but mark the type as broken */
5556 parent = mono_defaults.object_class;
5557 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5560 class->parent = parent;
5562 if (parent->generic_class && !parent->name) {
5564 * If the parent is a generic instance, we may get
5565 * called before it is fully initialized, especially
5566 * before it has its name.
5571 #ifndef DISABLE_REMOTING
5572 class->marshalbyref = parent->marshalbyref;
5573 class->contextbound = parent->contextbound;
5576 class->delegate = parent->delegate;
5578 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5579 mono_class_set_is_com_object (class);
5581 if (system_namespace) {
5582 #ifndef DISABLE_REMOTING
5583 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5584 class->marshalbyref = 1;
5586 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5587 class->contextbound = 1;
5589 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5590 class->delegate = 1;
5593 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5594 (strcmp (class->parent->name_space, "System") == 0)))
5595 class->valuetype = 1;
5596 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5597 class->valuetype = class->enumtype = 1;
5599 /*class->enumtype = class->parent->enumtype; */
5601 /* initialize com types if COM interfaces are present */
5603 if (MONO_CLASS_IS_IMPORT (class))
5604 init_com_from_comimport (class);
5606 class->parent = NULL;
5612 * mono_class_setup_supertypes:
5615 * Build the data structure needed to make fast type checks work.
5616 * This currently sets two fields in @class:
5617 * - idepth: distance between @class and System.Object in the type
5619 * - supertypes: array of classes: each element has a class in the hierarchy
5620 * starting from @class up to System.Object
5622 * LOCKING: This function is atomic, in case of contention we waste memory.
5625 mono_class_setup_supertypes (MonoClass *class)
5628 MonoClass **supertypes;
5630 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5634 if (class->parent && !class->parent->supertypes)
5635 mono_class_setup_supertypes (class->parent);
5637 class->idepth = class->parent->idepth + 1;
5641 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5642 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5644 if (class->parent) {
5645 supertypes [class->idepth - 1] = class;
5646 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5648 supertypes [0] = class;
5651 mono_atomic_store_release (&class->supertypes, supertypes);
5655 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5657 MonoClass *gtd = (MonoClass*)user_data;
5658 /* Only try to fix generic instances of @gtd */
5659 if (gclass->generic_class->container_class != gtd)
5662 /* Check if the generic instance has no parent. */
5663 if (gtd->parent && !gclass->parent)
5664 mono_generic_class_setup_parent (gclass, gtd);
5670 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5672 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5673 mono_error_set_type_load_class (error, class, msg);
5677 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5679 MonoLoaderError *lerror = mono_loader_get_last_error ();
5682 set_failure_from_loader_error (class, lerror);
5683 mono_error_set_from_loader_error (error);
5687 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5688 mono_error_set_type_load_class (error, class, msg);
5693 * mono_class_create_from_typedef:
5694 * @image: image where the token is valid
5695 * @type_token: typedef token
5696 * @error: used to return any error found while creating the type
5698 * Create the MonoClass* representing the specified type token.
5699 * @type_token must be a TypeDef token.
5701 * FIXME: don't return NULL on failure, just the the caller figure it out.
5704 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5706 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5707 MonoClass *class, *parent = NULL;
5708 guint32 cols [MONO_TYPEDEF_SIZE];
5709 guint32 cols_next [MONO_TYPEDEF_SIZE];
5710 guint tidx = mono_metadata_token_index (type_token);
5711 MonoGenericContext *context = NULL;
5712 const char *name, *nspace;
5714 MonoClass **interfaces;
5715 guint32 field_last, method_last;
5716 guint32 nesting_tokeen;
5718 mono_error_init (error);
5720 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5721 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5722 g_assert (!mono_loader_get_last_error ());
5726 mono_loader_lock ();
5728 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5729 mono_loader_unlock ();
5730 g_assert (!mono_loader_get_last_error ());
5734 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5736 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5737 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5739 class = mono_image_alloc0 (image, sizeof (MonoClass));
5742 class->name_space = nspace;
5744 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5746 class->image = image;
5747 class->type_token = type_token;
5748 class->flags = cols [MONO_TYPEDEF_FLAGS];
5750 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5752 classes_size += sizeof (MonoClass);
5755 * Check whether we're a generic type definition.
5757 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5758 if (class->generic_container) {
5759 class->is_generic = 1;
5760 class->generic_container->owner.klass = class;
5761 context = &class->generic_container->context;
5764 if (class->generic_container)
5765 enable_gclass_recording ();
5767 if (cols [MONO_TYPEDEF_EXTENDS]) {
5769 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5771 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5772 /*WARNING: this must satisfy mono_metadata_type_hash*/
5773 class->this_arg.byref = 1;
5774 class->this_arg.data.klass = class;
5775 class->this_arg.type = MONO_TYPE_CLASS;
5776 class->byval_arg.data.klass = class;
5777 class->byval_arg.type = MONO_TYPE_CLASS;
5779 parent = mono_class_get_checked (image, parent_token, error);
5780 if (parent && context) /* Always inflate */
5781 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5783 if (parent == NULL) {
5784 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5785 goto parent_failure;
5788 for (tmp = parent; tmp; tmp = tmp->parent) {
5790 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5791 goto parent_failure;
5793 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5794 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5795 goto parent_failure;
5800 mono_class_setup_parent (class, parent);
5802 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5803 mono_class_setup_mono_type (class);
5805 if (class->generic_container)
5806 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5809 * This might access class->byval_arg for recursion generated by generic constraints,
5810 * so it has to come after setup_mono_type ().
5812 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5813 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5814 if (!mono_error_ok (error)) {
5815 /*FIXME implement a mono_class_set_failure_from_mono_error */
5816 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5817 mono_loader_unlock ();
5818 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5819 g_assert (!mono_loader_get_last_error ());
5824 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5828 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5832 class->cast_class = class->element_class = class;
5834 if (!class->enumtype) {
5835 if (!mono_metadata_interfaces_from_typedef_full (
5836 image, type_token, &interfaces, &icount, FALSE, context)){
5837 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5838 mono_loader_unlock ();
5839 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5843 class->interfaces = interfaces;
5844 class->interface_count = icount;
5845 class->interfaces_inited = 1;
5848 /*g_print ("Load class %s\n", name);*/
5851 * Compute the field and method lists
5853 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5854 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5856 if (tt->rows > tidx){
5857 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5858 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5859 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5861 field_last = image->tables [MONO_TABLE_FIELD].rows;
5862 method_last = image->tables [MONO_TABLE_METHOD].rows;
5865 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5866 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5867 class->field.count = field_last - class->field.first;
5869 class->field.count = 0;
5871 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5872 class->method.count = method_last - class->method.first;
5874 class->method.count = 0;
5876 /* reserve space to store vector pointer in arrays */
5877 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5878 class->instance_size += 2 * sizeof (gpointer);
5879 g_assert (class->field.count == 0);
5882 if (class->enumtype) {
5883 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5884 if (!enum_basetype) {
5885 /*set it to a default value as the whole runtime can't handle this to be null*/
5886 class->cast_class = class->element_class = mono_defaults.int32_class;
5887 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5888 mono_loader_unlock ();
5889 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5890 g_assert (!mono_loader_get_last_error ());
5893 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5897 * If we're a generic type definition, load the constraints.
5898 * We must do this after the class has been constructed to make certain recursive scenarios
5901 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5902 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)));
5903 mono_loader_unlock ();
5904 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5905 g_assert (!mono_loader_get_last_error ());
5909 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5910 if (!strncmp (name, "Vector", 6))
5911 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");
5914 mono_loader_unlock ();
5916 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5917 g_assert (!mono_loader_get_last_error ());
5922 mono_class_setup_mono_type (class);
5923 mono_loader_unlock ();
5924 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5925 g_assert (!mono_loader_get_last_error ());
5929 /** is klass Nullable<T>? */
5931 mono_class_is_nullable (MonoClass *klass)
5933 return klass->generic_class != NULL &&
5934 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5938 /** if klass is T? return T */
5940 mono_class_get_nullable_param (MonoClass *klass)
5942 g_assert (mono_class_is_nullable (klass));
5943 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5947 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5951 MonoGenericClass *gclass = klass->generic_class;
5953 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5954 if (!mono_error_ok (&error)) {
5955 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5956 klass->parent = mono_defaults.object_class;
5957 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5958 mono_error_cleanup (&error);
5962 mono_class_setup_parent (klass, klass->parent);
5964 if (klass->enumtype) {
5965 klass->cast_class = gtd->cast_class;
5966 klass->element_class = gtd->element_class;
5972 * Create the `MonoClass' for an instantiation of a generic type.
5973 * We only do this if we actually need it.
5976 mono_generic_class_get_class (MonoGenericClass *gclass)
5978 MonoClass *klass, *gklass;
5980 if (gclass->cached_class)
5981 return gclass->cached_class;
5983 mono_loader_lock ();
5984 if (gclass->cached_class) {
5985 mono_loader_unlock ();
5986 return gclass->cached_class;
5989 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5991 gklass = gclass->container_class;
5993 if (record_gclass_instantiation > 0)
5994 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5996 if (gklass->nested_in) {
5997 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5998 klass->nested_in = gklass->nested_in;
6001 klass->name = gklass->name;
6002 klass->name_space = gklass->name_space;
6004 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6006 klass->image = gklass->image;
6007 klass->flags = gklass->flags;
6008 klass->type_token = gklass->type_token;
6009 klass->field.count = gklass->field.count;
6011 klass->is_inflated = 1;
6012 klass->generic_class = gclass;
6014 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
6015 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6016 klass->this_arg.byref = TRUE;
6017 klass->enumtype = gklass->enumtype;
6018 klass->valuetype = gklass->valuetype;
6020 klass->cast_class = klass->element_class = klass;
6022 if (mono_class_is_nullable (klass))
6023 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6026 * We're not interested in the nested classes of a generic instance.
6027 * We use the generic type definition to look for nested classes.
6030 mono_generic_class_setup_parent (klass, gklass);
6032 if (gclass->is_dynamic) {
6035 mono_class_setup_supertypes (klass);
6037 if (klass->enumtype) {
6039 * For enums, gklass->fields might not been set, but instance_size etc. is
6040 * already set in mono_reflection_create_internal_class (). For non-enums,
6041 * these will be computed normally in mono_class_layout_fields ().
6043 klass->instance_size = gklass->instance_size;
6044 klass->sizes.class_size = gklass->sizes.class_size;
6045 mono_memory_barrier ();
6046 klass->size_inited = 1;
6050 mono_memory_barrier ();
6051 gclass->cached_class = klass;
6053 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6055 inflated_classes ++;
6056 inflated_classes_size += sizeof (MonoClass);
6058 mono_loader_unlock ();
6064 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6066 MonoClass *klass, **ptr;
6068 MonoGenericContainer *container = mono_generic_param_owner (param);
6072 image = mono_defaults.corlib;
6074 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6075 classes_size += sizeof (MonoClass);
6078 klass->name = pinfo->name;
6080 int n = mono_generic_param_num (param);
6081 klass->name = mono_image_alloc0 (image, 16);
6082 sprintf ((char*)klass->name, "%d", n);
6087 MonoMethod *omethod = container->owner.method;
6088 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6090 MonoClass *oklass = container->owner.klass;
6091 klass->name_space = oklass ? oklass->name_space : "";
6094 klass->name_space = "";
6097 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6101 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6105 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6106 klass->parent = pinfo->constraints [0];
6108 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6109 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6111 klass->parent = mono_defaults.object_class;
6114 if (count - pos > 0) {
6115 klass->interface_count = count - pos;
6116 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6117 klass->interfaces_inited = TRUE;
6118 for (i = pos; i < count; i++)
6119 klass->interfaces [i - pos] = pinfo->constraints [i];
6122 klass->image = image;
6124 klass->inited = TRUE;
6125 klass->cast_class = klass->element_class = klass;
6126 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6128 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6129 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6130 klass->this_arg.byref = TRUE;
6132 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6133 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6135 /*Init these fields to sane values*/
6136 klass->min_align = 1;
6137 klass->instance_size = sizeof (gpointer);
6138 mono_memory_barrier ();
6139 klass->size_inited = 1;
6141 mono_class_setup_supertypes (klass);
6143 if (count - pos > 0) {
6144 mono_class_setup_vtable (klass->parent);
6145 if (klass->parent->exception_type)
6146 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6148 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6154 #define FAST_CACHE_SIZE 16
6157 * LOCKING: Takes the image lock depending on @take_lock.
6160 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6162 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6163 MonoImage *image = param->image;
6168 if (n < FAST_CACHE_SIZE) {
6170 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6172 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6174 MonoClass *klass = NULL;
6175 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6178 mono_image_lock (image);
6179 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6181 mono_image_unlock (image);
6188 * LOCKING: Image lock (param->image) must be held
6191 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6193 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6194 MonoImage *image = param->image;
6198 if (n < FAST_CACHE_SIZE) {
6200 /* Requires locking to avoid droping an already published class */
6201 if (!image->mvar_cache_fast)
6202 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6203 image->mvar_cache_fast [n] = klass;
6205 if (!image->var_cache_fast)
6206 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6207 image->var_cache_fast [n] = klass;
6210 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6212 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6214 ht = g_hash_table_new (NULL, NULL);
6215 mono_memory_barrier ();
6217 image->mvar_cache_slow = ht;
6219 image->var_cache_slow = ht;
6222 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6227 * LOCKING: Acquires the image lock (@image).
6230 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6232 MonoGenericContainer *container = mono_generic_param_owner (param);
6233 MonoGenericParamInfo *pinfo = NULL;
6234 MonoClass *klass, *klass2;
6237 pinfo = mono_generic_param_info (param);
6238 klass = pinfo->pklass;
6241 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6246 if (!image && container) {
6248 MonoMethod *method = container->owner.method;
6249 image = (method && method->klass) ? method->klass->image : NULL;
6251 MonoClass *klass = container->owner.klass;
6252 // FIXME: 'klass' should not be null
6253 // But, monodis creates GenericContainers without associating a owner to it
6254 image = klass ? klass->image : NULL;
6258 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6260 mono_memory_barrier ();
6262 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6263 image = mono_defaults.corlib;
6265 mono_image_lock (image);
6267 klass2 = pinfo->pklass;
6269 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6275 pinfo->pklass = klass;
6277 set_anon_gparam_class (param, is_mvar, klass);
6279 mono_image_unlock (image);
6281 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6283 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6285 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6291 mono_ptr_class_get (MonoType *type)
6294 MonoClass *el_class;
6298 el_class = mono_class_from_mono_type (type);
6299 image = el_class->image;
6301 mono_image_lock (image);
6302 if (image->ptr_cache) {
6303 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6304 mono_image_unlock (image);
6308 mono_image_unlock (image);
6310 result = mono_image_alloc0 (image, sizeof (MonoClass));
6312 classes_size += sizeof (MonoClass);
6314 result->parent = NULL; /* no parent for PTR types */
6315 result->name_space = el_class->name_space;
6316 name = g_strdup_printf ("%s*", el_class->name);
6317 result->name = mono_image_strdup (image, name);
6320 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6322 result->image = el_class->image;
6323 result->inited = TRUE;
6324 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6325 /* Can pointers get boxed? */
6326 result->instance_size = sizeof (gpointer);
6327 result->cast_class = result->element_class = el_class;
6328 result->blittable = TRUE;
6330 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6331 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6332 result->this_arg.byref = TRUE;
6334 mono_class_setup_supertypes (result);
6336 mono_image_lock (image);
6337 if (image->ptr_cache) {
6339 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6340 mono_image_unlock (image);
6341 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6345 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6347 g_hash_table_insert (image->ptr_cache, el_class, result);
6348 mono_image_unlock (image);
6350 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6356 mono_fnptr_class_get (MonoMethodSignature *sig)
6359 static GHashTable *ptr_hash = NULL;
6361 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6363 mono_loader_lock ();
6366 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6368 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6369 mono_loader_unlock ();
6372 result = g_new0 (MonoClass, 1);
6374 result->parent = NULL; /* no parent for PTR types */
6375 result->name_space = "System";
6376 result->name = "MonoFNPtrFakeClass";
6378 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6380 result->image = mono_defaults.corlib; /* need to fix... */
6381 result->inited = TRUE;
6382 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6383 /* Can pointers get boxed? */
6384 result->instance_size = sizeof (gpointer);
6385 result->cast_class = result->element_class = result;
6386 result->blittable = TRUE;
6388 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6389 result->this_arg.data.method = result->byval_arg.data.method = sig;
6390 result->this_arg.byref = TRUE;
6391 result->blittable = TRUE;
6393 mono_class_setup_supertypes (result);
6395 g_hash_table_insert (ptr_hash, sig, result);
6397 mono_loader_unlock ();
6399 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6405 mono_class_from_mono_type (MonoType *type)
6407 switch (type->type) {
6408 case MONO_TYPE_OBJECT:
6409 return type->data.klass? type->data.klass: mono_defaults.object_class;
6410 case MONO_TYPE_VOID:
6411 return type->data.klass? type->data.klass: mono_defaults.void_class;
6412 case MONO_TYPE_BOOLEAN:
6413 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6414 case MONO_TYPE_CHAR:
6415 return type->data.klass? type->data.klass: mono_defaults.char_class;
6417 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6419 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6421 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6423 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6425 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6427 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6429 return type->data.klass? type->data.klass: mono_defaults.int_class;
6431 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6433 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6435 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6437 return type->data.klass? type->data.klass: mono_defaults.single_class;
6439 return type->data.klass? type->data.klass: mono_defaults.double_class;
6440 case MONO_TYPE_STRING:
6441 return type->data.klass? type->data.klass: mono_defaults.string_class;
6442 case MONO_TYPE_TYPEDBYREF:
6443 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6444 case MONO_TYPE_ARRAY:
6445 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6447 return mono_ptr_class_get (type->data.type);
6448 case MONO_TYPE_FNPTR:
6449 return mono_fnptr_class_get (type->data.method);
6450 case MONO_TYPE_SZARRAY:
6451 return mono_array_class_get (type->data.klass, 1);
6452 case MONO_TYPE_CLASS:
6453 case MONO_TYPE_VALUETYPE:
6454 return type->data.klass;
6455 case MONO_TYPE_GENERICINST:
6456 return mono_generic_class_get_class (type->data.generic_class);
6458 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6459 case MONO_TYPE_MVAR:
6460 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6462 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6463 g_assert_not_reached ();
6470 * mono_type_retrieve_from_typespec
6471 * @image: context where the image is created
6472 * @type_spec: typespec token
6473 * @context: the generic context used to evaluate generic instantiations in
6476 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6478 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6480 *did_inflate = FALSE;
6485 if (context && (context->class_inst || context->method_inst)) {
6486 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6488 if (!mono_error_ok (error)) {
6489 g_assert (!mono_loader_get_last_error ());
6495 *did_inflate = TRUE;
6502 * mono_class_create_from_typespec
6503 * @image: context where the image is created
6504 * @type_spec: typespec token
6505 * @context: the generic context used to evaluate generic instantiations in
6508 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6511 gboolean inflated = FALSE;
6512 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6513 if (!mono_error_ok (error))
6515 ret = mono_class_from_mono_type (t);
6517 mono_metadata_free_type (t);
6522 * mono_bounded_array_class_get:
6523 * @element_class: element class
6524 * @rank: the dimension of the array class
6525 * @bounded: whenever the array has non-zero bounds
6527 * Returns: a class object describing the array with element type @element_type and
6531 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6535 MonoClass *parent = NULL;
6536 GSList *list, *rootlist = NULL;
6539 gboolean corlib_type = FALSE;
6541 g_assert (rank <= 255);
6544 /* bounded only matters for one-dimensional arrays */
6547 image = eclass->image;
6549 if (rank == 1 && !bounded) {
6551 * This case is very frequent not just during compilation because of calls
6552 * from mono_class_from_mono_type (), mono_array_new (),
6553 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6555 mono_mutex_lock (&image->szarray_cache_lock);
6556 if (!image->szarray_cache)
6557 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6558 class = g_hash_table_lookup (image->szarray_cache, eclass);
6559 mono_mutex_unlock (&image->szarray_cache_lock);
6563 mono_loader_lock ();
6565 mono_loader_lock ();
6567 if (!image->array_cache)
6568 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6570 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6571 for (; list; list = list->next) {
6573 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6574 mono_loader_unlock ();
6581 /* for the building corlib use System.Array from it */
6582 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6583 parent = mono_class_from_name (image, "System", "Array");
6586 parent = mono_defaults.array_class;
6587 if (!parent->inited)
6588 mono_class_init (parent);
6591 class = mono_image_alloc0 (image, sizeof (MonoClass));
6593 class->image = image;
6594 class->name_space = eclass->name_space;
6595 nsize = strlen (eclass->name);
6596 name = g_malloc (nsize + 2 + rank + 1);
6597 memcpy (name, eclass->name, nsize);
6600 memset (name + nsize + 1, ',', rank - 1);
6602 name [nsize + rank] = '*';
6603 name [nsize + rank + bounded] = ']';
6604 name [nsize + rank + bounded + 1] = 0;
6605 class->name = mono_image_strdup (image, name);
6608 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6610 classes_size += sizeof (MonoClass);
6612 class->type_token = 0;
6613 /* all arrays are marked serializable and sealed, bug #42779 */
6614 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6615 class->parent = parent;
6616 class->instance_size = mono_class_instance_size (class->parent);
6618 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6619 /*Arrays of those two types are invalid.*/
6620 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6621 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6622 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6623 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6624 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6626 /* element_size -1 is ok as this is not an instantitable type*/
6627 class->sizes.element_size = -1;
6629 class->sizes.element_size = mono_class_array_element_size (eclass);
6631 mono_class_setup_supertypes (class);
6633 if (eclass->generic_class)
6634 mono_class_init (eclass);
6635 if (!eclass->size_inited)
6636 mono_class_setup_fields (eclass);
6637 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6638 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6640 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6644 if (eclass->enumtype)
6645 class->cast_class = eclass->element_class;
6647 class->cast_class = eclass;
6649 switch (class->cast_class->byval_arg.type) {
6651 class->cast_class = mono_defaults.byte_class;
6654 class->cast_class = mono_defaults.int16_class;
6657 #if SIZEOF_VOID_P == 4
6661 class->cast_class = mono_defaults.int32_class;
6664 #if SIZEOF_VOID_P == 8
6668 class->cast_class = mono_defaults.int64_class;
6672 class->element_class = eclass;
6674 if ((rank > 1) || bounded) {
6675 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6676 class->byval_arg.type = MONO_TYPE_ARRAY;
6677 class->byval_arg.data.array = at;
6678 at->eklass = eclass;
6680 /* FIXME: complete.... */
6682 class->byval_arg.type = MONO_TYPE_SZARRAY;
6683 class->byval_arg.data.klass = eclass;
6685 class->this_arg = class->byval_arg;
6686 class->this_arg.byref = 1;
6691 class->generic_container = eclass->generic_container;
6693 if (rank == 1 && !bounded) {
6694 MonoClass *prev_class;
6696 mono_mutex_lock (&image->szarray_cache_lock);
6697 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6699 /* Someone got in before us */
6702 g_hash_table_insert (image->szarray_cache, eclass, class);
6703 mono_mutex_unlock (&image->szarray_cache_lock);
6705 list = g_slist_append (rootlist, class);
6706 g_hash_table_insert (image->array_cache, eclass, list);
6709 mono_loader_unlock ();
6711 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6717 * mono_array_class_get:
6718 * @element_class: element class
6719 * @rank: the dimension of the array class
6721 * Returns: a class object describing the array with element type @element_type and
6725 mono_array_class_get (MonoClass *eclass, guint32 rank)
6727 return mono_bounded_array_class_get (eclass, rank, FALSE);
6731 * mono_class_instance_size:
6734 * Returns: the size of an object instance
6737 mono_class_instance_size (MonoClass *klass)
6739 if (!klass->size_inited)
6740 mono_class_init (klass);
6742 return klass->instance_size;
6746 * mono_class_min_align:
6749 * Returns: minimm alignment requirements
6752 mono_class_min_align (MonoClass *klass)
6754 if (!klass->size_inited)
6755 mono_class_init (klass);
6757 return klass->min_align;
6761 * mono_class_value_size:
6764 * This function is used for value types, and return the
6765 * space and the alignment to store that kind of value object.
6767 * Returns: the size of a value of kind @klass
6770 mono_class_value_size (MonoClass *klass, guint32 *align)
6774 /* fixme: check disable, because we still have external revereces to
6775 * mscorlib and Dummy Objects
6777 /*g_assert (klass->valuetype);*/
6779 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6782 *align = klass->min_align;
6788 * mono_class_data_size:
6791 * Returns: the size of the static class data
6794 mono_class_data_size (MonoClass *klass)
6797 mono_class_init (klass);
6798 /* This can happen with dynamically created types */
6799 if (!klass->fields_inited)
6800 mono_class_setup_fields_locking (klass);
6802 /* in arrays, sizes.class_size is unioned with element_size
6803 * and arrays have no static fields
6807 return klass->sizes.class_size;
6811 * Auxiliary routine to mono_class_get_field
6813 * Takes a field index instead of a field token.
6815 static MonoClassField *
6816 mono_class_get_field_idx (MonoClass *class, int idx)
6818 mono_class_setup_fields_locking (class);
6819 if (class->exception_type)
6823 if (class->image->uncompressed_metadata) {
6825 * class->field.first points to the FieldPtr table, while idx points into the
6826 * Field table, so we have to do a search.
6828 /*FIXME this is broken for types with multiple fields with the same name.*/
6829 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6832 for (i = 0; i < class->field.count; ++i)
6833 if (mono_field_get_name (&class->fields [i]) == name)
6834 return &class->fields [i];
6835 g_assert_not_reached ();
6837 if (class->field.count) {
6838 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6839 return &class->fields [idx - class->field.first];
6843 class = class->parent;
6849 * mono_class_get_field:
6850 * @class: the class to lookup the field.
6851 * @field_token: the field token
6853 * Returns: A MonoClassField representing the type and offset of
6854 * the field, or a NULL value if the field does not belong to this
6858 mono_class_get_field (MonoClass *class, guint32 field_token)
6860 int idx = mono_metadata_token_index (field_token);
6862 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6864 return mono_class_get_field_idx (class, idx - 1);
6868 * mono_class_get_field_from_name:
6869 * @klass: the class to lookup the field.
6870 * @name: the field name
6872 * Search the class @klass and it's parents for a field with the name @name.
6874 * Returns: the MonoClassField pointer of the named field or NULL
6877 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6879 return mono_class_get_field_from_name_full (klass, name, NULL);
6883 * mono_class_get_field_from_name_full:
6884 * @klass: the class to lookup the field.
6885 * @name: the field name
6886 * @type: the type of the fields. This optional.
6888 * Search the class @klass and it's parents for a field with the name @name and type @type.
6890 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6891 * of its generic type definition.
6893 * Returns: the MonoClassField pointer of the named field or NULL
6896 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6900 mono_class_setup_fields_locking (klass);
6901 if (klass->exception_type)
6905 for (i = 0; i < klass->field.count; ++i) {
6906 MonoClassField *field = &klass->fields [i];
6908 if (strcmp (name, mono_field_get_name (field)) != 0)
6912 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6913 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6918 klass = klass->parent;
6924 * mono_class_get_field_token:
6925 * @field: the field we need the token of
6927 * Get the token of a field. Note that the tokesn is only valid for the image
6928 * the field was loaded from. Don't use this function for fields in dynamic types.
6930 * Returns: the token representing the field in the image it was loaded from.
6933 mono_class_get_field_token (MonoClassField *field)
6935 MonoClass *klass = field->parent;
6938 mono_class_setup_fields_locking (klass);
6943 for (i = 0; i < klass->field.count; ++i) {
6944 if (&klass->fields [i] == field) {
6945 int idx = klass->field.first + i + 1;
6947 if (klass->image->uncompressed_metadata)
6948 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6949 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6952 klass = klass->parent;
6955 g_assert_not_reached ();
6960 mono_field_get_index (MonoClassField *field)
6962 int index = field - field->parent->fields;
6964 g_assert (index >= 0 && index < field->parent->field.count);
6970 * mono_class_get_field_default_value:
6972 * Return the default value of the field as a pointer into the metadata blob.
6975 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6978 guint32 constant_cols [MONO_CONSTANT_SIZE];
6980 MonoClass *klass = field->parent;
6982 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6984 if (!klass->ext || !klass->ext->field_def_values) {
6985 MonoFieldDefaultValue *def_values;
6987 mono_class_alloc_ext (klass);
6989 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6991 mono_image_lock (klass->image);
6992 mono_memory_barrier ();
6993 if (!klass->ext->field_def_values)
6994 klass->ext->field_def_values = def_values;
6995 mono_image_unlock (klass->image);
6998 field_index = mono_field_get_index (field);
7000 if (!klass->ext->field_def_values [field_index].data) {
7001 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7005 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7007 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7008 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
7009 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7012 *def_type = klass->ext->field_def_values [field_index].def_type;
7013 return klass->ext->field_def_values [field_index].data;
7017 mono_property_get_index (MonoProperty *prop)
7019 int index = prop - prop->parent->ext->properties;
7021 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7027 * mono_class_get_property_default_value:
7029 * Return the default value of the field as a pointer into the metadata blob.
7032 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7035 guint32 constant_cols [MONO_CONSTANT_SIZE];
7036 MonoClass *klass = property->parent;
7038 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7040 * We don't cache here because it is not used by C# so it's quite rare, but
7041 * we still do the lookup in klass->ext because that is where the data
7042 * is stored for dynamic assemblies.
7045 if (image_is_dynamic (klass->image)) {
7046 int prop_index = mono_property_get_index (property);
7047 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7048 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7049 return klass->ext->prop_def_values [prop_index].data;
7053 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7057 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7058 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7059 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7063 mono_class_get_event_token (MonoEvent *event)
7065 MonoClass *klass = event->parent;
7070 for (i = 0; i < klass->ext->event.count; ++i) {
7071 if (&klass->ext->events [i] == event)
7072 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7075 klass = klass->parent;
7078 g_assert_not_reached ();
7083 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7087 gpointer iter = NULL;
7088 while ((p = mono_class_get_properties (klass, &iter))) {
7089 if (! strcmp (name, p->name))
7092 klass = klass->parent;
7098 mono_class_get_property_token (MonoProperty *prop)
7100 MonoClass *klass = prop->parent;
7104 gpointer iter = NULL;
7105 while ((p = mono_class_get_properties (klass, &iter))) {
7106 if (&klass->ext->properties [i] == prop)
7107 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7111 klass = klass->parent;
7114 g_assert_not_reached ();
7119 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7121 const char *name, *nspace;
7122 if (image_is_dynamic (image))
7123 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7125 switch (type_token & 0xff000000){
7126 case MONO_TOKEN_TYPE_DEF: {
7127 guint32 cols [MONO_TYPEDEF_SIZE];
7128 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7129 guint tidx = mono_metadata_token_index (type_token);
7131 if (tidx > tt->rows)
7132 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7134 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7135 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7136 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7137 if (strlen (nspace) == 0)
7138 return g_strdup_printf ("%s", name);
7140 return g_strdup_printf ("%s.%s", nspace, name);
7143 case MONO_TOKEN_TYPE_REF: {
7145 guint32 cols [MONO_TYPEREF_SIZE];
7146 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7147 guint tidx = mono_metadata_token_index (type_token);
7150 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7152 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7153 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7154 mono_error_cleanup (&error);
7158 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7159 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7160 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7161 if (strlen (nspace) == 0)
7162 return g_strdup_printf ("%s", name);
7164 return g_strdup_printf ("%s.%s", nspace, name);
7167 case MONO_TOKEN_TYPE_SPEC:
7168 return g_strdup_printf ("Typespec 0x%08x", type_token);
7170 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7175 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7177 if (image_is_dynamic (image))
7178 return g_strdup_printf ("DynamicAssembly %s", image->name);
7180 switch (type_token & 0xff000000){
7181 case MONO_TOKEN_TYPE_DEF:
7182 if (image->assembly)
7183 return mono_stringify_assembly_name (&image->assembly->aname);
7184 else if (image->assembly_name)
7185 return g_strdup (image->assembly_name);
7186 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7187 case MONO_TOKEN_TYPE_REF: {
7189 MonoAssemblyName aname;
7190 guint32 cols [MONO_TYPEREF_SIZE];
7191 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7192 guint32 idx = mono_metadata_token_index (type_token);
7195 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7197 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7198 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7199 mono_error_cleanup (&error);
7202 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7204 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7205 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7206 case MONO_RESOLUTION_SCOPE_MODULE:
7208 return g_strdup ("");
7209 case MONO_RESOLUTION_SCOPE_MODULEREF:
7211 return g_strdup ("");
7212 case MONO_RESOLUTION_SCOPE_TYPEREF:
7214 return g_strdup ("");
7215 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7216 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7217 return mono_stringify_assembly_name (&aname);
7219 g_assert_not_reached ();
7223 case MONO_TOKEN_TYPE_SPEC:
7225 return g_strdup ("");
7227 g_assert_not_reached ();
7234 * mono_class_get_full:
7235 * @image: the image where the class resides
7236 * @type_token: the token for the class
7237 * @context: the generic context used to evaluate generic instantiations in
7238 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7240 * Returns: the MonoClass that represents @type_token in @image
7243 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7247 class = mono_class_get_checked (image, type_token, &error);
7249 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7250 class = mono_class_inflate_generic_class_checked (class, context, &error);
7253 mono_loader_set_error_from_mono_error (&error);
7254 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7261 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7265 mono_error_init (error);
7266 class = mono_class_get_checked (image, type_token, error);
7268 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7269 class = mono_class_inflate_generic_class_checked (class, context, error);
7274 * mono_class_get_checked:
7275 * @image: the image where the class resides
7276 * @type_token: the token for the class
7277 * @error: error object to return any error
7279 * Returns: the MonoClass that represents @type_token in @image
7282 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7284 MonoClass *class = NULL;
7286 mono_error_init (error);
7288 if (image_is_dynamic (image)) {
7289 int table = mono_metadata_token_table (type_token);
7291 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7292 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7295 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7299 switch (type_token & 0xff000000){
7300 case MONO_TOKEN_TYPE_DEF:
7301 class = mono_class_create_from_typedef (image, type_token, error);
7303 case MONO_TOKEN_TYPE_REF:
7304 class = mono_class_from_typeref_checked (image, type_token, error);
7306 case MONO_TOKEN_TYPE_SPEC:
7307 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7310 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7314 /* Generic case, should be avoided for when a better error is possible. */
7315 if (!class && mono_error_ok (error)) {
7316 char *name = mono_class_name_from_token (image, type_token);
7317 char *assembly = mono_assembly_name_from_token (image, type_token);
7318 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7326 * mono_type_get_checked:
7327 * @image: the image where the type resides
7328 * @type_token: the token for the type
7329 * @context: the generic context used to evaluate generic instantiations in
7330 * @error: Error handling context
7332 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7334 * Returns: the MonoType that represents @type_token in @image
7337 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7339 MonoType *type = NULL;
7340 gboolean inflated = FALSE;
7342 mono_error_init (error);
7344 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7345 if (image_is_dynamic (image))
7346 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7348 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7349 MonoClass *class = mono_class_get_checked (image, type_token, error);
7352 g_assert (!mono_loader_get_last_error ());
7357 return mono_class_get_type (class);
7360 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7363 g_assert (!mono_loader_get_last_error ());
7368 MonoType *tmp = type;
7369 type = mono_class_get_type (mono_class_from_mono_type (type));
7370 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7371 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7372 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7374 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7376 if (type->type != tmp->type)
7379 mono_metadata_free_type (tmp);
7386 mono_class_get (MonoImage *image, guint32 type_token)
7388 return mono_class_get_full (image, type_token, NULL);
7392 * mono_image_init_name_cache:
7394 * Initializes the class name cache stored in image->name_cache.
7396 * LOCKING: Acquires the corresponding image lock.
7399 mono_image_init_name_cache (MonoImage *image)
7401 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7402 guint32 cols [MONO_TYPEDEF_SIZE];
7405 guint32 i, visib, nspace_index;
7406 GHashTable *name_cache2, *nspace_table;
7408 mono_image_lock (image);
7410 if (image->name_cache) {
7411 mono_image_unlock (image);
7415 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7417 if (image_is_dynamic (image)) {
7418 mono_image_unlock (image);
7422 /* Temporary hash table to avoid lookups in the nspace_table */
7423 name_cache2 = g_hash_table_new (NULL, NULL);
7425 for (i = 1; i <= t->rows; ++i) {
7426 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7427 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7429 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7430 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7432 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7434 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7435 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7437 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7438 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7439 if (!nspace_table) {
7440 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7441 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7442 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7445 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7448 /* Load type names from EXPORTEDTYPES table */
7450 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7451 guint32 cols [MONO_EXP_TYPE_SIZE];
7454 for (i = 0; i < t->rows; ++i) {
7455 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7456 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7457 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7459 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7460 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7461 if (!nspace_table) {
7462 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7463 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7464 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7467 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7471 g_hash_table_destroy (name_cache2);
7472 mono_image_unlock (image);
7475 /*FIXME Only dynamic assemblies should allow this operation.*/
7477 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7478 const char *name, guint32 index)
7480 GHashTable *nspace_table;
7481 GHashTable *name_cache;
7484 mono_image_lock (image);
7486 if (!image->name_cache)
7487 mono_image_init_name_cache (image);
7489 name_cache = image->name_cache;
7490 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7491 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7492 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7495 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7496 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7498 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7500 mono_image_unlock (image);
7509 find_nocase (gpointer key, gpointer value, gpointer user_data)
7511 char *name = (char*)key;
7512 FindUserData *data = (FindUserData*)user_data;
7514 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7515 data->value = value;
7519 * mono_class_from_name_case:
7520 * @image: The MonoImage where the type is looked up in
7521 * @name_space: the type namespace
7522 * @name: the type short name.
7523 * @deprecated: use the _checked variant
7525 * Obtains a MonoClass with a given namespace and a given name which
7526 * is located in the given MonoImage. The namespace and name
7527 * lookups are case insensitive.
7530 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7533 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7534 g_assert (!mono_error_ok (&error));
7539 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7541 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7542 guint32 cols [MONO_TYPEDEF_SIZE];
7547 mono_error_init (error);
7549 if (image_is_dynamic (image)) {
7551 FindUserData user_data;
7553 mono_image_lock (image);
7555 if (!image->name_cache)
7556 mono_image_init_name_cache (image);
7558 user_data.key = name_space;
7559 user_data.value = NULL;
7560 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7562 if (user_data.value) {
7563 GHashTable *nspace_table = (GHashTable*)user_data.value;
7565 user_data.key = name;
7566 user_data.value = NULL;
7568 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7570 if (user_data.value)
7571 token = GPOINTER_TO_UINT (user_data.value);
7574 mono_image_unlock (image);
7577 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7583 /* add a cache if needed */
7584 for (i = 1; i <= t->rows; ++i) {
7585 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7586 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7588 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7589 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7591 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7593 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7594 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7595 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7596 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7602 return_nested_in (MonoClass *class, char *nested)
7605 char *s = strchr (nested, '/');
7606 gpointer iter = NULL;
7613 while ((found = mono_class_get_nested_types (class, &iter))) {
7614 if (strcmp (found->name, nested) == 0) {
7616 return return_nested_in (found, s);
7624 search_modules (MonoImage *image, const char *name_space, const char *name)
7626 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7627 MonoImage *file_image;
7632 * The EXPORTEDTYPES table only contains public types, so have to search the
7634 * Note: image->modules contains the contents of the MODULEREF table, while
7635 * the real module list is in the FILE table.
7637 for (i = 0; i < file_table->rows; i++) {
7638 guint32 cols [MONO_FILE_SIZE];
7639 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7640 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7643 file_image = mono_image_load_file_for_image (image, i + 1);
7645 class = mono_class_from_name (file_image, name_space, name);
7655 * mono_class_from_name:
7656 * @image: The MonoImage where the type is looked up in
7657 * @name_space: the type namespace
7658 * @name: the type short name.
7660 * Obtains a MonoClass with a given namespace and a given name which
7661 * is located in the given MonoImage.
7663 * To reference nested classes, use the "/" character as a separator.
7664 * For example use "Foo/Bar" to reference the class Bar that is nested
7665 * inside Foo, like this: "class Foo { class Bar {} }".
7668 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7670 GHashTable *nspace_table;
7671 MonoImage *loaded_image;
7678 if ((nested = strchr (name, '/'))) {
7679 int pos = nested - name;
7680 int len = strlen (name);
7683 memcpy (buf, name, len + 1);
7685 nested = buf + pos + 1;
7689 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7690 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7691 gboolean res = get_class_from_name (image, name_space, name, &class);
7694 class = search_modules (image, name_space, name);
7696 return class ? return_nested_in (class, nested) : NULL;
7702 mono_image_lock (image);
7704 if (!image->name_cache)
7705 mono_image_init_name_cache (image);
7707 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7710 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7712 mono_image_unlock (image);
7714 if (!token && image_is_dynamic (image) && image->modules) {
7715 /* Search modules as well */
7716 for (i = 0; i < image->module_count; ++i) {
7717 MonoImage *module = image->modules [i];
7719 class = mono_class_from_name (module, name_space, name);
7726 class = search_modules (image, name_space, name);
7734 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7735 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7736 guint32 cols [MONO_EXP_TYPE_SIZE];
7739 idx = mono_metadata_token_index (token);
7741 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7743 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7744 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7745 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7748 class = mono_class_from_name (loaded_image, name_space, name);
7750 return return_nested_in (class, nested);
7752 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7753 guint32 assembly_idx;
7755 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7757 mono_assembly_load_reference (image, assembly_idx - 1);
7758 g_assert (image->references [assembly_idx - 1]);
7759 if (image->references [assembly_idx - 1] == (gpointer)-1)
7762 /* FIXME: Cycle detection */
7763 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7765 g_error ("not yet implemented");
7769 token = MONO_TOKEN_TYPE_DEF | token;
7771 class = mono_class_get (image, token);
7773 return return_nested_in (class, nested);
7778 * mono_class_is_subclass_of:
7779 * @klass: class to probe if it is a subclass of another one
7780 * @klassc: the class we suspect is the base class
7781 * @check_interfaces: whether we should perform interface checks
7783 * This method determines whether @klass is a subclass of @klassc.
7785 * If the @check_interfaces flag is set, then if @klassc is an interface
7786 * this method return true if the @klass implements the interface or
7787 * if @klass is an interface, if one of its base classes is @klass.
7789 * If @check_interfaces is false then, then if @klass is not an interface
7790 * then it returns true if the @klass is a subclass of @klassc.
7792 * if @klass is an interface and @klassc is System.Object, then this function
7797 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7798 gboolean check_interfaces)
7800 /*FIXME test for interfaces with variant generic arguments*/
7802 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7803 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7805 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7808 for (i = 0; i < klass->interface_count; i ++) {
7809 MonoClass *ic = klass->interfaces [i];
7814 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7819 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7822 if (klassc == mono_defaults.object_class)
7829 mono_type_is_generic_argument (MonoType *type)
7831 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7835 mono_class_has_variant_generic_params (MonoClass *klass)
7838 MonoGenericContainer *container;
7840 if (!klass->generic_class)
7843 container = klass->generic_class->container_class->generic_container;
7845 for (i = 0; i < container->type_argc; ++i)
7846 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7853 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7855 if (target == candidate)
7858 if (check_for_reference_conv &&
7859 mono_type_is_generic_argument (&target->byval_arg) &&
7860 mono_type_is_generic_argument (&candidate->byval_arg)) {
7861 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7862 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7864 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7867 if (!mono_class_is_assignable_from (target, candidate))
7873 * @container the generic container from the GTD
7874 * @klass: the class to be assigned to
7875 * @oklass: the source class
7877 * Both klass and oklass must be instances of the same generic interface.
7878 * Return true if @klass can be assigned to a @klass variable
7881 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7884 MonoType **klass_argv, **oklass_argv;
7885 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7886 MonoGenericContainer *container = klass_gtd->generic_container;
7888 if (klass == oklass)
7891 /*Viable candidates are instances of the same generic interface*/
7892 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7895 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7896 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7898 for (j = 0; j < container->type_argc; ++j) {
7899 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7900 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7902 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7906 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7907 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7909 if (param1_class != param2_class) {
7910 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7911 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7913 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7914 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7924 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7926 MonoGenericParam *gparam, *ogparam;
7927 MonoGenericParamInfo *tinfo, *cinfo;
7928 MonoClass **candidate_class;
7929 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7932 if (target == candidate)
7934 if (target->byval_arg.type != candidate->byval_arg.type)
7937 gparam = target->byval_arg.data.generic_param;
7938 ogparam = candidate->byval_arg.data.generic_param;
7939 tinfo = mono_generic_param_info (gparam);
7940 cinfo = mono_generic_param_info (ogparam);
7942 class_constraint_satisfied = FALSE;
7943 valuetype_constraint_satisfied = FALSE;
7945 /*candidate must have a super set of target's special constraints*/
7946 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7947 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7949 if (cinfo->constraints) {
7950 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7951 MonoClass *cc = *candidate_class;
7953 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7954 class_constraint_satisfied = TRUE;
7955 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7956 valuetype_constraint_satisfied = TRUE;
7959 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7960 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7962 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7964 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7966 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7967 valuetype_constraint_satisfied)) {
7972 /*candidate type constraints must be a superset of target's*/
7973 if (tinfo->constraints) {
7974 MonoClass **target_class;
7975 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7976 MonoClass *tc = *target_class;
7979 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7980 * check it's constraints since it satisfy the constraint by itself.
7982 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7985 if (!cinfo->constraints)
7988 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7989 MonoClass *cc = *candidate_class;
7991 if (mono_class_is_assignable_from (tc, cc))
7995 * This happens when we have the following:
7997 * Bar<K> where K : IFace
7998 * Foo<T, U> where T : U where U : IFace
8000 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8003 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8004 if (mono_gparam_is_assignable_from (target, cc))
8008 if (!*candidate_class)
8013 /*candidate itself must have a constraint that satisfy target*/
8014 if (cinfo->constraints) {
8015 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8016 MonoClass *cc = *candidate_class;
8017 if (mono_class_is_assignable_from (target, cc))
8025 * mono_class_is_assignable_from:
8026 * @klass: the class to be assigned to
8027 * @oklass: the source class
8029 * Return: true if an instance of object oklass can be assigned to an
8030 * instance of object @klass
8033 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8035 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8037 mono_class_init (klass);
8039 if (!oklass->inited)
8040 mono_class_init (oklass);
8042 if (klass->exception_type || oklass->exception_type)
8045 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8046 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8048 return mono_gparam_is_assignable_from (klass, oklass);
8051 if (MONO_CLASS_IS_INTERFACE (klass)) {
8052 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8053 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8054 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8058 for (i = 0; constraints [i]; ++i) {
8059 if (mono_class_is_assignable_from (klass, constraints [i]))
8067 /* interface_offsets might not be set for dynamic classes */
8068 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8070 * oklass might be a generic type parameter but they have
8071 * interface_offsets set.
8073 return mono_reflection_call_is_assignable_to (oklass, klass);
8074 if (!oklass->interface_bitmap)
8075 /* Happens with generic instances of not-yet created dynamic types */
8077 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8080 if (mono_class_has_variant_generic_params (klass)) {
8083 mono_class_setup_interfaces (oklass, &error);
8084 if (!mono_error_ok (&error)) {
8085 mono_error_cleanup (&error);
8089 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8090 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8091 MonoClass *iface = oklass->interfaces_packed [i];
8093 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8098 } else if (klass->delegate) {
8099 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8101 }else if (klass->rank) {
8102 MonoClass *eclass, *eoclass;
8104 if (oklass->rank != klass->rank)
8107 /* vectors vs. one dimensional arrays */
8108 if (oklass->byval_arg.type != klass->byval_arg.type)
8111 eclass = klass->cast_class;
8112 eoclass = oklass->cast_class;
8115 * a is b does not imply a[] is b[] when a is a valuetype, and
8116 * b is a reference type.
8119 if (eoclass->valuetype) {
8120 if ((eclass == mono_defaults.enum_class) ||
8121 (eclass == mono_defaults.enum_class->parent) ||
8122 (eclass == mono_defaults.object_class))
8126 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8127 } else if (mono_class_is_nullable (klass)) {
8128 if (mono_class_is_nullable (oklass))
8129 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8131 return mono_class_is_assignable_from (klass->cast_class, oklass);
8132 } else if (klass == mono_defaults.object_class)
8135 return mono_class_has_parent (oklass, klass);
8138 /*Check if @oklass is variant compatible with @klass.*/
8140 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8143 MonoType **klass_argv, **oklass_argv;
8144 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8145 MonoGenericContainer *container = klass_gtd->generic_container;
8147 /*Viable candidates are instances of the same generic interface*/
8148 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8151 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8152 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8154 for (j = 0; j < container->type_argc; ++j) {
8155 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8156 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8158 if (param1_class->valuetype != param2_class->valuetype)
8162 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8163 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8165 if (param1_class != param2_class) {
8166 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8167 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8169 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8170 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8178 /*Check if @candidate implements the interface @target*/
8180 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8184 gboolean is_variant = mono_class_has_variant_generic_params (target);
8186 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8187 if (mono_class_is_variant_compatible_slow (target, candidate))
8192 if (candidate == target)
8195 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8196 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8197 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8199 if (tb && tb->interfaces) {
8200 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8201 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8202 MonoClass *iface_class;
8204 /* we can't realize the type here since it can do pretty much anything. */
8207 iface_class = mono_class_from_mono_type (iface->type);
8208 if (iface_class == target)
8210 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8212 if (mono_class_implement_interface_slow (target, iface_class))
8217 /*setup_interfaces don't mono_class_init anything*/
8218 /*FIXME this doesn't handle primitive type arrays.
8219 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8220 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8222 mono_class_setup_interfaces (candidate, &error);
8223 if (!mono_error_ok (&error)) {
8224 mono_error_cleanup (&error);
8228 for (i = 0; i < candidate->interface_count; ++i) {
8229 if (candidate->interfaces [i] == target)
8232 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8235 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8239 candidate = candidate->parent;
8240 } while (candidate);
8246 * Check if @oklass can be assigned to @klass.
8247 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8250 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8252 if (candidate == target)
8254 if (target == mono_defaults.object_class)
8257 if (mono_class_has_parent (candidate, target))
8260 /*If target is not an interface there is no need to check them.*/
8261 if (MONO_CLASS_IS_INTERFACE (target))
8262 return mono_class_implement_interface_slow (target, candidate);
8264 if (target->delegate && mono_class_has_variant_generic_params (target))
8265 return mono_class_is_variant_compatible (target, candidate, FALSE);
8268 MonoClass *eclass, *eoclass;
8270 if (target->rank != candidate->rank)
8273 /* vectors vs. one dimensional arrays */
8274 if (target->byval_arg.type != candidate->byval_arg.type)
8277 eclass = target->cast_class;
8278 eoclass = candidate->cast_class;
8281 * a is b does not imply a[] is b[] when a is a valuetype, and
8282 * b is a reference type.
8285 if (eoclass->valuetype) {
8286 if ((eclass == mono_defaults.enum_class) ||
8287 (eclass == mono_defaults.enum_class->parent) ||
8288 (eclass == mono_defaults.object_class))
8292 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8294 /*FIXME properly handle nullables */
8295 /*FIXME properly handle (M)VAR */
8300 * mono_class_get_cctor:
8301 * @klass: A MonoClass pointer
8303 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8306 mono_class_get_cctor (MonoClass *klass)
8308 MonoCachedClassInfo cached_info;
8310 if (image_is_dynamic (klass->image)) {
8312 * has_cctor is not set for these classes because mono_class_init () is
8315 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8318 if (!klass->has_cctor)
8321 if (mono_class_get_cached_class_info (klass, &cached_info))
8322 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8324 if (klass->generic_class && !klass->methods)
8325 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8327 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8331 * mono_class_get_finalizer:
8332 * @klass: The MonoClass pointer
8334 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8337 mono_class_get_finalizer (MonoClass *klass)
8339 MonoCachedClassInfo cached_info;
8342 mono_class_init (klass);
8343 if (!mono_class_has_finalizer (klass))
8346 if (mono_class_get_cached_class_info (klass, &cached_info))
8347 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8349 mono_class_setup_vtable (klass);
8350 return klass->vtable [finalize_slot];
8355 * mono_class_needs_cctor_run:
8356 * @klass: the MonoClass pointer
8357 * @caller: a MonoMethod describing the caller
8359 * Determines whenever the class has a static constructor and whenever it
8360 * needs to be called when executing CALLER.
8363 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8367 method = mono_class_get_cctor (klass);
8369 return (method == caller) ? FALSE : TRUE;
8375 * mono_class_array_element_size:
8378 * Returns: the number of bytes an element of type @klass
8379 * uses when stored into an array.
8382 mono_class_array_element_size (MonoClass *klass)
8384 MonoType *type = &klass->byval_arg;
8387 switch (type->type) {
8390 case MONO_TYPE_BOOLEAN:
8394 case MONO_TYPE_CHAR:
8403 case MONO_TYPE_CLASS:
8404 case MONO_TYPE_STRING:
8405 case MONO_TYPE_OBJECT:
8406 case MONO_TYPE_SZARRAY:
8407 case MONO_TYPE_ARRAY:
8409 case MONO_TYPE_MVAR:
8410 return sizeof (gpointer);
8415 case MONO_TYPE_VALUETYPE:
8416 if (type->data.klass->enumtype) {
8417 type = mono_class_enum_basetype (type->data.klass);
8418 klass = klass->element_class;
8421 return mono_class_instance_size (klass) - sizeof (MonoObject);
8422 case MONO_TYPE_GENERICINST:
8423 type = &type->data.generic_class->container_class->byval_arg;
8426 case MONO_TYPE_VOID:
8430 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8436 * mono_array_element_size:
8437 * @ac: pointer to a #MonoArrayClass
8439 * Returns: the size of single array element.
8442 mono_array_element_size (MonoClass *ac)
8444 g_assert (ac->rank);
8445 return ac->sizes.element_size;
8449 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8450 MonoGenericContext *context)
8452 if (image_is_dynamic (image)) {
8453 MonoClass *tmp_handle_class;
8454 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8456 g_assert (tmp_handle_class);
8458 *handle_class = tmp_handle_class;
8460 if (tmp_handle_class == mono_defaults.typehandle_class)
8461 return &((MonoClass*)obj)->byval_arg;
8466 switch (token & 0xff000000) {
8467 case MONO_TOKEN_TYPE_DEF:
8468 case MONO_TOKEN_TYPE_REF:
8469 case MONO_TOKEN_TYPE_SPEC: {
8473 *handle_class = mono_defaults.typehandle_class;
8474 type = mono_type_get_checked (image, token, context, &error);
8476 mono_loader_set_error_from_mono_error (&error);
8477 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8480 mono_class_init (mono_class_from_mono_type (type));
8481 /* We return a MonoType* as handle */
8484 case MONO_TOKEN_FIELD_DEF: {
8487 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8491 *handle_class = mono_defaults.fieldhandle_class;
8492 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8494 mono_loader_set_error_from_mono_error (&error);
8495 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8498 mono_class_init (class);
8499 return mono_class_get_field (class, token);
8501 case MONO_TOKEN_METHOD_DEF:
8502 case MONO_TOKEN_METHOD_SPEC: {
8504 meth = mono_get_method_full (image, token, NULL, context);
8506 *handle_class = mono_defaults.methodhandle_class;
8509 case MONO_TOKEN_MEMBER_REF: {
8510 guint32 cols [MONO_MEMBERREF_SIZE];
8512 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8513 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8514 mono_metadata_decode_blob_size (sig, &sig);
8515 if (*sig == 0x6) { /* it's a field */
8518 MonoClassField *field;
8519 field = mono_field_from_token_checked (image, token, &klass, context, &error);
8521 *handle_class = mono_defaults.fieldhandle_class;
8523 mono_loader_set_error_from_mono_error (&error);
8524 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8529 meth = mono_get_method_full (image, token, NULL, context);
8531 *handle_class = mono_defaults.methodhandle_class;
8536 g_warning ("Unknown token 0x%08x in ldtoken", token);
8543 * This function might need to call runtime functions so it can't be part
8544 * of the metadata library.
8546 static MonoLookupDynamicToken lookup_dynamic = NULL;
8549 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8551 lookup_dynamic = func;
8555 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8557 MonoClass *handle_class;
8559 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8563 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8565 return lookup_dynamic (image, token, valid_token, handle_class, context);
8568 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8571 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8573 get_cached_class_info = func;
8577 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8579 if (!get_cached_class_info)
8582 return get_cached_class_info (klass, res);
8586 mono_install_get_class_from_name (MonoGetClassFromName func)
8588 get_class_from_name = func;
8592 mono_class_get_image (MonoClass *klass)
8594 return klass->image;
8598 * mono_class_get_element_class:
8599 * @klass: the MonoClass to act on
8601 * Returns: the element class of an array or an enumeration.
8604 mono_class_get_element_class (MonoClass *klass)
8606 return klass->element_class;
8610 * mono_class_is_valuetype:
8611 * @klass: the MonoClass to act on
8613 * Returns: true if the MonoClass represents a ValueType.
8616 mono_class_is_valuetype (MonoClass *klass)
8618 return klass->valuetype;
8622 * mono_class_is_enum:
8623 * @klass: the MonoClass to act on
8625 * Returns: true if the MonoClass represents an enumeration.
8628 mono_class_is_enum (MonoClass *klass)
8630 return klass->enumtype;
8634 * mono_class_enum_basetype:
8635 * @klass: the MonoClass to act on
8637 * Returns: the underlying type representation for an enumeration.
8640 mono_class_enum_basetype (MonoClass *klass)
8642 if (klass->element_class == klass)
8643 /* SRE or broken types */
8646 return &klass->element_class->byval_arg;
8650 * mono_class_get_parent
8651 * @klass: the MonoClass to act on
8653 * Returns: the parent class for this class.
8656 mono_class_get_parent (MonoClass *klass)
8658 return klass->parent;
8662 * mono_class_get_nesting_type;
8663 * @klass: the MonoClass to act on
8665 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8668 mono_class_get_nesting_type (MonoClass *klass)
8670 return klass->nested_in;
8674 * mono_class_get_rank:
8675 * @klass: the MonoClass to act on
8677 * Returns: the rank for the array (the number of dimensions).
8680 mono_class_get_rank (MonoClass *klass)
8686 * mono_class_get_flags:
8687 * @klass: the MonoClass to act on
8689 * The type flags from the TypeDef table from the metadata.
8690 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8693 * Returns: the flags from the TypeDef table.
8696 mono_class_get_flags (MonoClass *klass)
8698 return klass->flags;
8702 * mono_class_get_name
8703 * @klass: the MonoClass to act on
8705 * Returns: the name of the class.
8708 mono_class_get_name (MonoClass *klass)
8714 * mono_class_get_namespace:
8715 * @klass: the MonoClass to act on
8717 * Returns: the namespace of the class.
8720 mono_class_get_namespace (MonoClass *klass)
8722 return klass->name_space;
8726 * mono_class_get_type:
8727 * @klass: the MonoClass to act on
8729 * This method returns the internal Type representation for the class.
8731 * Returns: the MonoType from the class.
8734 mono_class_get_type (MonoClass *klass)
8736 return &klass->byval_arg;
8740 * mono_class_get_type_token
8741 * @klass: the MonoClass to act on
8743 * This method returns type token for the class.
8745 * Returns: the type token for the class.
8748 mono_class_get_type_token (MonoClass *klass)
8750 return klass->type_token;
8754 * mono_class_get_byref_type:
8755 * @klass: the MonoClass to act on
8760 mono_class_get_byref_type (MonoClass *klass)
8762 return &klass->this_arg;
8766 * mono_class_num_fields:
8767 * @klass: the MonoClass to act on
8769 * Returns: the number of static and instance fields in the class.
8772 mono_class_num_fields (MonoClass *klass)
8774 return klass->field.count;
8778 * mono_class_num_methods:
8779 * @klass: the MonoClass to act on
8781 * Returns: the number of methods in the class.
8784 mono_class_num_methods (MonoClass *klass)
8786 return klass->method.count;
8790 * mono_class_num_properties
8791 * @klass: the MonoClass to act on
8793 * Returns: the number of properties in the class.
8796 mono_class_num_properties (MonoClass *klass)
8798 mono_class_setup_properties (klass);
8800 return klass->ext->property.count;
8804 * mono_class_num_events:
8805 * @klass: the MonoClass to act on
8807 * Returns: the number of events in the class.
8810 mono_class_num_events (MonoClass *klass)
8812 mono_class_setup_events (klass);
8814 return klass->ext->event.count;
8818 * mono_class_get_fields:
8819 * @klass: the MonoClass to act on
8821 * This routine is an iterator routine for retrieving the fields in a class.
8823 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8824 * iterate over all of the elements. When no more values are
8825 * available, the return value is NULL.
8827 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8830 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8832 MonoClassField* field;
8836 mono_class_setup_fields_locking (klass);
8837 if (klass->exception_type)
8839 /* start from the first */
8840 if (klass->field.count) {
8841 return *iter = &klass->fields [0];
8849 if (field < &klass->fields [klass->field.count]) {
8850 return *iter = field;
8856 * mono_class_get_methods
8857 * @klass: the MonoClass to act on
8859 * This routine is an iterator routine for retrieving the fields in a class.
8861 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8862 * iterate over all of the elements. When no more values are
8863 * available, the return value is NULL.
8865 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8868 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8870 MonoMethod** method;
8874 mono_class_setup_methods (klass);
8877 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8878 * FIXME we should better report this error to the caller
8880 if (!klass->methods)
8882 /* start from the first */
8883 if (klass->method.count) {
8884 *iter = &klass->methods [0];
8885 return klass->methods [0];
8893 if (method < &klass->methods [klass->method.count]) {
8901 * mono_class_get_virtual_methods:
8903 * Iterate over the virtual methods of KLASS.
8905 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8908 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8910 MonoMethod** method;
8913 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8915 mono_class_setup_methods (klass);
8917 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8918 * FIXME we should better report this error to the caller
8920 if (!klass->methods)
8922 /* start from the first */
8923 method = &klass->methods [0];
8928 while (method < &klass->methods [klass->method.count]) {
8929 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8933 if (method < &klass->methods [klass->method.count]) {
8940 /* Search directly in metadata to avoid calling setup_methods () */
8941 MonoMethod *res = NULL;
8947 start_index = GPOINTER_TO_UINT (*iter);
8950 for (i = start_index; i < klass->method.count; ++i) {
8953 /* class->method.first points into the methodptr table */
8954 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8956 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8960 if (i < klass->method.count) {
8961 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8962 /* Add 1 here so the if (*iter) check fails */
8963 *iter = GUINT_TO_POINTER (i + 1);
8972 * mono_class_get_properties:
8973 * @klass: the MonoClass to act on
8975 * This routine is an iterator routine for retrieving the properties in a class.
8977 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8978 * iterate over all of the elements. When no more values are
8979 * available, the return value is NULL.
8981 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8984 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8986 MonoProperty* property;
8990 mono_class_setup_properties (klass);
8991 /* start from the first */
8992 if (klass->ext->property.count) {
8993 return *iter = &klass->ext->properties [0];
9001 if (property < &klass->ext->properties [klass->ext->property.count]) {
9002 return *iter = property;
9008 * mono_class_get_events:
9009 * @klass: the MonoClass to act on
9011 * This routine is an iterator routine for retrieving the properties in a class.
9013 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9014 * iterate over all of the elements. When no more values are
9015 * available, the return value is NULL.
9017 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9020 mono_class_get_events (MonoClass* klass, gpointer *iter)
9026 mono_class_setup_events (klass);
9027 /* start from the first */
9028 if (klass->ext->event.count) {
9029 return *iter = &klass->ext->events [0];
9037 if (event < &klass->ext->events [klass->ext->event.count]) {
9038 return *iter = event;
9044 * mono_class_get_interfaces
9045 * @klass: the MonoClass to act on
9047 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9049 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9050 * iterate over all of the elements. When no more values are
9051 * available, the return value is NULL.
9053 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9056 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9064 mono_class_init (klass);
9065 if (!klass->interfaces_inited) {
9066 mono_class_setup_interfaces (klass, &error);
9067 if (!mono_error_ok (&error)) {
9068 mono_error_cleanup (&error);
9072 /* start from the first */
9073 if (klass->interface_count) {
9074 *iter = &klass->interfaces [0];
9075 return klass->interfaces [0];
9083 if (iface < &klass->interfaces [klass->interface_count]) {
9091 setup_nested_types (MonoClass *klass)
9094 GList *classes, *nested_classes, *l;
9097 if (klass->nested_classes_inited)
9100 if (!klass->type_token)
9101 klass->nested_classes_inited = TRUE;
9103 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9107 guint32 cols [MONO_NESTED_CLASS_SIZE];
9108 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9109 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9110 if (!mono_error_ok (&error)) {
9111 /*FIXME don't swallow the error message*/
9112 mono_error_cleanup (&error);
9114 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9118 classes = g_list_prepend (classes, nclass);
9120 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9123 mono_class_alloc_ext (klass);
9125 nested_classes = NULL;
9126 for (l = classes; l; l = l->next)
9127 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9128 g_list_free (classes);
9130 mono_image_lock (klass->image);
9132 mono_memory_barrier ();
9133 if (!klass->nested_classes_inited) {
9134 klass->ext->nested_classes = nested_classes;
9135 mono_memory_barrier ();
9136 klass->nested_classes_inited = TRUE;
9139 mono_image_unlock (klass->image);
9143 * mono_class_get_nested_types
9144 * @klass: the MonoClass to act on
9146 * This routine is an iterator routine for retrieving the nested types of a class.
9147 * This works only if @klass is non-generic, or a generic type definition.
9149 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9150 * iterate over all of the elements. When no more values are
9151 * available, the return value is NULL.
9153 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9156 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9162 if (!klass->nested_classes_inited)
9163 setup_nested_types (klass);
9166 /* start from the first */
9167 if (klass->ext && klass->ext->nested_classes) {
9168 *iter = klass->ext->nested_classes;
9169 return klass->ext->nested_classes->data;
9171 /* no nested types */
9186 * mono_class_is_delegate
9187 * @klass: the MonoClass to act on
9189 * Returns: true if the MonoClass represents a System.Delegate.
9192 mono_class_is_delegate (MonoClass *klass)
9194 return klass->delegate;
9198 * mono_class_implements_interface
9199 * @klass: The MonoClass to act on
9200 * @interface: The interface to check if @klass implements.
9202 * Returns: true if @klass implements @interface.
9205 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9207 return mono_class_is_assignable_from (iface, klass);
9211 * mono_field_get_name:
9212 * @field: the MonoClassField to act on
9214 * Returns: the name of the field.
9217 mono_field_get_name (MonoClassField *field)
9223 * mono_field_get_type:
9224 * @field: the MonoClassField to act on
9226 * Returns: MonoType of the field.
9229 mono_field_get_type (MonoClassField *field)
9232 MonoType *type = mono_field_get_type_checked (field, &error);
9233 if (!mono_error_ok (&error)) {
9234 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9235 mono_error_cleanup (&error);
9242 * mono_field_get_type_checked:
9243 * @field: the MonoClassField to act on
9244 * @error: used to return any erro found while retrieving @field type
9246 * Returns: MonoType of the field.
9249 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9251 mono_error_init (error);
9253 mono_field_resolve_type (field, error);
9258 * mono_field_get_parent:
9259 * @field: the MonoClassField to act on
9261 * Returns: MonoClass where the field was defined.
9264 mono_field_get_parent (MonoClassField *field)
9266 return field->parent;
9270 * mono_field_get_flags;
9271 * @field: the MonoClassField to act on
9273 * The metadata flags for a field are encoded using the
9274 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9276 * Returns: the flags for the field.
9279 mono_field_get_flags (MonoClassField *field)
9282 return mono_field_resolve_flags (field);
9283 return field->type->attrs;
9287 * mono_field_get_offset;
9288 * @field: the MonoClassField to act on
9290 * Returns: the field offset.
9293 mono_field_get_offset (MonoClassField *field)
9295 return field->offset;
9299 mono_field_get_rva (MonoClassField *field)
9303 MonoClass *klass = field->parent;
9304 MonoFieldDefaultValue *field_def_values;
9306 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9308 if (!klass->ext || !klass->ext->field_def_values) {
9309 mono_class_alloc_ext (klass);
9311 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9313 mono_image_lock (klass->image);
9314 if (!klass->ext->field_def_values)
9315 klass->ext->field_def_values = field_def_values;
9316 mono_image_unlock (klass->image);
9319 field_index = mono_field_get_index (field);
9321 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9322 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9324 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9325 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9328 return klass->ext->field_def_values [field_index].data;
9332 * mono_field_get_data;
9333 * @field: the MonoClassField to act on
9335 * Returns: pointer to the metadata constant value or to the field
9336 * data if it has an RVA flag.
9339 mono_field_get_data (MonoClassField *field)
9341 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9342 MonoTypeEnum def_type;
9344 return mono_class_get_field_default_value (field, &def_type);
9345 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9346 return mono_field_get_rva (field);
9353 * mono_property_get_name:
9354 * @prop: the MonoProperty to act on
9356 * Returns: the name of the property
9359 mono_property_get_name (MonoProperty *prop)
9365 * mono_property_get_set_method
9366 * @prop: the MonoProperty to act on.
9368 * Returns: the setter method of the property (A MonoMethod)
9371 mono_property_get_set_method (MonoProperty *prop)
9377 * mono_property_get_get_method
9378 * @prop: the MonoProperty to act on.
9380 * Returns: the setter method of the property (A MonoMethod)
9383 mono_property_get_get_method (MonoProperty *prop)
9389 * mono_property_get_parent:
9390 * @prop: the MonoProperty to act on.
9392 * Returns: the MonoClass where the property was defined.
9395 mono_property_get_parent (MonoProperty *prop)
9397 return prop->parent;
9401 * mono_property_get_flags:
9402 * @prop: the MonoProperty to act on.
9404 * The metadata flags for a property are encoded using the
9405 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9407 * Returns: the flags for the property.
9410 mono_property_get_flags (MonoProperty *prop)
9416 * mono_event_get_name:
9417 * @event: the MonoEvent to act on
9419 * Returns: the name of the event.
9422 mono_event_get_name (MonoEvent *event)
9428 * mono_event_get_add_method:
9429 * @event: The MonoEvent to act on.
9431 * Returns: the @add' method for the event (a MonoMethod).
9434 mono_event_get_add_method (MonoEvent *event)
9440 * mono_event_get_remove_method:
9441 * @event: The MonoEvent to act on.
9443 * Returns: the @remove method for the event (a MonoMethod).
9446 mono_event_get_remove_method (MonoEvent *event)
9448 return event->remove;
9452 * mono_event_get_raise_method:
9453 * @event: The MonoEvent to act on.
9455 * Returns: the @raise method for the event (a MonoMethod).
9458 mono_event_get_raise_method (MonoEvent *event)
9460 return event->raise;
9464 * mono_event_get_parent:
9465 * @event: the MonoEvent to act on.
9467 * Returns: the MonoClass where the event is defined.
9470 mono_event_get_parent (MonoEvent *event)
9472 return event->parent;
9476 * mono_event_get_flags
9477 * @event: the MonoEvent to act on.
9479 * The metadata flags for an event are encoded using the
9480 * EVENT_* constants. See the tabledefs.h file for details.
9482 * Returns: the flags for the event.
9485 mono_event_get_flags (MonoEvent *event)
9487 return event->attrs;
9491 * mono_class_get_method_from_name:
9492 * @klass: where to look for the method
9493 * @name: name of the method
9494 * @param_count: number of parameters. -1 for any number.
9496 * Obtains a MonoMethod with a given name and number of parameters.
9497 * It only works if there are no multiple signatures for any given method name.
9500 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9502 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9506 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9508 MonoMethod *res = NULL;
9511 /* Search directly in the metadata to avoid calling setup_methods () */
9512 for (i = 0; i < klass->method.count; ++i) {
9513 guint32 cols [MONO_METHOD_SIZE];
9515 MonoMethodSignature *sig;
9517 /* class->method.first points into the methodptr table */
9518 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9520 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9521 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9522 if (param_count == -1) {
9526 sig = mono_method_signature (method);
9527 if (sig && sig->param_count == param_count) {
9538 * mono_class_get_method_from_name_flags:
9539 * @klass: where to look for the method
9540 * @name_space: name of the method
9541 * @param_count: number of parameters. -1 for any number.
9542 * @flags: flags which must be set in the method
9544 * Obtains a MonoMethod with a given name and number of parameters.
9545 * It only works if there are no multiple signatures for any given method name.
9548 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9550 MonoMethod *res = NULL;
9553 mono_class_init (klass);
9555 if (klass->generic_class && !klass->methods) {
9556 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9559 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9560 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
9565 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9566 mono_class_setup_methods (klass);
9568 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9569 See mono/tests/array_load_exception.il
9570 FIXME we should better report this error to the caller
9572 if (!klass->methods)
9574 for (i = 0; i < klass->method.count; ++i) {
9575 MonoMethod *method = klass->methods [i];
9577 if (method->name[0] == name [0] &&
9578 !strcmp (name, method->name) &&
9579 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9580 ((method->flags & flags) == flags)) {
9587 res = find_method_in_metadata (klass, name, param_count, flags);
9594 * mono_class_set_failure:
9595 * @klass: class in which the failure was detected
9596 * @ex_type: the kind of exception/error to be thrown (later)
9597 * @ex_data: exception data (specific to each type of exception/error)
9599 * Keep a detected failure informations in the class for later processing.
9600 * Note that only the first failure is kept.
9602 * LOCKING: Acquires the loader lock.
9605 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9607 if (klass->exception_type)
9610 mono_loader_lock ();
9611 klass->exception_type = ex_type;
9613 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9614 mono_loader_unlock ();
9620 * mono_class_get_exception_data:
9622 * Return the exception_data property of KLASS.
9624 * LOCKING: Acquires the loader lock.
9627 mono_class_get_exception_data (MonoClass *klass)
9629 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9633 * mono_classes_init:
9635 * Initialize the resources used by this module.
9638 mono_classes_init (void)
9640 mono_mutex_init (&classes_mutex);
9642 mono_counters_register ("Inflated methods size",
9643 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9644 mono_counters_register ("Inflated classes",
9645 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9646 mono_counters_register ("Inflated classes size",
9647 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9648 mono_counters_register ("MonoClass size",
9649 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9650 mono_counters_register ("MonoClassExt size",
9651 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9655 * mono_classes_cleanup:
9657 * Free the resources used by this module.
9660 mono_classes_cleanup (void)
9662 if (global_interface_bitset)
9663 mono_bitset_free (global_interface_bitset);
9664 global_interface_bitset = NULL;
9665 mono_mutex_destroy (&classes_mutex);
9669 * mono_class_get_exception_for_failure:
9670 * @klass: class in which the failure was detected
9672 * Return a constructed MonoException than the caller can then throw
9673 * using mono_raise_exception - or NULL if no failure is present (or
9674 * doesn't result in an exception).
9677 mono_class_get_exception_for_failure (MonoClass *klass)
9679 gpointer exception_data = mono_class_get_exception_data (klass);
9681 switch (klass->exception_type) {
9682 #ifndef DISABLE_SECURITY
9683 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9684 MonoDomain *domain = mono_domain_get ();
9685 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9686 MonoMethod *method = exception_data;
9687 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9688 MonoObject *exc = NULL;
9692 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9693 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9694 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9696 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9697 return (MonoException*) exc;
9700 case MONO_EXCEPTION_TYPE_LOAD: {
9703 char *str = mono_type_get_full_name (klass);
9704 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9705 name = mono_string_new (mono_domain_get (), str);
9707 ex = mono_get_exception_type_load (name, astr);
9711 case MONO_EXCEPTION_MISSING_METHOD: {
9712 char *class_name = exception_data;
9713 char *assembly_name = class_name + strlen (class_name) + 1;
9715 return mono_get_exception_missing_method (class_name, assembly_name);
9717 case MONO_EXCEPTION_MISSING_FIELD: {
9718 char *class_name = exception_data;
9719 char *member_name = class_name + strlen (class_name) + 1;
9721 return mono_get_exception_missing_field (class_name, member_name);
9723 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9724 char *msg_format = exception_data;
9725 char *assembly_name = msg_format + strlen (msg_format) + 1;
9726 char *msg = g_strdup_printf (msg_format, assembly_name);
9729 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9735 case MONO_EXCEPTION_BAD_IMAGE: {
9736 return mono_get_exception_bad_image_format (exception_data);
9739 MonoLoaderError *error;
9742 error = mono_loader_get_last_error ();
9744 ex = mono_loader_error_prepare_exception (error);
9748 /* TODO - handle other class related failures */
9755 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9757 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9758 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9760 if (outer_klass == inner_klass)
9762 inner_klass = inner_klass->nested_in;
9763 } while (inner_klass);
9768 mono_class_get_generic_type_definition (MonoClass *klass)
9770 return klass->generic_class ? klass->generic_class->container_class : klass;
9774 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9776 * Generic instantiations are ignored for all super types of @klass.
9778 * Visibility checks ignoring generic instantiations.
9781 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9784 klass = mono_class_get_generic_type_definition (klass);
9785 parent = mono_class_get_generic_type_definition (parent);
9786 mono_class_setup_supertypes (klass);
9788 for (i = 0; i < klass->idepth; ++i) {
9789 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9795 * Subtype can only access parent members with family protection if the site object
9796 * is subclass of Subtype. For example:
9797 * class A { protected int x; }
9799 * void valid_access () {
9803 * void invalid_access () {
9810 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9812 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9815 if (context_klass == NULL)
9817 /*if access_klass is not member_klass context_klass must be type compat*/
9818 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9824 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9827 if (accessing == accessed)
9829 if (!accessed || !accessing)
9832 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9833 * anywhere so untrusted friends are not safe to access platform's code internals */
9834 if (mono_security_core_clr_enabled ()) {
9835 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9839 mono_assembly_load_friends (accessed);
9840 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9841 MonoAssemblyName *friend = tmp->data;
9842 /* Be conservative with checks */
9845 if (strcmp (accessing->aname.name, friend->name))
9847 if (friend->public_key_token [0]) {
9848 if (!accessing->aname.public_key_token [0])
9850 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9859 * If klass is a generic type or if it is derived from a generic type, return the
9860 * MonoClass of the generic definition
9861 * Returns NULL if not found
9864 get_generic_definition_class (MonoClass *klass)
9867 if (klass->generic_class && klass->generic_class->container_class)
9868 return klass->generic_class->container_class;
9869 klass = klass->parent;
9875 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9878 for (i = 0; i < ginst->type_argc; ++i) {
9879 MonoType *type = ginst->type_argv[i];
9880 switch (type->type) {
9881 case MONO_TYPE_SZARRAY:
9882 if (!can_access_type (access_klass, type->data.klass))
9885 case MONO_TYPE_ARRAY:
9886 if (!can_access_type (access_klass, type->data.array->eklass))
9890 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9893 case MONO_TYPE_CLASS:
9894 case MONO_TYPE_VALUETYPE:
9895 case MONO_TYPE_GENERICINST:
9896 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9904 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9908 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9911 if (access_klass->element_class && !access_klass->enumtype)
9912 access_klass = access_klass->element_class;
9914 if (member_klass->element_class && !member_klass->enumtype)
9915 member_klass = member_klass->element_class;
9917 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9919 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9922 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9925 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9928 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9931 /*Non nested type with nested visibility. We just fail it.*/
9932 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9935 switch (access_level) {
9936 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9937 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9939 case TYPE_ATTRIBUTE_PUBLIC:
9942 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9945 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9946 return is_nesting_type (member_klass, access_klass);
9948 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9949 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9951 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9952 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9954 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9955 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9956 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9958 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9959 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9960 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9965 /* FIXME: check visibility of type, too */
9967 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9969 MonoClass *member_generic_def;
9970 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9973 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9974 access_klass->generic_container) &&
9975 (member_generic_def = get_generic_definition_class (member_klass))) {
9976 MonoClass *access_container;
9978 if (access_klass->generic_container)
9979 access_container = access_klass;
9981 access_container = access_klass->generic_class->container_class;
9983 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9987 /* Partition I 8.5.3.2 */
9988 /* the access level values are the same for fields and methods */
9989 switch (access_level) {
9990 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9991 /* same compilation unit */
9992 return access_klass->image == member_klass->image;
9993 case FIELD_ATTRIBUTE_PRIVATE:
9994 return access_klass == member_klass;
9995 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9996 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9997 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10000 case FIELD_ATTRIBUTE_ASSEMBLY:
10001 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10002 case FIELD_ATTRIBUTE_FAMILY:
10003 if (is_valid_family_access (access_klass, member_klass, context_klass))
10006 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10007 if (is_valid_family_access (access_klass, member_klass, context_klass))
10009 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10010 case FIELD_ATTRIBUTE_PUBLIC:
10017 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10019 /* FIXME: check all overlapping fields */
10020 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10022 MonoClass *nested = method->klass->nested_in;
10024 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10027 nested = nested->nested_in;
10034 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10036 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10038 MonoClass *nested = method->klass->nested_in;
10040 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10043 nested = nested->nested_in;
10048 * with generics calls to explicit interface implementations can be expressed
10049 * directly: the method is private, but we must allow it. This may be opening
10050 * a hole or the generics code should handle this differently.
10051 * Maybe just ensure the interface type is public.
10053 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10059 * mono_method_can_access_method_full:
10060 * @method: The caller method
10061 * @called: The called method
10062 * @context_klass: The static type on stack of the owner @called object used
10064 * This function must be used with instance calls, as they have more strict family accessibility.
10065 * It can be used with static methods, but context_klass should be NULL.
10067 * Returns: TRUE if caller have proper visibility and acessibility to @called
10070 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10072 MonoClass *access_class = method->klass;
10073 MonoClass *member_class = called->klass;
10074 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10076 MonoClass *nested = access_class->nested_in;
10078 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10081 nested = nested->nested_in;
10088 can = can_access_type (access_class, member_class);
10090 MonoClass *nested = access_class->nested_in;
10092 can = can_access_type (nested, member_class);
10095 nested = nested->nested_in;
10102 if (called->is_inflated) {
10103 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10104 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10113 * mono_method_can_access_field_full:
10114 * @method: The caller method
10115 * @field: The accessed field
10116 * @context_klass: The static type on stack of the owner @field object used
10118 * This function must be used with instance fields, as they have more strict family accessibility.
10119 * It can be used with static fields, but context_klass should be NULL.
10121 * Returns: TRUE if caller have proper visibility and acessibility to @field
10124 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10126 MonoClass *access_class = method->klass;
10127 MonoClass *member_class = field->parent;
10128 /* FIXME: check all overlapping fields */
10129 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10131 MonoClass *nested = access_class->nested_in;
10133 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10136 nested = nested->nested_in;
10143 can = can_access_type (access_class, member_class);
10145 MonoClass *nested = access_class->nested_in;
10147 can = can_access_type (nested, member_class);
10150 nested = nested->nested_in;
10160 * mono_class_can_access_class:
10161 * @source_class: The source class
10162 * @target_class: The accessed class
10164 * This function returns is @target_class is visible to @source_class
10166 * Returns: TRUE if source have proper visibility and acessibility to target
10169 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10171 return can_access_type (source_class, target_class);
10175 * mono_type_is_valid_enum_basetype:
10176 * @type: The MonoType to check
10178 * Returns: TRUE if the type can be used as the basetype of an enum
10180 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10181 switch (type->type) {
10184 case MONO_TYPE_BOOLEAN:
10187 case MONO_TYPE_CHAR:
10200 * mono_class_is_valid_enum:
10201 * @klass: An enum class to be validated
10203 * This method verify the required properties an enum should have.
10205 * Returns: TRUE if the informed enum class is valid
10207 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10208 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10209 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10211 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10212 MonoClassField * field;
10213 gpointer iter = NULL;
10214 gboolean found_base_field = FALSE;
10216 g_assert (klass->enumtype);
10217 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10218 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10222 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10225 while ((field = mono_class_get_fields (klass, &iter))) {
10226 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10227 if (found_base_field)
10229 found_base_field = TRUE;
10230 if (!mono_type_is_valid_enum_basetype (field->type))
10235 if (!found_base_field)
10238 if (klass->method.count > 0)
10245 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10247 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10251 * mono_class_setup_interface_id:
10253 * Initializes MonoClass::interface_id if required.
10255 * LOCKING: Acquires the loader lock.
10258 mono_class_setup_interface_id (MonoClass *class)
10260 mono_loader_lock ();
10261 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10262 class->interface_id = mono_get_unique_iid (class);
10263 mono_loader_unlock ();
10267 * mono_class_alloc_ext:
10269 * Allocate klass->ext if not already done.
10272 mono_class_alloc_ext (MonoClass *klass)
10279 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10280 mono_image_lock (klass->image);
10281 mono_memory_barrier ();
10284 class_ext_size += sizeof (MonoClassExt);
10285 mono_image_unlock (klass->image);
10289 * mono_class_setup_interfaces:
10291 * Initialize class->interfaces/interfaces_count.
10292 * LOCKING: Acquires the loader lock.
10293 * This function can fail the type.
10296 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10298 int i, interface_count;
10299 MonoClass **interfaces;
10301 mono_error_init (error);
10303 if (klass->interfaces_inited)
10306 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10307 MonoType *args [1];
10309 /* generic IList, ICollection, IEnumerable */
10310 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10311 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10313 args [0] = &klass->element_class->byval_arg;
10314 interfaces [0] = mono_class_bind_generic_parameters (
10315 mono_defaults.generic_ilist_class, 1, args, FALSE);
10316 if (interface_count > 1)
10317 interfaces [1] = mono_class_bind_generic_parameters (
10318 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10319 } else if (klass->generic_class) {
10320 MonoClass *gklass = klass->generic_class->container_class;
10322 mono_class_setup_interfaces (gklass, error);
10323 if (!mono_error_ok (error)) {
10324 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10328 interface_count = gklass->interface_count;
10329 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10330 for (i = 0; i < interface_count; i++) {
10331 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10332 if (!mono_error_ok (error)) {
10333 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10338 interface_count = 0;
10342 mono_image_lock (klass->image);
10344 if (!klass->interfaces_inited) {
10345 klass->interface_count = interface_count;
10346 klass->interfaces = interfaces;
10348 mono_memory_barrier ();
10350 klass->interfaces_inited = TRUE;
10353 mono_image_unlock (klass->image);
10357 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10359 MonoClass *class = field->parent;
10360 MonoImage *image = class->image;
10361 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10362 int field_idx = field - class->fields;
10364 mono_error_init (error);
10367 MonoClassField *gfield = >d->fields [field_idx];
10368 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10369 if (!mono_error_ok (error)) {
10370 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10371 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10375 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10376 if (!mono_error_ok (error)) {
10377 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10378 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10383 guint32 cols [MONO_FIELD_SIZE];
10384 MonoGenericContainer *container = NULL;
10385 int idx = class->field.first + field_idx;
10387 /*FIXME, in theory we do not lazy load SRE fields*/
10388 g_assert (!image_is_dynamic (image));
10390 if (class->generic_container) {
10391 container = class->generic_container;
10393 container = gtd->generic_container;
10394 g_assert (container);
10397 /* class->field.first and idx points into the fieldptr table */
10398 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10400 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10401 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10402 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10406 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10408 mono_metadata_decode_value (sig, &sig);
10409 /* FIELD signature == 0x06 */
10410 g_assert (*sig == 0x06);
10411 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10413 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10418 mono_field_resolve_flags (MonoClassField *field)
10420 MonoClass *class = field->parent;
10421 MonoImage *image = class->image;
10422 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10423 int field_idx = field - class->fields;
10427 MonoClassField *gfield = >d->fields [field_idx];
10428 return mono_field_get_flags (gfield);
10430 int idx = class->field.first + field_idx;
10432 /*FIXME, in theory we do not lazy load SRE fields*/
10433 g_assert (!image_is_dynamic (image));
10435 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10440 * mono_class_setup_basic_field_info:
10441 * @class: The class to initialize
10443 * Initializes the class->fields array of fields.
10444 * Aquires the loader lock.
10447 mono_class_setup_basic_field_info_locking (MonoClass *class)
10449 mono_loader_lock ();
10450 mono_class_setup_basic_field_info (class);
10451 mono_loader_unlock ();
10455 * mono_class_get_fields_lazy:
10456 * @klass: the MonoClass to act on
10458 * This routine is an iterator routine for retrieving the fields in a class.
10459 * Only minimal information about fields are loaded. Accessors must be used
10460 * for all MonoClassField returned.
10462 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10463 * iterate over all of the elements. When no more values are
10464 * available, the return value is NULL.
10466 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10469 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10471 MonoClassField* field;
10475 mono_class_setup_basic_field_info_locking (klass);
10476 if (!klass->fields)
10478 /* start from the first */
10479 if (klass->field.count) {
10480 return *iter = &klass->fields [0];
10488 if (field < &klass->fields [klass->field.count]) {
10489 return *iter = field;
10495 mono_class_full_name (MonoClass *klass)
10497 return mono_type_full_name (&klass->byval_arg);