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_full:
972 * Instantiate method @method with the generic context @context.
973 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
974 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
977 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
980 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
981 if (!mono_error_ok (&error))
982 /*FIXME do proper error handling - on this case, kill this function. */
983 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
989 * mono_class_inflate_generic_method_full_checked:
990 * Same as mono_class_inflate_generic_method_full but return failure using @error.
993 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
996 MonoMethodInflated *iresult, *cached;
997 MonoMethodSignature *sig;
998 MonoGenericContext tmp_context;
999 gboolean is_mb_open = FALSE;
1001 mono_error_init (error);
1003 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1004 while (method->is_inflated) {
1005 MonoGenericContext *method_context = mono_method_get_context (method);
1006 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1008 tmp_context = inflate_generic_context (method_context, context, error);
1009 if (!mono_error_ok (error))
1011 context = &tmp_context;
1013 if (mono_metadata_generic_context_equal (method_context, context))
1016 method = imethod->declaring;
1020 * A method only needs to be inflated if the context has argument for which it is
1023 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1024 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1027 if (!((method->is_generic && context->method_inst) ||
1028 (method->klass->generic_container && context->class_inst)))
1032 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1033 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1034 * This is opposite to the way non-SRE MethodInfos behave.
1036 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1038 * void Example<T> () {
1042 * In Example, the method token must be encoded as: "void Example<!!0>()"
1044 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1045 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1047 * On the other hand, inflating a non-SRE generic method with its own arguments should
1048 * return itself. For example:
1050 * MethodInfo m = ... //m is a generic method definition
1051 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1054 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1055 * what happens with regular methods.
1057 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1058 * everything should behave like a regular type or method.
1061 is_mb_open = method->is_generic &&
1062 image_is_dynamic (method->klass->image) && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1063 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1065 iresult = g_new0 (MonoMethodInflated, 1);
1066 iresult->context = *context;
1067 iresult->declaring = method;
1068 iresult->method.method.is_mb_open = is_mb_open;
1070 if (!context->method_inst && method->is_generic)
1071 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1073 if (!context->class_inst) {
1074 g_assert (!iresult->declaring->klass->generic_class);
1075 if (iresult->declaring->klass->generic_container)
1076 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1077 else if (iresult->declaring->klass->generic_class)
1078 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1081 cached = mono_method_inflated_lookup (iresult, FALSE);
1084 return (MonoMethod*)cached;
1087 mono_stats.inflated_method_count++;
1089 inflated_methods_size += sizeof (MonoMethodInflated);
1091 sig = mono_method_signature (method);
1093 char *name = mono_type_get_full_name (method->klass);
1094 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1100 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1102 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1105 result = (MonoMethod *) iresult;
1106 result->is_inflated = TRUE;
1107 result->is_generic = FALSE;
1108 result->sre_method = FALSE;
1109 result->signature = NULL;
1110 result->is_mb_open = is_mb_open;
1112 if (!context->method_inst) {
1113 /* Set the generic_container of the result to the generic_container of method */
1114 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1116 if (generic_container) {
1117 result->is_generic = 1;
1118 mono_method_set_generic_container (result, generic_container);
1122 if (!klass_hint || !klass_hint->generic_class ||
1123 klass_hint->generic_class->container_class != method->klass ||
1124 klass_hint->generic_class->context.class_inst != context->class_inst)
1127 if (method->klass->generic_container)
1128 result->klass = klass_hint;
1130 if (!result->klass) {
1131 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1132 if (!mono_error_ok (error))
1135 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1137 mono_metadata_free_type (inflated);
1141 * FIXME: This should hold, but it doesn't:
1143 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1144 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1145 * g_assert (result->is_generic);
1148 * Fixing this here causes other things to break, hence a very
1149 * ugly hack in mini-trampolines.c - see
1150 * is_generic_method_definition().
1153 return (MonoMethod*)mono_method_inflated_lookup (iresult, TRUE);
1161 * mono_get_inflated_method:
1163 * Obsolete. We keep it around since it's mentioned in the public API.
1166 mono_get_inflated_method (MonoMethod *method)
1172 * mono_method_get_context_general:
1174 * @uninflated: handle uninflated methods?
1176 * Returns the generic context of a method or NULL if it doesn't have
1177 * one. For an inflated method that's the context stored in the
1178 * method. Otherwise it's in the method's generic container or in the
1179 * generic container of the method's class.
1182 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1184 if (method->is_inflated) {
1185 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1186 return &imethod->context;
1190 if (method->is_generic)
1191 return &(mono_method_get_generic_container (method)->context);
1192 if (method->klass->generic_container)
1193 return &method->klass->generic_container->context;
1198 * mono_method_get_context:
1201 * Returns the generic context for method if it's inflated, otherwise
1205 mono_method_get_context (MonoMethod *method)
1207 return mono_method_get_context_general (method, FALSE);
1211 * mono_method_get_generic_container:
1213 * Returns the generic container of METHOD, which should be a generic method definition.
1214 * Returns NULL if METHOD is not a generic method definition.
1215 * LOCKING: Acquires the loader lock.
1217 MonoGenericContainer*
1218 mono_method_get_generic_container (MonoMethod *method)
1220 MonoGenericContainer *container;
1222 if (!method->is_generic)
1225 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1226 g_assert (container);
1232 * mono_method_set_generic_container:
1234 * Sets the generic container of METHOD to CONTAINER.
1235 * LOCKING: Acquires the image lock.
1238 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1240 g_assert (method->is_generic);
1242 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1246 * mono_class_find_enum_basetype:
1247 * @class: The enum class
1249 * Determine the basetype of an enum by iterating through its fields. We do this
1250 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1253 mono_class_find_enum_basetype (MonoClass *class, MonoError *error)
1255 MonoGenericContainer *container = NULL;
1256 MonoImage *m = class->image;
1257 const int top = class->field.count;
1260 g_assert (class->enumtype);
1262 mono_error_init (error);
1264 if (class->generic_container)
1265 container = class->generic_container;
1266 else if (class->generic_class) {
1267 MonoClass *gklass = class->generic_class->container_class;
1269 container = gklass->generic_container;
1270 g_assert (container);
1274 * Fetch all the field information.
1276 for (i = 0; i < top; i++){
1278 guint32 cols [MONO_FIELD_SIZE];
1279 int idx = class->field.first + i;
1282 /* class->field.first and idx points into the fieldptr table */
1283 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1285 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1288 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1289 mono_error_set_bad_image (error, class->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1293 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1294 mono_metadata_decode_value (sig, &sig);
1295 /* FIELD signature == 0x06 */
1297 mono_error_set_bad_image (error, class->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1301 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1303 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1304 mono_error_set_from_loader_error (error);
1306 mono_error_set_bad_image (error, class->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1309 if (class->generic_class) {
1310 //FIXME do we leak here?
1311 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (class), error);
1312 if (!mono_error_ok (error))
1314 ftype->attrs = cols [MONO_FIELD_FLAGS];
1319 mono_error_set_type_load_class (error, class, "Could not find base type");
1322 g_assert (!mono_loader_get_last_error ());
1327 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1330 mono_type_has_exceptions (MonoType *type)
1332 switch (type->type) {
1333 case MONO_TYPE_CLASS:
1334 case MONO_TYPE_VALUETYPE:
1335 case MONO_TYPE_SZARRAY:
1336 return type->data.klass->exception_type;
1337 case MONO_TYPE_ARRAY:
1338 return type->data.array->eklass->exception_type;
1339 case MONO_TYPE_GENERICINST:
1340 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1348 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1352 mono_class_alloc (MonoClass *class, int size)
1354 if (class->generic_class)
1355 return mono_image_set_alloc (class->generic_class->owner, size);
1357 return mono_image_alloc (class->image, size);
1361 mono_class_alloc0 (MonoClass *class, int size)
1365 res = mono_class_alloc (class, size);
1366 memset (res, 0, size);
1370 #define mono_class_new0(class,struct_type, n_structs) \
1371 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1374 * mono_class_setup_basic_field_info:
1375 * @class: The class to initialize
1377 * Initializes the class->fields.
1378 * LOCKING: Assumes the loader lock is held.
1381 mono_class_setup_basic_field_info (MonoClass *class)
1383 MonoClassField *field;
1391 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1392 image = class->image;
1393 top = class->field.count;
1395 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1397 * This happens when a generic instance of an unfinished generic typebuilder
1398 * is used as an element type for creating an array type. We can't initialize
1399 * the fields of this class using the fields of gklass, since gklass is not
1400 * finished yet, fields could be added to it later.
1406 mono_class_setup_basic_field_info (gtd);
1408 top = gtd->field.count;
1409 class->field.first = gtd->field.first;
1410 class->field.count = gtd->field.count;
1413 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1416 * Fetch all the field information.
1418 for (i = 0; i < top; i++){
1419 field = &class->fields [i];
1420 field->parent = class;
1423 field->name = mono_field_get_name (>d->fields [i]);
1425 int idx = class->field.first + i;
1426 /* class->field.first and idx points into the fieldptr table */
1427 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1428 /* The name is needed for fieldrefs */
1429 field->name = mono_metadata_string_heap (image, name_idx);
1435 * mono_class_setup_fields:
1436 * @class: The class to initialize
1438 * Initializes the class->fields.
1439 * LOCKING: Assumes the loader lock is held.
1442 mono_class_setup_fields (MonoClass *class)
1445 MonoImage *m = class->image;
1447 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1448 int i, blittable = TRUE;
1449 guint32 real_size = 0;
1450 guint32 packing_size = 0;
1451 gboolean explicit_size;
1452 MonoClassField *field;
1453 MonoGenericContainer *container = NULL;
1454 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1457 * FIXME: We have a race condition here. It's possible that this function returns
1458 * to its caller with `instance_size` set to `0` instead of the actual size. This
1459 * is not a problem when the function is called recursively on the same class,
1460 * because the size will be initialized by the outer invocation. What follows is a
1461 * description of how it can occur in other cases, too. There it is a problem,
1462 * because it can lead to the GC being asked to allocate an object of size `0`,
1463 * which SGen chokes on. The race condition is triggered infrequently by
1464 * `tests/sgen-suspend.cs`.
1466 * This function is called for a class whenever one of its subclasses is inited.
1467 * For example, it's called for every subclass of Object. What it does is this:
1469 * if (class->setup_fields_called)
1472 * class->instance_size = 0;
1474 * class->setup_fields_called = 1;
1475 * ... critical point
1476 * class->instance_size = actual_instance_size;
1478 * The last two steps are sometimes reversed, but that only changes the way in which
1479 * the race condition works.
1481 * Assume thread A goes through this function and makes it to the critical point.
1482 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1483 * immediately, but `instance_size` is incorrect.
1485 * The other case looks like this:
1487 * if (class->setup_fields_called)
1489 * ... critical point X
1490 * class->instance_size = 0;
1491 * ... critical point Y
1492 * class->instance_size = actual_instance_size;
1494 * class->setup_fields_called = 1;
1496 * Assume thread A goes through the function and makes it to critical point X. Now
1497 * thread B runs through the whole of the function, returning, assuming
1498 * `instance_size` is set. At that point thread A gets to run and makes it to
1499 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1502 if (class->setup_fields_called)
1505 if (class->generic_class && image_is_dynamic (class->generic_class->container_class->image) && !class->generic_class->container_class->wastypebuilder) {
1507 * This happens when a generic instance of an unfinished generic typebuilder
1508 * is used as an element type for creating an array type. We can't initialize
1509 * the fields of this class using the fields of gklass, since gklass is not
1510 * finished yet, fields could be added to it later.
1515 mono_class_setup_basic_field_info (class);
1516 top = class->field.count;
1519 mono_class_setup_fields (gtd);
1520 if (gtd->exception_type) {
1521 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1526 class->instance_size = 0;
1528 class->sizes.class_size = 0;
1530 if (class->parent) {
1531 /* For generic instances, class->parent might not have been initialized */
1532 mono_class_init (class->parent);
1533 if (!class->parent->size_inited) {
1534 mono_class_setup_fields (class->parent);
1535 if (class->parent->exception_type) {
1536 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1540 class->instance_size += class->parent->instance_size;
1541 class->min_align = class->parent->min_align;
1542 /* we use |= since it may have been set already */
1543 class->has_references |= class->parent->has_references;
1544 blittable = class->parent->blittable;
1546 class->instance_size = sizeof (MonoObject);
1547 class->min_align = 1;
1550 /* We can't really enable 16 bytes alignment until the GC supports it.
1551 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1552 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1553 Bug #506144 is an example of this issue.
1555 if (class->simd_type)
1556 class->min_align = 16;
1558 /* Get the real size */
1559 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1561 if (explicit_size) {
1562 if ((packing_size & 0xfffffff0) != 0) {
1563 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1564 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1567 class->packing_size = packing_size;
1568 real_size += class->instance_size;
1572 if (explicit_size && real_size) {
1573 class->instance_size = MAX (real_size, class->instance_size);
1575 class->blittable = blittable;
1576 mono_memory_barrier ();
1577 class->size_inited = 1;
1578 class->fields_inited = 1;
1579 class->setup_fields_called = 1;
1583 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1586 /* Prevent infinite loops if the class references itself */
1587 class->setup_fields_called = 1;
1589 if (class->generic_container) {
1590 container = class->generic_container;
1592 container = gtd->generic_container;
1593 g_assert (container);
1597 * Fetch all the field information.
1599 for (i = 0; i < top; i++){
1600 int idx = class->field.first + i;
1601 field = &class->fields [i];
1603 field->parent = class;
1606 mono_field_resolve_type (field, &error);
1607 if (!mono_error_ok (&error)) {
1608 /*mono_field_resolve_type already failed class*/
1609 mono_error_cleanup (&error);
1613 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1614 g_assert (field->type);
1617 if (mono_field_is_deleted (field))
1620 MonoClassField *gfield = >d->fields [i];
1621 field->offset = gfield->offset;
1623 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1625 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1626 field->offset = offset;
1628 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1629 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1632 if (field->offset < -1) { /*-1 is used to encode special static fields */
1633 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1636 if (class->generic_container) {
1637 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1643 /* Only do these checks if we still think this type is blittable */
1644 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1645 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1648 MonoClass *field_class = mono_class_from_mono_type (field->type);
1650 mono_class_setup_fields (field_class);
1651 if (field_class->exception_type) {
1652 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1656 if (!field_class || !field_class->blittable)
1661 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1662 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1663 blittable = class->element_class->blittable;
1666 if (mono_type_has_exceptions (field->type)) {
1667 char *class_name = mono_type_get_full_name (class);
1668 char *type_name = mono_type_full_name (field->type);
1670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1671 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1672 g_free (class_name);
1676 /* The def_value of fields is compute lazily during vtable creation */
1679 if (class == mono_defaults.string_class)
1682 class->blittable = blittable;
1684 if (class->enumtype && !mono_class_enum_basetype (class)) {
1685 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1688 if (explicit_size && real_size) {
1689 class->instance_size = MAX (real_size, class->instance_size);
1692 if (class->exception_type)
1694 mono_class_layout_fields (class);
1696 /*valuetypes can't be neither bigger than 1Mb or empty. */
1697 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1698 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1700 mono_memory_barrier ();
1701 class->fields_inited = 1;
1705 * mono_class_setup_fields_locking:
1706 * @class: The class to initialize
1708 * Initializes the class->fields array of fields.
1709 * Aquires the loader lock.
1712 mono_class_setup_fields_locking (MonoClass *class)
1714 /* This can be checked without locks */
1715 if (class->fields_inited)
1717 mono_loader_lock ();
1718 mono_class_setup_fields (class);
1719 mono_loader_unlock ();
1723 * mono_class_has_references:
1725 * Returns whenever @klass->has_references is set, initializing it if needed.
1726 * Aquires the loader lock.
1729 mono_class_has_references (MonoClass *klass)
1731 if (klass->init_pending) {
1732 /* Be conservative */
1735 mono_class_init (klass);
1737 return klass->has_references;
1742 * mono_type_get_basic_type_from_generic:
1745 * Returns a closed type corresponding to the possibly open type
1749 mono_type_get_basic_type_from_generic (MonoType *type)
1751 /* When we do generic sharing we let type variables stand for reference types. */
1752 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1753 return &mono_defaults.object_class->byval_arg;
1758 * mono_class_layout_fields:
1761 * Compute the placement of fields inside an object or struct, according to
1762 * the layout rules and set the following fields in @class:
1763 * - has_references (if the class contains instance references firled or structs that contain references)
1764 * - has_static_refs (same, but for static fields)
1765 * - instance_size (size of the object in memory)
1766 * - class_size (size needed for the static fields)
1767 * - size_inited (flag set when the instance_size is set)
1769 * LOCKING: this is supposed to be called with the loader lock held.
1772 mono_class_layout_fields (MonoClass *class)
1775 const int top = class->field.count;
1776 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1777 guint32 pass, passes, real_size;
1778 gboolean gc_aware_layout = FALSE;
1779 gboolean has_static_fields = FALSE;
1780 MonoClassField *field;
1783 * When we do generic sharing we need to have layout
1784 * information for open generic classes (either with a generic
1785 * context containing type variables or with a generic
1786 * container), so we don't return in that case anymore.
1790 * Enable GC aware auto layout: in this mode, reference
1791 * fields are grouped together inside objects, increasing collector
1793 * Requires that all classes whose layout is known to native code be annotated
1794 * with [StructLayout (LayoutKind.Sequential)]
1795 * Value types have gc_aware_layout disabled by default, as per
1796 * what the default is for other runtimes.
1798 /* corlib is missing [StructLayout] directives in many places */
1799 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1800 if (!class->valuetype)
1801 gc_aware_layout = TRUE;
1804 /* Compute klass->has_references */
1806 * Process non-static fields first, since static fields might recursively
1807 * refer to the class itself.
1809 for (i = 0; i < top; i++) {
1812 field = &class->fields [i];
1814 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1815 ftype = mono_type_get_underlying_type (field->type);
1816 ftype = mono_type_get_basic_type_from_generic (ftype);
1817 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1818 class->has_references = TRUE;
1822 for (i = 0; i < top; i++) {
1825 field = &class->fields [i];
1827 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1828 ftype = mono_type_get_underlying_type (field->type);
1829 ftype = mono_type_get_basic_type_from_generic (ftype);
1830 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1831 class->has_static_refs = TRUE;
1835 for (i = 0; i < top; i++) {
1838 field = &class->fields [i];
1840 ftype = mono_type_get_underlying_type (field->type);
1841 ftype = mono_type_get_basic_type_from_generic (ftype);
1842 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1843 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1844 class->has_static_refs = TRUE;
1846 class->has_references = TRUE;
1851 * Compute field layout and total size (not considering static fields)
1855 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1856 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1858 if (gc_aware_layout)
1863 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1866 if (class->parent) {
1867 mono_class_setup_fields (class->parent);
1868 if (class->parent->exception_type) {
1869 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1872 real_size = class->parent->instance_size;
1874 real_size = sizeof (MonoObject);
1877 for (pass = 0; pass < passes; ++pass) {
1878 for (i = 0; i < top; i++){
1883 field = &class->fields [i];
1885 if (mono_field_is_deleted (field))
1887 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1890 ftype = mono_type_get_underlying_type (field->type);
1891 ftype = mono_type_get_basic_type_from_generic (ftype);
1892 if (gc_aware_layout) {
1893 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1902 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1903 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1904 /* This field is a hack inserted by MCS to empty structures */
1908 size = mono_type_size (field->type, &align);
1910 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1911 align = class->packing_size ? MIN (class->packing_size, align): align;
1912 /* if the field has managed references, we need to force-align it
1915 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1916 align = MAX (align, sizeof (gpointer));
1918 class->min_align = MAX (align, class->min_align);
1919 field->offset = real_size;
1921 field->offset += align - 1;
1922 field->offset &= ~(align - 1);
1924 /*TypeBuilders produce all sort of weird things*/
1925 g_assert (image_is_dynamic (class->image) || field->offset > 0);
1926 real_size = field->offset + size;
1929 class->instance_size = MAX (real_size, class->instance_size);
1931 if (class->instance_size & (class->min_align - 1)) {
1932 class->instance_size += class->min_align - 1;
1933 class->instance_size &= ~(class->min_align - 1);
1937 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
1941 for (i = 0; i < top; i++) {
1946 field = &class->fields [i];
1949 * There must be info about all the fields in a type if it
1950 * uses explicit layout.
1952 if (mono_field_is_deleted (field))
1954 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1957 size = mono_type_size (field->type, &align);
1958 align = class->packing_size ? MIN (class->packing_size, align): align;
1959 class->min_align = MAX (align, class->min_align);
1962 * When we get here, field->offset is already set by the
1963 * loader (for either runtime fields or fields loaded from metadata).
1964 * The offset is from the start of the object: this works for both
1965 * classes and valuetypes.
1967 field->offset += sizeof (MonoObject);
1968 ftype = mono_type_get_underlying_type (field->type);
1969 ftype = mono_type_get_basic_type_from_generic (ftype);
1970 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1971 if (field->offset % sizeof (gpointer)) {
1972 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1979 real_size = MAX (real_size, size + field->offset);
1982 if (class->has_references) {
1983 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
1985 /* Check for overlapping reference and non-reference fields */
1986 for (i = 0; i < top; i++) {
1989 field = &class->fields [i];
1991 if (mono_field_is_deleted (field))
1993 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1995 ftype = mono_type_get_underlying_type (field->type);
1996 if (MONO_TYPE_IS_REFERENCE (ftype))
1997 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
1999 for (i = 0; i < top; i++) {
2000 field = &class->fields [i];
2002 if (mono_field_is_deleted (field))
2004 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2007 // FIXME: Too much code does this
2009 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2010 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);
2011 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2015 g_free (ref_bitmap);
2018 class->instance_size = MAX (real_size, class->instance_size);
2019 if (class->instance_size & (class->min_align - 1)) {
2020 class->instance_size += class->min_align - 1;
2021 class->instance_size &= ~(class->min_align - 1);
2027 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2029 * For small structs, set min_align to at least the struct size to improve
2030 * performance, and since the JIT memset/memcpy code assumes this and generates
2031 * unaligned accesses otherwise. See #78990 for a testcase.
2033 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2034 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
2037 mono_memory_barrier ();
2038 class->size_inited = 1;
2041 * Compute static field layout and size
2043 for (i = 0; i < top; i++){
2047 field = &class->fields [i];
2049 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2051 if (mono_field_is_deleted (field))
2054 if (mono_type_has_exceptions (field->type)) {
2055 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
2059 has_static_fields = TRUE;
2061 size = mono_type_size (field->type, &align);
2062 field->offset = class->sizes.class_size;
2063 /*align is always non-zero here*/
2064 field->offset += align - 1;
2065 field->offset &= ~(align - 1);
2066 class->sizes.class_size = field->offset + size;
2069 if (has_static_fields && class->sizes.class_size == 0)
2070 /* Simplify code which depends on class_size != 0 if the class has static fields */
2071 class->sizes.class_size = 8;
2075 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2079 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2080 method->klass = class;
2081 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2082 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2083 method->signature = sig;
2084 method->name = name;
2087 if (name [0] == '.') {
2088 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2090 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2096 * mono_class_setup_methods:
2099 * Initializes the 'methods' array in CLASS.
2100 * Calling this method should be avoided if possible since it allocates a lot
2101 * of long-living MonoMethod structures.
2102 * Methods belonging to an interface are assigned a sequential slot starting
2105 * On failure this function sets class->exception_type
2108 mono_class_setup_methods (MonoClass *class)
2111 MonoMethod **methods;
2116 if (class->generic_class) {
2118 MonoClass *gklass = class->generic_class->container_class;
2120 mono_class_init (gklass);
2121 if (!gklass->exception_type)
2122 mono_class_setup_methods (gklass);
2123 if (gklass->exception_type) {
2124 /* FIXME make exception_data less opaque so it's possible to dup it here */
2125 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2129 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2130 count = gklass->method.count;
2131 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (count + 1));
2133 for (i = 0; i < count; i++) {
2134 methods [i] = mono_class_inflate_generic_method_full_checked (
2135 gklass->methods [i], class, mono_class_get_context (class), &error);
2136 if (!mono_error_ok (&error)) {
2137 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2138 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)));
2141 mono_error_cleanup (&error);
2145 } else if (class->rank) {
2147 MonoMethod *amethod;
2148 MonoMethodSignature *sig;
2149 int count_generic = 0, first_generic = 0;
2151 gboolean jagged_ctor = FALSE;
2153 count = 3 + (class->rank > 1? 2: 1);
2155 mono_class_setup_interfaces (class, &error);
2156 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2158 if (class->rank == 1 && class->element_class->rank) {
2160 class->method.count ++;
2163 if (class->interface_count) {
2164 count_generic = generic_array_methods (class);
2165 first_generic = count;
2166 count += class->interface_count * count_generic;
2169 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * count);
2171 sig = mono_metadata_signature_alloc (class->image, class->rank);
2172 sig->ret = &mono_defaults.void_class->byval_arg;
2173 sig->pinvoke = TRUE;
2174 sig->hasthis = TRUE;
2175 for (i = 0; i < class->rank; ++i)
2176 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2178 amethod = create_array_method (class, ".ctor", sig);
2179 methods [method_num++] = amethod;
2180 if (class->rank > 1) {
2181 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2182 sig->ret = &mono_defaults.void_class->byval_arg;
2183 sig->pinvoke = TRUE;
2184 sig->hasthis = TRUE;
2185 for (i = 0; i < class->rank * 2; ++i)
2186 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2188 amethod = create_array_method (class, ".ctor", sig);
2189 methods [method_num++] = amethod;
2193 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2194 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2195 sig->ret = &mono_defaults.void_class->byval_arg;
2196 sig->pinvoke = TRUE;
2197 sig->hasthis = TRUE;
2198 for (i = 0; i < class->rank + 1; ++i)
2199 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2200 amethod = create_array_method (class, ".ctor", sig);
2201 methods [method_num++] = amethod;
2204 /* element Get (idx11, [idx2, ...]) */
2205 sig = mono_metadata_signature_alloc (class->image, class->rank);
2206 sig->ret = &class->element_class->byval_arg;
2207 sig->pinvoke = TRUE;
2208 sig->hasthis = TRUE;
2209 for (i = 0; i < class->rank; ++i)
2210 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2211 amethod = create_array_method (class, "Get", sig);
2212 methods [method_num++] = amethod;
2213 /* element& Address (idx11, [idx2, ...]) */
2214 sig = mono_metadata_signature_alloc (class->image, class->rank);
2215 sig->ret = &class->element_class->this_arg;
2216 sig->pinvoke = TRUE;
2217 sig->hasthis = TRUE;
2218 for (i = 0; i < class->rank; ++i)
2219 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2220 amethod = create_array_method (class, "Address", sig);
2221 methods [method_num++] = amethod;
2222 /* void Set (idx11, [idx2, ...], element) */
2223 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2224 sig->ret = &mono_defaults.void_class->byval_arg;
2225 sig->pinvoke = TRUE;
2226 sig->hasthis = TRUE;
2227 for (i = 0; i < class->rank; ++i)
2228 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2229 sig->params [i] = &class->element_class->byval_arg;
2230 amethod = create_array_method (class, "Set", sig);
2231 methods [method_num++] = amethod;
2233 for (i = 0; i < class->interface_count; i++)
2234 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2236 count = class->method.count;
2237 methods = mono_class_alloc (class, sizeof (MonoMethod*) * count);
2238 for (i = 0; i < count; ++i) {
2239 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2240 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2244 if (MONO_CLASS_IS_INTERFACE (class)) {
2246 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2247 for (i = 0; i < count; ++i) {
2248 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2249 methods [i]->slot = slot++;
2253 mono_image_lock (class->image);
2255 if (!class->methods) {
2256 class->method.count = count;
2258 /* Needed because of the double-checking locking pattern */
2259 mono_memory_barrier ();
2261 class->methods = methods;
2264 mono_image_unlock (class->image);
2268 * mono_class_get_method_by_index:
2270 * Returns class->methods [index], initializing class->methods if neccesary.
2272 * LOCKING: Acquires the loader lock.
2275 mono_class_get_method_by_index (MonoClass *class, int index)
2277 /* Avoid calling setup_methods () if possible */
2278 if (class->generic_class && !class->methods) {
2279 MonoClass *gklass = class->generic_class->container_class;
2282 m = mono_class_inflate_generic_method_full (
2283 gklass->methods [index], class, mono_class_get_context (class));
2285 * If setup_methods () is called later for this class, no duplicates are created,
2286 * since inflate_generic_method guarantees that only one instance of a method
2287 * is created for each context.
2290 mono_class_setup_methods (class);
2291 g_assert (m == class->methods [index]);
2295 mono_class_setup_methods (class);
2296 if (class->exception_type) /*FIXME do proper error handling*/
2298 g_assert (index >= 0 && index < class->method.count);
2299 return class->methods [index];
2304 * mono_class_get_inflated_method:
2306 * Given an inflated class CLASS and a method METHOD which should be a method of
2307 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2310 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2312 MonoClass *gklass = class->generic_class->container_class;
2315 g_assert (method->klass == gklass);
2317 mono_class_setup_methods (gklass);
2318 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2320 for (i = 0; i < gklass->method.count; ++i) {
2321 if (gklass->methods [i] == method) {
2323 return class->methods [i];
2325 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2333 * mono_class_get_vtable_entry:
2335 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2336 * LOCKING: Acquires the loader lock.
2339 mono_class_get_vtable_entry (MonoClass *class, int offset)
2343 if (class->rank == 1) {
2345 * szarrays do not overwrite any methods of Array, so we can avoid
2346 * initializing their vtables in some cases.
2348 mono_class_setup_vtable (class->parent);
2349 if (offset < class->parent->vtable_size)
2350 return class->parent->vtable [offset];
2353 if (class->generic_class) {
2354 MonoClass *gklass = class->generic_class->container_class;
2355 mono_class_setup_vtable (gklass);
2356 m = gklass->vtable [offset];
2358 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2360 mono_class_setup_vtable (class);
2361 if (class->exception_type)
2363 m = class->vtable [offset];
2370 * mono_class_get_vtable_size:
2372 * Return the vtable size for KLASS.
2375 mono_class_get_vtable_size (MonoClass *klass)
2377 mono_class_setup_vtable (klass);
2379 return klass->vtable_size;
2383 * mono_class_setup_properties:
2385 * Initialize class->ext.property and class->ext.properties.
2387 * This method can fail the class.
2390 mono_class_setup_properties (MonoClass *class)
2392 guint startm, endm, i, j;
2393 guint32 cols [MONO_PROPERTY_SIZE];
2394 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2395 MonoProperty *properties;
2399 if (class->ext && class->ext->properties)
2402 if (class->generic_class) {
2403 MonoClass *gklass = class->generic_class->container_class;
2405 mono_class_init (gklass);
2406 mono_class_setup_properties (gklass);
2407 if (gklass->exception_type) {
2408 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2412 properties = mono_class_new0 (class, MonoProperty, gklass->ext->property.count + 1);
2414 for (i = 0; i < gklass->ext->property.count; i++) {
2415 MonoProperty *prop = &properties [i];
2417 *prop = gklass->ext->properties [i];
2420 prop->get = mono_class_inflate_generic_method_full (
2421 prop->get, class, mono_class_get_context (class));
2423 prop->set = mono_class_inflate_generic_method_full (
2424 prop->set, class, mono_class_get_context (class));
2426 prop->parent = class;
2429 first = gklass->ext->property.first;
2430 count = gklass->ext->property.count;
2432 first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2433 count = last - first;
2436 mono_class_setup_methods (class);
2437 if (class->exception_type)
2441 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2442 for (i = first; i < last; ++i) {
2443 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2444 properties [i - first].parent = class;
2445 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2446 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2448 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2449 for (j = startm; j < endm; ++j) {
2452 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2454 if (class->image->uncompressed_metadata)
2455 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2456 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2458 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2460 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2461 case METHOD_SEMANTIC_SETTER:
2462 properties [i - first].set = method;
2464 case METHOD_SEMANTIC_GETTER:
2465 properties [i - first].get = method;
2474 mono_class_alloc_ext (class);
2476 mono_image_lock (class->image);
2478 if (class->ext->properties) {
2479 /* We leak 'properties' which was allocated from the image mempool */
2480 mono_image_unlock (class->image);
2484 class->ext->property.first = first;
2485 class->ext->property.count = count;
2487 /* Flush any pending writes as we do double checked locking on class->ext->properties */
2488 mono_memory_barrier ();
2490 /* Leave this assignment as the last op in the function */
2491 class->ext->properties = properties;
2493 mono_image_unlock (class->image);
2497 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2499 MonoMethod **om, **retval;
2502 for (om = methods, count = 0; *om; ++om, ++count)
2505 retval = g_new0 (MonoMethod*, count + 1);
2507 for (om = methods, count = 0; *om; ++om, ++count)
2508 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2513 /*This method can fail the class.*/
2515 mono_class_setup_events (MonoClass *class)
2518 guint startm, endm, i, j;
2519 guint32 cols [MONO_EVENT_SIZE];
2520 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2524 if (class->ext && class->ext->events)
2527 if (class->generic_class) {
2528 MonoClass *gklass = class->generic_class->container_class;
2529 MonoGenericContext *context = NULL;
2531 mono_class_setup_events (gklass);
2532 if (gklass->exception_type) {
2533 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2537 first = gklass->ext->event.first;
2538 count = gklass->ext->event.count;
2540 events = mono_class_new0 (class, MonoEvent, count);
2543 context = mono_class_get_context (class);
2545 for (i = 0; i < count; i++) {
2546 MonoEvent *event = &events [i];
2547 MonoEvent *gevent = &gklass->ext->events [i];
2549 event->parent = class;
2550 event->name = gevent->name;
2551 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2552 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2553 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2554 #ifndef MONO_SMALL_CONFIG
2555 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2557 event->attrs = gevent->attrs;
2560 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2561 count = last - first;
2564 mono_class_setup_methods (class);
2565 if (class->exception_type) {
2566 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2571 events = mono_class_alloc0 (class, sizeof (MonoEvent) * count);
2572 for (i = first; i < last; ++i) {
2573 MonoEvent *event = &events [i - first];
2575 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2576 event->parent = class;
2577 event->attrs = cols [MONO_EVENT_FLAGS];
2578 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2580 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2581 for (j = startm; j < endm; ++j) {
2584 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2586 if (class->image->uncompressed_metadata)
2587 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2588 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2590 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2592 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2593 case METHOD_SEMANTIC_ADD_ON:
2594 event->add = method;
2596 case METHOD_SEMANTIC_REMOVE_ON:
2597 event->remove = method;
2599 case METHOD_SEMANTIC_FIRE:
2600 event->raise = method;
2602 case METHOD_SEMANTIC_OTHER: {
2603 #ifndef MONO_SMALL_CONFIG
2606 if (event->other == NULL) {
2607 event->other = g_new0 (MonoMethod*, 2);
2609 while (event->other [n])
2611 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2613 event->other [n] = method;
2614 /* NULL terminated */
2615 event->other [n + 1] = NULL;
2626 mono_class_alloc_ext (class);
2628 mono_image_lock (class->image);
2630 if (class->ext->events) {
2631 mono_image_unlock (class->image);
2635 class->ext->event.first = first;
2636 class->ext->event.count = count;
2638 /* Flush any pending writes as we do double checked locking on class->ext.events */
2639 mono_memory_barrier ();
2641 /* Leave this assignment as the last op in the function */
2642 class->ext->events = events;
2644 mono_image_unlock (class->image);
2648 * Global pool of interface IDs, represented as a bitset.
2649 * LOCKING: Protected by the classes lock.
2651 static MonoBitSet *global_interface_bitset = NULL;
2654 * mono_unload_interface_ids:
2655 * @bitset: bit set of interface IDs
2657 * When an image is unloaded, the interface IDs associated with
2658 * the image are put back in the global pool of IDs so the numbers
2662 mono_unload_interface_ids (MonoBitSet *bitset)
2665 mono_bitset_sub (global_interface_bitset, bitset);
2670 mono_unload_interface_id (MonoClass *class)
2672 if (global_interface_bitset && class->interface_id) {
2674 mono_bitset_clear (global_interface_bitset, class->interface_id);
2680 * mono_get_unique_iid:
2683 * Assign a unique integer ID to the interface represented by @class.
2684 * The ID will positive and as small as possible.
2685 * LOCKING: Acquires the classes lock.
2686 * Returns: the new ID.
2689 mono_get_unique_iid (MonoClass *class)
2693 g_assert (MONO_CLASS_IS_INTERFACE (class));
2697 if (!global_interface_bitset) {
2698 global_interface_bitset = mono_bitset_new (128, 0);
2701 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2703 int old_size = mono_bitset_size (global_interface_bitset);
2704 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2705 mono_bitset_free (global_interface_bitset);
2706 global_interface_bitset = new_set;
2709 mono_bitset_set (global_interface_bitset, iid);
2710 /* set the bit also in the per-image set */
2711 if (!class->generic_class) {
2712 if (class->image->interface_bitset) {
2713 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2714 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2715 mono_bitset_free (class->image->interface_bitset);
2716 class->image->interface_bitset = new_set;
2719 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2721 mono_bitset_set (class->image->interface_bitset, iid);
2726 #ifndef MONO_SMALL_CONFIG
2727 if (mono_print_vtable) {
2729 char *type_name = mono_type_full_name (&class->byval_arg);
2730 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2731 generic_id = class->generic_class->context.class_inst->id;
2732 g_assert (generic_id != 0);
2736 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2741 g_assert (iid <= 65535);
2746 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2751 mono_class_setup_interfaces (klass, error);
2752 if (!mono_error_ok (error))
2755 for (i = 0; i < klass->interface_count; i++) {
2756 ic = klass->interfaces [i];
2759 *res = g_ptr_array_new ();
2760 g_ptr_array_add (*res, ic);
2761 mono_class_init (ic);
2762 if (ic->exception_type) {
2763 mono_error_set_type_load_class (error, ic, "Error Loading class");
2767 collect_implemented_interfaces_aux (ic, res, error);
2768 if (!mono_error_ok (error))
2774 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2776 GPtrArray *res = NULL;
2778 collect_implemented_interfaces_aux (klass, &res, error);
2779 if (!mono_error_ok (error)) {
2781 g_ptr_array_free (res, TRUE);
2788 compare_interface_ids (const void *p_key, const void *p_element) {
2789 const MonoClass *key = p_key;
2790 const MonoClass *element = *(MonoClass**) p_element;
2792 return (key->interface_id - element->interface_id);
2795 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2797 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2798 MonoClass **result = mono_binary_search (
2800 klass->interfaces_packed,
2801 klass->interface_offsets_count,
2802 sizeof (MonoClass *),
2803 compare_interface_ids);
2805 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2812 * mono_class_interface_offset_with_variance:
2814 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2815 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2817 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2819 * FIXME figure out MS disambiguation rules and fix this function.
2822 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2823 int i = mono_class_interface_offset (klass, itf);
2824 *non_exact_match = FALSE;
2828 if (!mono_class_has_variant_generic_params (itf))
2831 for (i = 0; i < klass->interface_offsets_count; i++) {
2832 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2833 *non_exact_match = TRUE;
2834 return klass->interface_offsets_packed [i];
2842 print_implemented_interfaces (MonoClass *klass) {
2845 GPtrArray *ifaces = NULL;
2847 int ancestor_level = 0;
2849 name = mono_type_get_full_name (klass);
2850 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2853 for (i = 0; i < klass->interface_offsets_count; i++)
2854 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2855 klass->interfaces_packed [i]->interface_id,
2856 klass->interface_offsets_packed [i],
2857 klass->interfaces_packed [i]->method.count,
2858 klass->interfaces_packed [i]->name_space,
2859 klass->interfaces_packed [i]->name );
2860 printf ("Interface flags: ");
2861 for (i = 0; i <= klass->max_interface_id; i++)
2862 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2863 printf ("(%d,T)", i);
2865 printf ("(%d,F)", i);
2867 printf ("Dump interface flags:");
2868 #ifdef COMPRESSED_INTERFACE_BITMAP
2870 const uint8_t* p = klass->interface_bitmap;
2871 i = klass->max_interface_id;
2873 printf (" %d x 00 %02X", p [0], p [1]);
2879 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2880 printf (" %02X", klass->interface_bitmap [i]);
2883 while (klass != NULL) {
2884 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2885 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2886 if (!mono_error_ok (&error)) {
2887 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2888 mono_error_cleanup (&error);
2889 } else if (ifaces) {
2890 for (i = 0; i < ifaces->len; i++) {
2891 MonoClass *ic = g_ptr_array_index (ifaces, i);
2892 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2893 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2895 mono_class_interface_offset (klass, ic),
2900 g_ptr_array_free (ifaces, TRUE);
2903 klass = klass->parent;
2908 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2911 args [0] = &arg0->byval_arg;
2913 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2917 array_class_get_if_rank (MonoClass *class, guint rank)
2919 return rank ? mono_array_class_get (class, rank) : class;
2923 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2925 valuetype_types [0] = eclass;
2926 if (eclass == mono_defaults.int16_class)
2927 valuetype_types [1] = mono_defaults.uint16_class;
2928 else if (eclass == mono_defaults.uint16_class)
2929 valuetype_types [1] = mono_defaults.int16_class;
2930 else if (eclass == mono_defaults.int32_class)
2931 valuetype_types [1] = mono_defaults.uint32_class;
2932 else if (eclass == mono_defaults.uint32_class)
2933 valuetype_types [1] = mono_defaults.int32_class;
2934 else if (eclass == mono_defaults.int64_class)
2935 valuetype_types [1] = mono_defaults.uint64_class;
2936 else if (eclass == mono_defaults.uint64_class)
2937 valuetype_types [1] = mono_defaults.int64_class;
2938 else if (eclass == mono_defaults.byte_class)
2939 valuetype_types [1] = mono_defaults.sbyte_class;
2940 else if (eclass == mono_defaults.sbyte_class)
2941 valuetype_types [1] = mono_defaults.byte_class;
2942 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2943 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2946 /* this won't be needed once bug #325495 is completely fixed
2947 * though we'll need something similar to know which interfaces to allow
2948 * in arrays when they'll be lazyly created
2950 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2951 * MS returns diferrent types based on which instance is called. For example:
2952 * object obj = new byte[10][];
2953 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2954 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2957 * Fixing this should kill quite some code, save some bits and improve compatibility.
2960 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2962 MonoClass *eclass = class->element_class;
2963 static MonoClass* generic_icollection_class = NULL;
2964 static MonoClass* generic_ienumerable_class = NULL;
2965 static MonoClass* generic_ienumerator_class = NULL;
2966 static MonoClass* generic_ireadonlylist_class = NULL;
2967 static MonoClass* generic_ireadonlycollection_class = NULL;
2968 MonoClass *valuetype_types[2] = { NULL, NULL };
2969 MonoClass **interfaces = NULL;
2970 int i, nifaces, interface_count, real_count, original_rank;
2972 gboolean internal_enumerator;
2973 gboolean eclass_is_valuetype;
2975 if (!mono_defaults.generic_ilist_class) {
2979 internal_enumerator = FALSE;
2980 eclass_is_valuetype = FALSE;
2981 original_rank = eclass->rank;
2982 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2983 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2985 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2987 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2988 original_rank = eclass->rank;
2990 eclass = eclass->element_class;
2991 internal_enumerator = TRUE;
2992 *is_enumerator = TRUE;
3000 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3001 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3003 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3005 if (!generic_icollection_class) {
3006 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3007 "System.Collections.Generic", "ICollection`1");
3008 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3009 "System.Collections.Generic", "IEnumerable`1");
3010 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3011 "System.Collections.Generic", "IEnumerator`1");
3012 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3013 "System.Collections.Generic", "IReadOnlyList`1");
3014 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3015 "System.Collections.Generic", "IReadOnlyCollection`1");
3018 mono_class_init (eclass);
3021 * Arrays in 2.0 need to implement a number of generic interfaces
3022 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3023 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3024 * We collect the types needed to build the
3025 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3026 * the generic interfaces needed to implement.
3028 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3029 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3031 if (eclass->valuetype) {
3032 nifaces = generic_ireadonlylist_class ? 5 : 3;
3033 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3035 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3036 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3037 if (internal_enumerator) {
3039 if (valuetype_types [1])
3043 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3044 interfaces [0] = valuetype_types [0];
3045 if (valuetype_types [1])
3046 interfaces [nifaces] = valuetype_types [1];
3048 eclass_is_valuetype = TRUE;
3051 int idepth = eclass->idepth;
3052 if (!internal_enumerator)
3054 nifaces = generic_ireadonlylist_class ? 2 : 3;
3056 // FIXME: This doesn't seem to work/required for generic params
3057 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3058 mono_class_setup_interface_offsets (eclass);
3060 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3061 /* we add object for interfaces and the supertypes for the other
3062 * types. The last of the supertypes is the element class itself which we
3063 * already created the explicit interfaces for (so we include it for IEnumerator
3064 * and exclude it for arrays).
3066 if (MONO_CLASS_IS_INTERFACE (eclass))
3069 interface_count += idepth;
3070 if (eclass->rank && eclass->element_class->valuetype) {
3071 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3072 if (valuetype_types [1])
3075 /* IList, ICollection, IEnumerable, IReadOnlyList */
3076 interface_count *= nifaces;
3077 real_count = interface_count;
3078 if (internal_enumerator) {
3079 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3080 if (valuetype_types [1])
3083 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
3084 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3085 interfaces [0] = mono_defaults.object_class;
3089 for (i = 0; i < idepth; i++) {
3090 mono_class_init (eclass->supertypes [i]);
3091 interfaces [j] = eclass->supertypes [i];
3095 if (all_interfaces) {
3096 for (i = 0; i < eclass->interface_offsets_count; i++) {
3097 interfaces [j] = eclass->interfaces_packed [i];
3101 for (i = 0; i < eclass->interface_count; i++) {
3102 interfaces [j] = eclass->interfaces [i];
3106 if (valuetype_types [1]) {
3107 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3112 /* instantiate the generic interfaces */
3113 for (i = 0; i < interface_count; i += nifaces) {
3114 MonoClass *iface = interfaces [i];
3116 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3117 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3119 if (eclass->valuetype) {
3120 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3121 if (generic_ireadonlylist_class) {
3122 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3123 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3126 if (!generic_ireadonlylist_class)
3127 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3130 if (internal_enumerator) {
3132 /* instantiate IEnumerator<iface> */
3133 for (i = 0; i < interface_count; i++) {
3134 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3136 j = interface_count;
3137 if (!eclass_is_valuetype) {
3138 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3139 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3142 for (i = 0; i < eclass->idepth; i++) {
3143 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3147 for (i = 0; i < eclass->interface_offsets_count; i++) {
3148 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3152 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3154 if (valuetype_types [1])
3155 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3159 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3160 for (i = 0; i < real_count; ++i) {
3161 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3162 g_print ("%s implements %s\n", type_name, name);
3173 find_array_interface (MonoClass *klass, const char *name)
3176 for (i = 0; i < klass->interface_count; ++i) {
3177 if (strcmp (klass->interfaces [i]->name, name) == 0)
3184 * Return the number of virtual methods.
3185 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3186 * Return -1 on failure.
3187 * FIXME It would be nice if this information could be cached somewhere.
3190 count_virtual_methods (MonoClass *class)
3194 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3196 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3197 mono_class_setup_methods (class);
3198 if (class->exception_type)
3201 for (i = 0; i < class->method.count; ++i) {
3202 flags = class->methods [i]->flags;
3203 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3207 for (i = 0; i < class->method.count; ++i) {
3208 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3210 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3218 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3226 m = (l + num_ifaces) / 2;
3227 if (interfaces_full [m] == ic)
3229 if (l == num_ifaces)
3231 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3240 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3242 int i = find_interface (num_ifaces, interfaces_full, ic);
3244 return interface_offsets_full [i];
3249 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3251 int i = find_interface (num_ifaces, interfaces_full, ic);
3255 interface_offsets_full [i] = offset;
3258 for (i = 0; i < num_ifaces; ++i) {
3259 if (interfaces_full [i]) {
3261 if (interfaces_full [i]->interface_id < ic->interface_id)
3264 while (end < num_ifaces && interfaces_full [end]) end++;
3265 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3266 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3268 interfaces_full [i] = ic;
3269 interface_offsets_full [i] = offset;
3275 #ifdef COMPRESSED_INTERFACE_BITMAP
3278 * Compressed interface bitmap design.
3280 * Interface bitmaps take a large amount of memory, because their size is
3281 * linear with the maximum interface id assigned in the process (each interface
3282 * is assigned a unique id as it is loaded). The number of interface classes
3283 * is high because of the many implicit interfaces implemented by arrays (we'll
3284 * need to lazy-load them in the future).
3285 * Most classes implement a very small number of interfaces, so the bitmap is
3286 * sparse. This bitmap needs to be checked by interface casts, so access to the
3287 * needed bit must be fast and doable with few jit instructions.
3289 * The current compression format is as follows:
3290 * *) it is a sequence of one or more two-byte elements
3291 * *) the first byte in the element is the count of empty bitmap bytes
3292 * at the current bitmap position
3293 * *) the second byte in the element is an actual bitmap byte at the current
3296 * As an example, the following compressed bitmap bytes:
3297 * 0x07 0x01 0x00 0x7
3298 * correspond to the following bitmap:
3299 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3301 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3302 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3303 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3307 * mono_compress_bitmap:
3308 * @dest: destination buffer
3309 * @bitmap: bitmap buffer
3310 * @size: size of @bitmap in bytes
3312 * This is a mono internal function.
3313 * The @bitmap data is compressed into a format that is small but
3314 * still searchable in few instructions by the JIT and runtime.
3315 * The compressed data is stored in the buffer pointed to by the
3316 * @dest array. Passing a #NULL value for @dest allows to just compute
3317 * the size of the buffer.
3318 * This compression algorithm assumes the bits set in the bitmap are
3319 * few and far between, like in interface bitmaps.
3320 * Returns: the size of the compressed bitmap in bytes.
3323 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3327 const uint8_t *end = bitmap + size;
3328 while (bitmap < end) {
3329 if (*bitmap || numz == 255) {
3353 * mono_class_interface_match:
3354 * @bitmap: a compressed bitmap buffer
3355 * @id: the index to check in the bitmap
3357 * This is a mono internal function.
3358 * Checks if a bit is set in a compressed interface bitmap. @id must
3359 * be already checked for being smaller than the maximum id encoded in the
3362 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3366 mono_class_interface_match (const uint8_t *bitmap, int id)
3369 id -= bitmap [0] * 8;
3373 return bitmap [1] & (1 << id);
3382 * LOCKING: this is supposed to be called with the loader lock held.
3383 * Return -1 on failure and set exception_type
3386 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3390 int i, j, max_iid, num_ifaces;
3391 MonoClass **interfaces_full = NULL;
3392 int *interface_offsets_full = NULL;
3394 GPtrArray **ifaces_array = NULL;
3395 int interface_offsets_count;
3396 MonoClass **array_interfaces = NULL;
3397 int num_array_interfaces;
3398 int is_enumerator = FALSE;
3400 mono_class_setup_supertypes (class);
3402 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3403 * implicit interfaces have the property that they are assigned the same slot in the
3404 * vtables for compatible interfaces
3406 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3408 /* compute maximum number of slots and maximum interface id */
3410 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3411 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3412 for (j = 0; j < class->idepth; j++) {
3413 k = class->supertypes [j];
3414 num_ifaces += k->interface_count;
3415 for (i = 0; i < k->interface_count; i++) {
3416 ic = k->interfaces [i];
3419 mono_class_init (ic);
3421 if (max_iid < ic->interface_id)
3422 max_iid = ic->interface_id;
3424 ifaces = mono_class_get_implemented_interfaces (k, &error);
3425 if (!mono_error_ok (&error)) {
3426 char *name = mono_type_get_full_name (k);
3427 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)));
3429 mono_error_cleanup (&error);
3434 num_ifaces += ifaces->len;
3435 for (i = 0; i < ifaces->len; ++i) {
3436 ic = g_ptr_array_index (ifaces, i);
3437 if (max_iid < ic->interface_id)
3438 max_iid = ic->interface_id;
3440 ifaces_array [j] = ifaces;
3444 for (i = 0; i < num_array_interfaces; ++i) {
3445 ic = array_interfaces [i];
3446 mono_class_init (ic);
3447 if (max_iid < ic->interface_id)
3448 max_iid = ic->interface_id;
3451 if (MONO_CLASS_IS_INTERFACE (class)) {
3453 if (max_iid < class->interface_id)
3454 max_iid = class->interface_id;
3456 class->max_interface_id = max_iid;
3457 /* compute vtable offset for interfaces */
3458 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3459 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3461 for (i = 0; i < num_ifaces; i++) {
3462 interface_offsets_full [i] = -1;
3465 /* skip the current class */
3466 for (j = 0; j < class->idepth - 1; j++) {
3467 k = class->supertypes [j];
3468 ifaces = ifaces_array [j];
3471 for (i = 0; i < ifaces->len; ++i) {
3473 ic = g_ptr_array_index (ifaces, i);
3475 /*Force the sharing of interface offsets between parent and subtypes.*/
3476 io = mono_class_interface_offset (k, ic);
3478 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3483 g_assert (class == class->supertypes [class->idepth - 1]);
3484 ifaces = ifaces_array [class->idepth - 1];
3486 for (i = 0; i < ifaces->len; ++i) {
3488 ic = g_ptr_array_index (ifaces, i);
3489 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3491 count = count_virtual_methods (ic);
3493 char *name = mono_type_get_full_name (ic);
3494 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3503 if (MONO_CLASS_IS_INTERFACE (class))
3504 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3506 if (num_array_interfaces) {
3507 if (is_enumerator) {
3508 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3509 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3510 g_assert (ienumerator_offset >= 0);
3511 for (i = 0; i < num_array_interfaces; ++i) {
3512 ic = array_interfaces [i];
3513 if (strcmp (ic->name, "IEnumerator`1") == 0)
3514 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3516 g_assert_not_reached ();
3517 /*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);*/
3520 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3521 int ilist_iface_idx = find_array_interface (class, "IList`1");
3522 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3523 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3524 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3525 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3526 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3527 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3528 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3529 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3530 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3531 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3532 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3533 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3534 for (i = 0; i < num_array_interfaces; ++i) {
3536 ic = array_interfaces [i];
3537 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3538 offset = ilist_offset;
3539 else if (strcmp (ic->name, "ICollection`1") == 0)
3540 offset = icollection_offset;
3541 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3542 offset = ienumerable_offset;
3543 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3544 offset = ireadonlylist_offset;
3545 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3546 offset = ireadonlycollection_offset;
3548 g_assert_not_reached ();
3549 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3550 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3555 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3556 if (interface_offsets_full [i] != -1) {
3557 interface_offsets_count ++;
3562 * We might get called multiple times:
3563 * - mono_class_init ()
3564 * - mono_class_setup_vtable ().
3565 * - mono_class_setup_interface_offsets ().
3566 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3567 * means we have to overwrite those when called from other places (#4440).
3569 if (class->interfaces_packed && !overwrite) {
3570 g_assert (class->interface_offsets_count == interface_offsets_count);
3574 class->interface_offsets_count = interface_offsets_count;
3575 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3576 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3577 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3578 #ifdef COMPRESSED_INTERFACE_BITMAP
3579 bitmap = g_malloc0 (bsize);
3581 bitmap = mono_class_alloc0 (class, bsize);
3583 for (i = 0; i < interface_offsets_count; i++) {
3584 int id = interfaces_full [i]->interface_id;
3585 bitmap [id >> 3] |= (1 << (id & 7));
3586 class->interfaces_packed [i] = interfaces_full [i];
3587 class->interface_offsets_packed [i] = interface_offsets_full [i];
3588 /*if (num_array_interfaces)
3589 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]);*/
3591 #ifdef COMPRESSED_INTERFACE_BITMAP
3592 i = mono_compress_bitmap (NULL, bitmap, bsize);
3593 class->interface_bitmap = mono_class_alloc0 (class, i);
3594 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3597 class->interface_bitmap = bitmap;
3602 g_free (interfaces_full);
3603 g_free (interface_offsets_full);
3604 g_free (array_interfaces);
3605 for (i = 0; i < class->idepth; i++) {
3606 ifaces = ifaces_array [i];
3608 g_ptr_array_free (ifaces, TRUE);
3610 g_free (ifaces_array);
3612 //printf ("JUST DONE: ");
3613 //print_implemented_interfaces (class);
3619 * Setup interface offsets for interfaces.
3621 * - class->max_interface_id
3622 * - class->interface_offsets_count
3623 * - class->interfaces_packed
3624 * - class->interface_offsets_packed
3625 * - class->interface_bitmap
3627 * This function can fail @class.
3630 mono_class_setup_interface_offsets (MonoClass *class)
3632 mono_loader_lock ();
3634 setup_interface_offsets (class, 0, FALSE);
3636 mono_loader_unlock ();
3639 /*Checks if @klass has @parent as one of it's parents type gtd
3643 * Bar<T> : Foo<Bar<Bar<T>>>
3647 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3649 klass = mono_class_get_generic_type_definition (klass);
3650 parent = mono_class_get_generic_type_definition (parent);
3651 mono_class_setup_supertypes (klass);
3652 mono_class_setup_supertypes (parent);
3654 return klass->idepth >= parent->idepth &&
3655 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3659 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3661 MonoGenericInst *ginst;
3663 if (!class->generic_class) {
3664 mono_class_setup_vtable_full (class, in_setup);
3665 return class->exception_type == 0;
3668 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3669 if (class->generic_class->container_class->exception_type) {
3670 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3674 ginst = class->generic_class->context.class_inst;
3675 for (i = 0; i < ginst->type_argc; ++i) {
3677 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3679 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3680 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3681 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3683 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3684 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3692 * mono_class_setup_vtable:
3694 * Creates the generic vtable of CLASS.
3695 * Initializes the following fields in MonoClass:
3698 * Plus all the fields initialized by setup_interface_offsets ().
3699 * If there is an error during vtable construction, class->exception_type is set.
3701 * LOCKING: Acquires the loader lock.
3704 mono_class_setup_vtable (MonoClass *class)
3706 mono_class_setup_vtable_full (class, NULL);
3710 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3712 MonoMethod **overrides;
3713 MonoGenericContext *context;
3721 if (MONO_CLASS_IS_INTERFACE (class)) {
3722 /* This sets method->slot for all methods if this is an interface */
3723 mono_class_setup_methods (class);
3727 if (class->exception_type)
3730 if (g_list_find (in_setup, class))
3733 mono_loader_lock ();
3735 if (class->vtable) {
3736 mono_loader_unlock ();
3740 mono_stats.generic_vtable_count ++;
3741 in_setup = g_list_prepend (in_setup, class);
3743 if (class->generic_class) {
3744 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3745 mono_loader_unlock ();
3746 g_list_remove (in_setup, class);
3750 context = mono_class_get_context (class);
3751 type_token = class->generic_class->container_class->type_token;
3753 context = (MonoGenericContext *) class->generic_container;
3754 type_token = class->type_token;
3757 if (image_is_dynamic (class->image)) {
3758 /* Generic instances can have zero method overrides without causing any harm.
3759 * This is true since we don't do layout all over again for them, we simply inflate
3760 * the layout of the parent.
3762 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3764 /* The following call fails if there are missing methods in the type */
3765 /* FIXME it's probably a good idea to avoid this for generic instances. */
3766 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3770 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3772 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3776 mono_loader_unlock ();
3777 g_list_remove (in_setup, class);
3782 #define DEBUG_INTERFACE_VTABLE_CODE 0
3783 #define TRACE_INTERFACE_VTABLE_CODE 0
3784 #define VERIFY_INTERFACE_VTABLE_CODE 0
3785 #define VTABLE_SELECTOR (1)
3787 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3788 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3789 if (!(VTABLE_SELECTOR)) break; \
3793 #define DEBUG_INTERFACE_VTABLE(stmt)
3796 #if TRACE_INTERFACE_VTABLE_CODE
3797 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3798 if (!(VTABLE_SELECTOR)) break; \
3802 #define TRACE_INTERFACE_VTABLE(stmt)
3805 #if VERIFY_INTERFACE_VTABLE_CODE
3806 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3807 if (!(VTABLE_SELECTOR)) break; \
3811 #define VERIFY_INTERFACE_VTABLE(stmt)
3815 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3817 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3821 GString *res = g_string_new ("");
3823 g_string_append_c (res, '(');
3824 for (i = 0; i < sig->param_count; ++i) {
3826 g_string_append_c (res, ',');
3827 mono_type_get_desc (res, sig->params [i], include_namespace);
3829 g_string_append (res, ")=>");
3830 if (sig->ret != NULL) {
3831 mono_type_get_desc (res, sig->ret, include_namespace);
3833 g_string_append (res, "NULL");
3836 g_string_free (res, FALSE);
3840 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3841 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3842 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3843 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3851 is_wcf_hack_disabled (void)
3853 static gboolean disabled;
3854 static gboolean inited = FALSE;
3856 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3863 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) {
3864 MonoMethodSignature *cmsig, *imsig;
3865 if (strcmp (im->name, cm->name) == 0) {
3866 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3867 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3870 if (! slot_is_empty) {
3871 if (require_newslot) {
3872 if (! interface_is_explicitly_implemented_by_class) {
3873 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3876 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3877 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3881 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3884 cmsig = mono_method_signature (cm);
3885 imsig = mono_method_signature (im);
3886 if (!cmsig || !imsig) {
3887 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3891 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3892 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3893 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3894 TRACE_INTERFACE_VTABLE (printf ("]"));
3897 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3898 /* CAS - SecurityAction.InheritanceDemand on interface */
3899 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3900 mono_secman_inheritancedemand_method (cm, im);
3903 if (mono_security_core_clr_enabled ())
3904 mono_security_core_clr_check_override (class, cm, im);
3906 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3907 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3908 char *body_name = mono_method_full_name (cm, TRUE);
3909 char *decl_name = mono_method_full_name (im, TRUE);
3910 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));
3918 MonoClass *ic = im->klass;
3919 const char *ic_name_space = ic->name_space;
3920 const char *ic_name = ic->name;
3923 if (! require_newslot) {
3924 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3927 if (cm->klass->rank == 0) {
3928 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3931 cmsig = mono_method_signature (cm);
3932 imsig = mono_method_signature (im);
3933 if (!cmsig || !imsig) {
3934 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3938 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3939 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3940 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3941 TRACE_INTERFACE_VTABLE (printf ("]"));
3944 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3945 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3948 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3949 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3952 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))) {
3953 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3957 subname = strstr (cm->name, ic_name_space);
3958 if (subname != cm->name) {
3959 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3962 subname += strlen (ic_name_space);
3963 if (subname [0] != '.') {
3964 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3968 if (strstr (subname, ic_name) != subname) {
3969 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3972 subname += strlen (ic_name);
3973 if (subname [0] != '.') {
3974 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3978 if (strcmp (subname, im->name) != 0) {
3979 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3983 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3984 /* CAS - SecurityAction.InheritanceDemand on interface */
3985 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3986 mono_secman_inheritancedemand_method (cm, im);
3989 if (mono_security_core_clr_enabled ())
3990 mono_security_core_clr_check_override (class, cm, im);
3992 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3993 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3994 char *body_name = mono_method_full_name (cm, TRUE);
3995 char *decl_name = mono_method_full_name (im, TRUE);
3996 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));
4006 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4008 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4009 MonoMethod *method = key;
4010 MonoMethod *override = value;
4011 MonoClass *method_class = mono_method_get_class (method);
4012 MonoClass *override_class = mono_method_get_class (override);
4014 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4015 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4016 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4019 print_overrides (GHashTable *override_map, const char *message) {
4021 printf ("Override map \"%s\" START:\n", message);
4022 g_hash_table_foreach (override_map, foreach_override, NULL);
4023 printf ("Override map \"%s\" END.\n", message);
4025 printf ("Override map \"%s\" EMPTY.\n", message);
4029 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4030 char *full_name = mono_type_full_name (&class->byval_arg);
4034 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4036 if (print_interfaces) {
4037 print_implemented_interfaces (class);
4038 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4041 if (class->parent) {
4042 parent_size = class->parent->vtable_size;
4046 for (i = 0; i < size; ++i) {
4047 MonoMethod *cm = vtable [i];
4048 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4049 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4051 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4059 #if VERIFY_INTERFACE_VTABLE_CODE
4061 mono_method_try_get_vtable_index (MonoMethod *method)
4063 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4064 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4065 if (imethod->declaring->is_generic)
4066 return imethod->declaring->slot;
4068 return method->slot;
4072 mono_class_verify_vtable (MonoClass *class)
4075 char *full_name = mono_type_full_name (&class->byval_arg);
4077 printf ("*** Verifying VTable of class '%s' \n", full_name);
4081 if (!class->methods)
4084 for (i = 0; i < class->method.count; ++i) {
4085 MonoMethod *cm = class->methods [i];
4088 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4092 full_name = mono_method_full_name (cm, TRUE);
4094 slot = mono_method_try_get_vtable_index (cm);
4096 if (slot >= class->vtable_size) {
4097 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
4101 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
4102 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
4103 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4104 g_free (other_name);
4107 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4114 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4116 char *method_signature;
4119 for (index = 0; index < onum; ++index) {
4120 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4121 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4123 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4124 type_name = mono_type_full_name (&class->byval_arg);
4125 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4126 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4127 g_free (method_signature);
4129 mono_class_setup_methods (class);
4130 if (class->exception_type) {
4131 char *name = mono_type_get_full_name (class);
4132 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4136 for (index = 0; index < class->method.count; ++index) {
4137 MonoMethod *cm = class->methods [index];
4138 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4140 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4141 g_free (method_signature);
4146 mono_method_get_method_definition (MonoMethod *method)
4148 while (method->is_inflated)
4149 method = ((MonoMethodInflated*)method)->declaring;
4154 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4158 for (i = 0; i < onum; ++i) {
4159 MonoMethod *decl = overrides [i * 2];
4160 MonoMethod *body = overrides [i * 2 + 1];
4162 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4163 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4167 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4168 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4169 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4171 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4175 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4176 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4177 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4179 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4183 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4184 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4188 body = mono_method_get_method_definition (body);
4189 decl = mono_method_get_method_definition (decl);
4191 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4192 char *body_name = mono_method_full_name (body, TRUE);
4193 char *decl_name = mono_method_full_name (decl, TRUE);
4194 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));
4204 mono_class_need_stelemref_method (MonoClass *class)
4206 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4210 * LOCKING: this is supposed to be called with the loader lock held.
4213 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4217 MonoMethod **vtable;
4218 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4219 GPtrArray *ifaces = NULL;
4220 GHashTable *override_map = NULL;
4221 gboolean security_enabled = mono_security_enabled ();
4223 gpointer class_iter;
4224 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4225 int first_non_interface_slot;
4227 GSList *virt_methods = NULL, *l;
4228 int stelemref_slot = 0;
4233 if (overrides && !verify_class_overrides (class, overrides, onum))
4236 ifaces = mono_class_get_implemented_interfaces (class, &error);
4237 if (!mono_error_ok (&error)) {
4238 char *name = mono_type_get_full_name (class);
4239 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)));
4241 mono_error_cleanup (&error);
4243 } else if (ifaces) {
4244 for (i = 0; i < ifaces->len; i++) {
4245 MonoClass *ic = g_ptr_array_index (ifaces, i);
4246 max_vtsize += ic->method.count;
4248 g_ptr_array_free (ifaces, TRUE);
4252 if (class->parent) {
4253 mono_class_init (class->parent);
4254 mono_class_setup_vtable_full (class->parent, in_setup);
4256 if (class->parent->exception_type) {
4257 char *name = mono_type_get_full_name (class->parent);
4258 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4263 max_vtsize += class->parent->vtable_size;
4264 cur_slot = class->parent->vtable_size;
4267 max_vtsize += class->method.count;
4269 /*Array have a slot for stelemref*/
4270 if (mono_class_need_stelemref_method (class)) {
4271 stelemref_slot = cur_slot;
4276 vtable = alloca (sizeof (gpointer) * max_vtsize);
4277 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4279 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4281 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4282 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4285 max_iid = class->max_interface_id;
4286 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4288 /* Optimized version for generic instances */
4289 if (class->generic_class) {
4291 MonoClass *gklass = class->generic_class->container_class;
4294 mono_class_setup_vtable_full (gklass, in_setup);
4295 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4296 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4300 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4301 class->vtable_size = gklass->vtable_size;
4302 for (i = 0; i < gklass->vtable_size; ++i)
4303 if (gklass->vtable [i]) {
4304 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4305 if (!mono_error_ok (&error)) {
4306 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4307 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4309 mono_error_cleanup (&error);
4313 tmp [i]->slot = gklass->vtable [i]->slot;
4315 mono_memory_barrier ();
4316 class->vtable = tmp;
4318 /* Have to set method->slot for abstract virtual methods */
4319 if (class->methods && gklass->methods) {
4320 for (i = 0; i < class->method.count; ++i)
4321 if (class->methods [i]->slot == -1)
4322 class->methods [i]->slot = gklass->methods [i]->slot;
4328 if (class->parent && class->parent->vtable_size) {
4329 MonoClass *parent = class->parent;
4332 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4334 // Also inherit parent interface vtables, just as a starting point.
4335 // This is needed otherwise bug-77127.exe fails when the property methods
4336 // have different names in the iterface and the class, because for child
4337 // classes the ".override" information is not used anymore.
4338 for (i = 0; i < parent->interface_offsets_count; i++) {
4339 MonoClass *parent_interface = parent->interfaces_packed [i];
4340 int interface_offset = mono_class_interface_offset (class, parent_interface);
4341 /*FIXME this is now dead code as this condition will never hold true.
4342 Since interface offsets are inherited then the offset of an interface implemented
4343 by a parent will never be the out of it's vtable boundary.
4345 if (interface_offset >= parent->vtable_size) {
4346 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4349 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4350 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4351 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4352 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4353 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4354 parent_interface_offset + j, parent_interface_offset, j,
4355 interface_offset + j, interface_offset, j));
4362 /*Array have a slot for stelemref*/
4363 if (mono_class_need_stelemref_method (class)) {
4364 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4366 method->slot = stelemref_slot;
4368 g_assert (method->slot == stelemref_slot);
4370 vtable [stelemref_slot] = method;
4373 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4374 /* override interface methods */
4375 for (i = 0; i < onum; i++) {
4376 MonoMethod *decl = overrides [i*2];
4377 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4379 dslot = mono_method_get_vtable_slot (decl);
4381 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4385 dslot += mono_class_interface_offset (class, decl->klass);
4386 vtable [dslot] = overrides [i*2 + 1];
4387 vtable [dslot]->slot = dslot;
4389 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4391 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4393 if (mono_security_core_clr_enabled ())
4394 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4397 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4398 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4401 * Create a list of virtual methods to avoid calling
4402 * mono_class_get_virtual_methods () which is slow because of the metadata
4406 gpointer iter = NULL;
4409 virt_methods = NULL;
4410 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4411 virt_methods = g_slist_prepend (virt_methods, cm);
4413 if (class->exception_type)
4417 // Loop on all implemented interfaces...
4418 for (i = 0; i < class->interface_offsets_count; i++) {
4419 MonoClass *parent = class->parent;
4421 gboolean interface_is_explicitly_implemented_by_class;
4424 ic = class->interfaces_packed [i];
4425 ic_offset = mono_class_interface_offset (class, ic);
4427 mono_class_setup_methods (ic);
4428 if (ic->exception_type)
4431 // Check if this interface is explicitly implemented (instead of just inherited)
4432 if (parent != NULL) {
4433 int implemented_interfaces_index;
4434 interface_is_explicitly_implemented_by_class = FALSE;
4435 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4436 if (ic == class->interfaces [implemented_interfaces_index]) {
4437 interface_is_explicitly_implemented_by_class = TRUE;
4442 interface_is_explicitly_implemented_by_class = TRUE;
4445 // Loop on all interface methods...
4446 for (im_index = 0; im_index < ic->method.count; im_index++) {
4447 MonoMethod *im = ic->methods [im_index];
4448 int im_slot = ic_offset + im->slot;
4449 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4451 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4454 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4456 // If there is an explicit implementation, just use it right away,
4457 // otherwise look for a matching method
4458 if (override_im == NULL) {
4463 // First look for a suitable method among the class methods
4465 for (l = virt_methods; l; l = l->next) {
4467 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)));
4468 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4469 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4470 vtable [im_slot] = cm;
4471 /* Why do we need this? */
4476 TRACE_INTERFACE_VTABLE (printf ("\n"));
4477 if (class->exception_type) /*Might be set by check_interface_method_override*/
4481 // If the slot is still empty, look in all the inherited virtual methods...
4482 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4483 MonoClass *parent = class->parent;
4484 // Reverse order, so that last added methods are preferred
4485 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4486 MonoMethod *cm = parent->vtable [cm_index];
4488 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));
4489 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4490 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4491 vtable [im_slot] = cm;
4492 /* Why do we need this? */
4498 if (class->exception_type) /*Might be set by check_interface_method_override*/
4500 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4504 g_assert (vtable [im_slot] == override_im);
4509 // If the class is not abstract, check that all its interface slots are full.
4510 // The check is done here and not directly at the end of the loop above because
4511 // it can happen (for injected generic array interfaces) that the same slot is
4512 // processed multiple times (those interfaces have overlapping slots), and it
4513 // will not always be the first pass the one that fills the slot.
4514 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4515 for (i = 0; i < class->interface_offsets_count; i++) {
4519 ic = class->interfaces_packed [i];
4520 ic_offset = mono_class_interface_offset (class, ic);
4522 for (im_index = 0; im_index < ic->method.count; im_index++) {
4523 MonoMethod *im = ic->methods [im_index];
4524 int im_slot = ic_offset + im->slot;
4526 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4529 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4530 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4531 if (vtable [im_slot] == NULL) {
4532 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4539 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4541 for (l = virt_methods; l; l = l->next) {
4544 * If the method is REUSE_SLOT, we must check in the
4545 * base class for a method to override.
4547 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4549 for (k = class->parent; k ; k = k->parent) {
4554 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4555 MonoMethodSignature *cmsig, *m1sig;
4557 cmsig = mono_method_signature (cm);
4558 m1sig = mono_method_signature (m1);
4560 if (!cmsig || !m1sig) {
4561 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4565 if (!strcmp(cm->name, m1->name) &&
4566 mono_metadata_signature_equal (cmsig, m1sig)) {
4568 /* CAS - SecurityAction.InheritanceDemand */
4569 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4570 mono_secman_inheritancedemand_method (cm, m1);
4573 if (mono_security_core_clr_enabled ())
4574 mono_security_core_clr_check_override (class, cm, m1);
4576 slot = mono_method_get_vtable_slot (m1);
4580 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4581 char *body_name = mono_method_full_name (cm, TRUE);
4582 char *decl_name = mono_method_full_name (m1, TRUE);
4583 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));
4589 g_assert (cm->slot < max_vtsize);
4591 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4592 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4593 mono_method_full_name (m1, 1), m1,
4594 mono_method_full_name (cm, 1), cm));
4595 g_hash_table_insert (override_map, m1, cm);
4599 if (k->exception_type)
4609 /*Non final newslot methods must be given a non-interface vtable slot*/
4610 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4614 cm->slot = cur_slot++;
4616 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4617 vtable [cm->slot] = cm;
4620 /* override non interface methods */
4621 for (i = 0; i < onum; i++) {
4622 MonoMethod *decl = overrides [i*2];
4623 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4624 g_assert (decl->slot != -1);
4625 vtable [decl->slot] = overrides [i*2 + 1];
4626 overrides [i * 2 + 1]->slot = decl->slot;
4628 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4629 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4630 mono_method_full_name (decl, 1), decl,
4631 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4632 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4634 if (mono_security_core_clr_enabled ())
4635 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4640 * If a method occupies more than one place in the vtable, and it is
4641 * overriden, then change the other occurances too.
4646 for (i = 0; i < max_vtsize; ++i)
4648 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4650 cm = g_hash_table_lookup (override_map, vtable [i]);
4655 g_hash_table_destroy (override_map);
4656 override_map = NULL;
4659 g_slist_free (virt_methods);
4660 virt_methods = NULL;
4662 /* Ensure that all vtable slots are filled with concrete instance methods */
4663 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4664 for (i = 0; i < cur_slot; ++i) {
4665 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4666 char *type_name = mono_type_get_full_name (class);
4667 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4668 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));
4670 g_free (method_name);
4676 if (class->generic_class) {
4677 MonoClass *gklass = class->generic_class->container_class;
4679 mono_class_init (gklass);
4681 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4683 /* Check that the vtable_size value computed in mono_class_init () is correct */
4684 if (class->vtable_size)
4685 g_assert (cur_slot == class->vtable_size);
4686 class->vtable_size = cur_slot;
4689 /* Try to share the vtable with our parent. */
4690 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4691 mono_memory_barrier ();
4692 class->vtable = class->parent->vtable;
4694 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4695 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4696 mono_memory_barrier ();
4697 class->vtable = tmp;
4700 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4701 if (mono_print_vtable) {
4704 print_implemented_interfaces (class);
4706 for (i = 0; i <= max_iid; i++)
4707 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4710 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4711 class->vtable_size, icount);
4713 for (i = 0; i < cur_slot; ++i) {
4718 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4719 mono_method_full_name (cm, TRUE));
4725 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4726 class->name, max_iid);
4728 for (i = 0; i < class->interface_count; i++) {
4729 ic = class->interfaces [i];
4730 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4731 mono_class_interface_offset (class, ic),
4732 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4735 for (k = class->parent; k ; k = k->parent) {
4736 for (i = 0; i < k->interface_count; i++) {
4737 ic = k->interfaces [i];
4738 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4739 mono_class_interface_offset (class, ic),
4740 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4746 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4751 char *name = mono_type_get_full_name (class);
4752 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4755 g_hash_table_destroy (override_map);
4757 g_slist_free (virt_methods);
4762 * mono_method_get_vtable_slot:
4764 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4765 * LOCKING: Acquires the loader lock.
4767 * FIXME Use proper MonoError machinery here.
4770 mono_method_get_vtable_slot (MonoMethod *method)
4772 if (method->slot == -1) {
4773 mono_class_setup_vtable (method->klass);
4774 if (method->klass->exception_type)
4776 if (method->slot == -1) {
4780 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4781 g_assert (method->klass->generic_class);
4782 gklass = method->klass->generic_class->container_class;
4783 mono_class_setup_methods (method->klass);
4784 g_assert (method->klass->methods);
4785 for (i = 0; i < method->klass->method.count; ++i) {
4786 if (method->klass->methods [i] == method)
4789 g_assert (i < method->klass->method.count);
4790 g_assert (gklass->methods);
4791 method->slot = gklass->methods [i]->slot;
4793 g_assert (method->slot != -1);
4795 return method->slot;
4799 * mono_method_get_vtable_index:
4802 * Returns the index into the runtime vtable to access the method or,
4803 * in the case of a virtual generic method, the virtual generic method
4804 * thunk. Returns -1 on failure.
4806 * FIXME Use proper MonoError machinery here.
4809 mono_method_get_vtable_index (MonoMethod *method)
4811 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4812 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4813 if (imethod->declaring->is_generic)
4814 return mono_method_get_vtable_slot (imethod->declaring);
4816 return mono_method_get_vtable_slot (method);
4819 static MonoMethod *default_ghc = NULL;
4820 static MonoMethod *default_finalize = NULL;
4821 static int finalize_slot = -1;
4822 static int ghc_slot = -1;
4825 initialize_object_slots (MonoClass *class)
4830 if (class == mono_defaults.object_class) {
4831 mono_class_setup_vtable (class);
4832 for (i = 0; i < class->vtable_size; ++i) {
4833 MonoMethod *cm = class->vtable [i];
4835 if (!strcmp (cm->name, "GetHashCode"))
4837 else if (!strcmp (cm->name, "Finalize"))
4841 g_assert (ghc_slot > 0);
4842 default_ghc = class->vtable [ghc_slot];
4844 g_assert (finalize_slot > 0);
4845 default_finalize = class->vtable [finalize_slot];
4850 MonoMethod *array_method;
4852 } GenericArrayMethodInfo;
4854 static int generic_array_method_num = 0;
4855 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4858 generic_array_methods (MonoClass *class)
4860 int i, count_generic = 0;
4861 GList *list = NULL, *tmp;
4862 if (generic_array_method_num)
4863 return generic_array_method_num;
4864 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4865 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4866 for (i = 0; i < class->parent->method.count; i++) {
4867 MonoMethod *m = class->parent->methods [i];
4868 if (!strncmp (m->name, "InternalArray__", 15)) {
4870 list = g_list_prepend (list, m);
4873 list = g_list_reverse (list);
4874 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4876 for (tmp = list; tmp; tmp = tmp->next) {
4877 const char *mname, *iname;
4879 MonoMethod *m = tmp->data;
4880 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4881 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4883 generic_array_method_info [i].array_method = m;
4884 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4885 iname = "System.Collections.Generic.ICollection`1.";
4886 mname = m->name + 27;
4887 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4888 iname = "System.Collections.Generic.IEnumerable`1.";
4889 mname = m->name + 27;
4890 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4891 iname = "System.Collections.Generic.IReadOnlyList`1.";
4892 mname = m->name + strlen (ireadonlylist_prefix);
4893 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4894 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4895 mname = m->name + strlen (ireadonlycollection_prefix);
4896 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4897 iname = "System.Collections.Generic.IList`1.";
4898 mname = m->name + 15;
4900 g_assert_not_reached ();
4903 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4904 strcpy (name, iname);
4905 strcpy (name + strlen (iname), mname);
4906 generic_array_method_info [i].name = name;
4909 /*g_print ("array generic methods: %d\n", count_generic);*/
4911 generic_array_method_num = count_generic;
4913 return generic_array_method_num;
4917 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4919 MonoGenericContext tmp_context;
4922 tmp_context.class_inst = NULL;
4923 tmp_context.method_inst = iface->generic_class->context.class_inst;
4924 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4926 for (i = 0; i < generic_array_method_num; i++) {
4927 MonoMethod *m = generic_array_method_info [i].array_method;
4928 MonoMethod *inflated;
4930 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4931 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4936 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4938 int null_length = strlen ("(null)");
4939 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4940 char *s = mono_image_alloc (image, len);
4943 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4944 g_assert (result == len - 1);
4950 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4952 gpointer exception_data = NULL;
4954 switch (error->exception_type) {
4955 case MONO_EXCEPTION_TYPE_LOAD:
4956 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4959 case MONO_EXCEPTION_MISSING_METHOD:
4960 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4963 case MONO_EXCEPTION_MISSING_FIELD: {
4964 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4965 const char *class_name;
4968 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4970 class_name = error->klass->name;
4972 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4975 g_free ((void*)class_name);
4979 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4982 if (error->ref_only)
4983 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.";
4985 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4987 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4991 case MONO_EXCEPTION_BAD_IMAGE:
4992 exception_data = error->msg;
4996 g_assert_not_reached ();
4999 mono_class_set_failure (class, error->exception_type, exception_data);
5004 * @class: the class to initialize
5006 * Compute the instance_size, class_size and other infos that cannot be
5007 * computed at mono_class_get() time. Also compute vtable_size if possible.
5008 * Returns TRUE on success or FALSE if there was a problem in loading
5009 * the type (incorrect assemblies, missing assemblies, methods, etc).
5011 * LOCKING: Acquires the loader lock.
5014 mono_class_init (MonoClass *class)
5017 MonoCachedClassInfo cached_info;
5018 gboolean has_cached_info;
5022 /* Double-checking locking pattern */
5023 if (class->inited || class->exception_type)
5024 return class->exception_type == MONO_EXCEPTION_NONE;
5026 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
5028 /* We do everything inside the lock to prevent races */
5029 mono_loader_lock ();
5031 if (class->inited || class->exception_type) {
5032 mono_loader_unlock ();
5033 /* Somebody might have gotten in before us */
5034 return class->exception_type == MONO_EXCEPTION_NONE;
5037 if (class->init_pending) {
5038 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5042 class->init_pending = 1;
5044 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
5045 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
5050 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
5051 MonoClass *element_class = class->element_class;
5052 if (!element_class->inited)
5053 mono_class_init (element_class);
5054 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5055 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5060 /* CAS - SecurityAction.InheritanceDemand */
5061 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
5062 mono_secman_inheritancedemand_class (class, class->parent);
5065 mono_stats.initialized_class_count++;
5067 if (class->generic_class && !class->generic_class->is_dynamic) {
5068 MonoClass *gklass = class->generic_class->container_class;
5070 mono_stats.generic_class_count++;
5072 class->method = gklass->method;
5073 class->field = gklass->field;
5075 mono_class_init (gklass);
5076 // FIXME: Why is this needed ?
5077 if (!gklass->exception_type)
5078 mono_class_setup_methods (gklass);
5079 if (gklass->exception_type) {
5080 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5084 if (MONO_CLASS_IS_INTERFACE (class))
5085 class->interface_id = mono_get_unique_iid (class);
5088 if (class->parent && !class->parent->inited)
5089 mono_class_init (class->parent);
5091 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
5093 if (class->generic_class || image_is_dynamic (class->image) || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
5094 class->nested_classes_inited = TRUE;
5097 * Computes the size used by the fields, and their locations
5099 if (has_cached_info) {
5100 class->instance_size = cached_info.instance_size;
5101 class->sizes.class_size = cached_info.class_size;
5102 class->packing_size = cached_info.packing_size;
5103 class->min_align = cached_info.min_align;
5104 class->blittable = cached_info.blittable;
5105 class->has_references = cached_info.has_references;
5106 class->has_static_refs = cached_info.has_static_refs;
5107 class->no_special_static_fields = cached_info.no_special_static_fields;
5110 if (!class->size_inited){
5111 mono_class_setup_fields (class);
5112 if (class->exception_type || mono_loader_get_last_error ())
5116 /* Initialize arrays */
5118 class->method.count = 3 + (class->rank > 1? 2: 1);
5120 if (class->interface_count) {
5121 int count_generic = generic_array_methods (class);
5122 class->method.count += class->interface_count * count_generic;
5126 mono_class_setup_supertypes (class);
5129 initialize_object_slots (class);
5132 * Initialize the rest of the data without creating a generic vtable if possible.
5133 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5134 * also avoid computing a generic vtable.
5136 if (has_cached_info) {
5138 class->vtable_size = cached_info.vtable_size;
5139 class->has_finalize = cached_info.has_finalize;
5140 class->has_finalize_inited = TRUE;
5141 class->ghcimpl = cached_info.ghcimpl;
5142 class->has_cctor = cached_info.has_cctor;
5143 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5144 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5145 * The first slot if for array with.
5147 static int szarray_vtable_size[2] = { 0 };
5149 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5152 if (!szarray_vtable_size [slot]) {
5153 mono_class_setup_vtable (class);
5154 szarray_vtable_size [slot] = class->vtable_size;
5156 class->vtable_size = szarray_vtable_size[slot];
5158 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5159 MonoClass *gklass = class->generic_class->container_class;
5161 /* Generic instance case */
5162 class->ghcimpl = gklass->ghcimpl;
5163 class->has_cctor = gklass->has_cctor;
5165 mono_class_setup_vtable (gklass);
5166 if (gklass->exception_type) {
5167 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5171 class->vtable_size = gklass->vtable_size;
5175 /* ghcimpl is not currently used
5177 if (class->parent) {
5178 MonoMethod *cmethod = class->vtable [ghc_slot];
5179 if (cmethod->is_inflated)
5180 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5181 if (cmethod == default_ghc) {
5187 /* C# doesn't allow interfaces to have cctors */
5188 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5189 MonoMethod *cmethod = NULL;
5191 if (class->type_token) {
5192 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5193 /* The find_method function ignores the 'flags' argument */
5194 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5195 class->has_cctor = 1;
5197 mono_class_setup_methods (class);
5198 if (class->exception_type)
5201 for (i = 0; i < class->method.count; ++i) {
5202 MonoMethod *method = class->methods [i];
5203 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5204 (strcmp (".cctor", method->name) == 0)) {
5205 class->has_cctor = 1;
5213 if (class->parent) {
5214 int first_iface_slot;
5215 /* This will compute class->parent->vtable_size for some classes */
5216 mono_class_init (class->parent);
5217 if (class->parent->exception_type) {
5218 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5221 if (mono_loader_get_last_error ())
5223 if (!class->parent->vtable_size) {
5224 /* FIXME: Get rid of this somehow */
5225 mono_class_setup_vtable (class->parent);
5226 if (class->parent->exception_type) {
5227 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5230 if (mono_loader_get_last_error ())
5233 first_iface_slot = class->parent->vtable_size;
5234 if (mono_class_need_stelemref_method (class))
5236 setup_interface_offsets (class, first_iface_slot, TRUE);
5238 setup_interface_offsets (class, 0, TRUE);
5241 if (mono_security_core_clr_enabled ())
5242 mono_security_core_clr_check_inheritance (class);
5244 if (mono_loader_get_last_error ()) {
5245 if (class->exception_type == MONO_EXCEPTION_NONE) {
5246 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5248 mono_loader_clear_error ();
5251 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5252 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5257 /* Because of the double-checking locking pattern */
5258 mono_memory_barrier ();
5260 class->init_pending = 0;
5262 mono_loader_unlock ();
5264 return class->exception_type == MONO_EXCEPTION_NONE;
5268 * mono_class_has_finalizer:
5270 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5274 mono_class_has_finalizer (MonoClass *klass)
5276 MonoClass *class = klass;
5277 gboolean has_finalize = FALSE;
5279 if (klass->has_finalize_inited)
5280 return klass->has_finalize;
5282 /* Interfaces and valuetypes are not supposed to have finalizers */
5283 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5284 MonoMethod *cmethod = NULL;
5286 if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5287 } else if (class->generic_class) {
5288 MonoClass *gklass = class->generic_class->container_class;
5290 has_finalize = mono_class_has_finalizer (gklass);
5291 } else if (class->parent && class->parent->has_finalize) {
5292 has_finalize = TRUE;
5294 if (class->parent) {
5296 * Can't search in metadata for a method named Finalize, because that
5297 * ignores overrides.
5299 mono_class_setup_vtable (class);
5300 if (class->exception_type || mono_loader_get_last_error ())
5303 cmethod = class->vtable [finalize_slot];
5307 g_assert (class->vtable_size > finalize_slot);
5309 if (class->parent) {
5310 if (cmethod->is_inflated)
5311 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5312 if (cmethod != default_finalize)
5313 has_finalize = TRUE;
5319 mono_image_lock (klass->image);
5321 if (!klass->has_finalize_inited) {
5322 klass->has_finalize = has_finalize ? 1 : 0;
5324 mono_memory_barrier ();
5325 klass->has_finalize_inited = TRUE;
5328 mono_image_unlock (klass->image);
5330 return klass->has_finalize;
5334 mono_is_corlib_image (MonoImage *image)
5336 /* FIXME: allow the dynamic case for our compilers and with full trust */
5337 if (image_is_dynamic (image))
5338 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5340 return image == mono_defaults.corlib;
5344 * LOCKING: this assumes the loader lock is held
5347 mono_class_setup_mono_type (MonoClass *class)
5349 const char *name = class->name;
5350 const char *nspace = class->name_space;
5351 gboolean is_corlib = mono_is_corlib_image (class->image);
5353 class->this_arg.byref = 1;
5354 class->this_arg.data.klass = class;
5355 class->this_arg.type = MONO_TYPE_CLASS;
5356 class->byval_arg.data.klass = class;
5357 class->byval_arg.type = MONO_TYPE_CLASS;
5359 if (is_corlib && !strcmp (nspace, "System")) {
5360 if (!strcmp (name, "ValueType")) {
5362 * do not set the valuetype bit for System.ValueType.
5363 * class->valuetype = 1;
5365 class->blittable = TRUE;
5366 } else if (!strcmp (name, "Enum")) {
5368 * do not set the valuetype bit for System.Enum.
5369 * class->valuetype = 1;
5371 class->valuetype = 0;
5372 class->enumtype = 0;
5373 } else if (!strcmp (name, "Object")) {
5374 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5375 } else if (!strcmp (name, "String")) {
5376 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5377 } else if (!strcmp (name, "TypedReference")) {
5378 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5382 if (class->valuetype) {
5383 int t = MONO_TYPE_VALUETYPE;
5385 if (is_corlib && !strcmp (nspace, "System")) {
5388 if (!strcmp (name, "Boolean")) {
5389 t = MONO_TYPE_BOOLEAN;
5390 } else if (!strcmp(name, "Byte")) {
5392 class->blittable = TRUE;
5396 if (!strcmp (name, "Char")) {
5401 if (!strcmp (name, "Double")) {
5403 class->blittable = TRUE;
5407 if (!strcmp (name, "Int32")) {
5409 class->blittable = TRUE;
5410 } else if (!strcmp(name, "Int16")) {
5412 class->blittable = TRUE;
5413 } else if (!strcmp(name, "Int64")) {
5415 class->blittable = TRUE;
5416 } else if (!strcmp(name, "IntPtr")) {
5418 class->blittable = TRUE;
5422 if (!strcmp (name, "Single")) {
5424 class->blittable = TRUE;
5425 } else if (!strcmp(name, "SByte")) {
5427 class->blittable = TRUE;
5431 if (!strcmp (name, "UInt32")) {
5433 class->blittable = TRUE;
5434 } else if (!strcmp(name, "UInt16")) {
5436 class->blittable = TRUE;
5437 } else if (!strcmp(name, "UInt64")) {
5439 class->blittable = TRUE;
5440 } else if (!strcmp(name, "UIntPtr")) {
5442 class->blittable = TRUE;
5446 if (!strcmp (name, "TypedReference")) {
5447 t = MONO_TYPE_TYPEDBYREF;
5448 class->blittable = TRUE;
5452 if (!strcmp (name, "Void")) {
5460 class->this_arg.type = class->byval_arg.type = t;
5463 if (MONO_CLASS_IS_INTERFACE (class))
5464 class->interface_id = mono_get_unique_iid (class);
5470 * COM initialization is delayed until needed.
5471 * However when a [ComImport] attribute is present on a type it will trigger
5472 * the initialization. This is not a problem unless the BCL being executed
5473 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5476 init_com_from_comimport (MonoClass *class)
5478 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5479 if (mono_security_core_clr_enabled ()) {
5480 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5481 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5482 /* but it can not be made available for application (i.e. user code) since all COM calls
5483 * are considered native calls. In this case we fail with a TypeLoadException (just like
5484 * Silverlight 2 does */
5485 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5490 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5492 #endif /*DISABLE_COM*/
5495 * LOCKING: this assumes the loader lock is held
5498 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5500 gboolean system_namespace;
5501 gboolean is_corlib = mono_is_corlib_image (class->image);
5503 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5505 /* if root of the hierarchy */
5506 if (system_namespace && !strcmp (class->name, "Object")) {
5507 class->parent = NULL;
5508 class->instance_size = sizeof (MonoObject);
5511 if (!strcmp (class->name, "<Module>")) {
5512 class->parent = NULL;
5513 class->instance_size = 0;
5517 if (!MONO_CLASS_IS_INTERFACE (class)) {
5518 /* Imported COM Objects always derive from __ComObject. */
5520 if (MONO_CLASS_IS_IMPORT (class)) {
5521 init_com_from_comimport (class);
5522 if (parent == mono_defaults.object_class)
5523 parent = mono_class_get_com_object_class ();
5527 /* set the parent to something useful and safe, but mark the type as broken */
5528 parent = mono_defaults.object_class;
5529 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5532 class->parent = parent;
5534 if (parent->generic_class && !parent->name) {
5536 * If the parent is a generic instance, we may get
5537 * called before it is fully initialized, especially
5538 * before it has its name.
5543 #ifndef DISABLE_REMOTING
5544 class->marshalbyref = parent->marshalbyref;
5545 class->contextbound = parent->contextbound;
5548 class->delegate = parent->delegate;
5550 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5551 mono_class_set_is_com_object (class);
5553 if (system_namespace) {
5554 #ifndef DISABLE_REMOTING
5555 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5556 class->marshalbyref = 1;
5558 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5559 class->contextbound = 1;
5561 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5562 class->delegate = 1;
5565 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5566 (strcmp (class->parent->name_space, "System") == 0)))
5567 class->valuetype = 1;
5568 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5569 class->valuetype = class->enumtype = 1;
5571 /*class->enumtype = class->parent->enumtype; */
5573 /* initialize com types if COM interfaces are present */
5575 if (MONO_CLASS_IS_IMPORT (class))
5576 init_com_from_comimport (class);
5578 class->parent = NULL;
5584 * mono_class_setup_supertypes:
5587 * Build the data structure needed to make fast type checks work.
5588 * This currently sets two fields in @class:
5589 * - idepth: distance between @class and System.Object in the type
5591 * - supertypes: array of classes: each element has a class in the hierarchy
5592 * starting from @class up to System.Object
5594 * LOCKING: This function is atomic, in case of contention we waste memory.
5597 mono_class_setup_supertypes (MonoClass *class)
5600 MonoClass **supertypes;
5602 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5606 if (class->parent && !class->parent->supertypes)
5607 mono_class_setup_supertypes (class->parent);
5609 class->idepth = class->parent->idepth + 1;
5613 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5614 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5616 if (class->parent) {
5617 supertypes [class->idepth - 1] = class;
5618 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5620 supertypes [0] = class;
5623 mono_atomic_store_release (&class->supertypes, supertypes);
5627 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5629 MonoClass *gtd = (MonoClass*)user_data;
5630 /* Only try to fix generic instances of @gtd */
5631 if (gclass->generic_class->container_class != gtd)
5634 /* Check if the generic instance has no parent. */
5635 if (gtd->parent && !gclass->parent)
5636 mono_generic_class_setup_parent (gclass, gtd);
5642 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5644 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5645 mono_error_set_type_load_class (error, class, msg);
5649 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5651 MonoLoaderError *lerror = mono_loader_get_last_error ();
5654 set_failure_from_loader_error (class, lerror);
5655 mono_error_set_from_loader_error (error);
5659 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5660 mono_error_set_type_load_class (error, class, msg);
5665 * mono_class_create_from_typedef:
5666 * @image: image where the token is valid
5667 * @type_token: typedef token
5668 * @error: used to return any error found while creating the type
5670 * Create the MonoClass* representing the specified type token.
5671 * @type_token must be a TypeDef token.
5673 * FIXME: don't return NULL on failure, just the the caller figure it out.
5676 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5678 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5679 MonoClass *class, *parent = NULL;
5680 guint32 cols [MONO_TYPEDEF_SIZE];
5681 guint32 cols_next [MONO_TYPEDEF_SIZE];
5682 guint tidx = mono_metadata_token_index (type_token);
5683 MonoGenericContext *context = NULL;
5684 const char *name, *nspace;
5686 MonoClass **interfaces;
5687 guint32 field_last, method_last;
5688 guint32 nesting_tokeen;
5690 mono_error_init (error);
5692 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5693 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5694 g_assert (!mono_loader_get_last_error ());
5698 mono_loader_lock ();
5700 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5701 mono_loader_unlock ();
5702 g_assert (!mono_loader_get_last_error ());
5706 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5708 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5709 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5711 class = mono_image_alloc0 (image, sizeof (MonoClass));
5714 class->name_space = nspace;
5716 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5718 class->image = image;
5719 class->type_token = type_token;
5720 class->flags = cols [MONO_TYPEDEF_FLAGS];
5722 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5724 classes_size += sizeof (MonoClass);
5727 * Check whether we're a generic type definition.
5729 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5730 if (class->generic_container) {
5731 class->is_generic = 1;
5732 class->generic_container->owner.klass = class;
5733 context = &class->generic_container->context;
5736 if (class->generic_container)
5737 enable_gclass_recording ();
5739 if (cols [MONO_TYPEDEF_EXTENDS]) {
5741 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5743 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5744 /*WARNING: this must satisfy mono_metadata_type_hash*/
5745 class->this_arg.byref = 1;
5746 class->this_arg.data.klass = class;
5747 class->this_arg.type = MONO_TYPE_CLASS;
5748 class->byval_arg.data.klass = class;
5749 class->byval_arg.type = MONO_TYPE_CLASS;
5751 parent = mono_class_get_checked (image, parent_token, error);
5752 if (parent && context) /* Always inflate */
5753 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5755 if (parent == NULL) {
5756 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5757 goto parent_failure;
5760 for (tmp = parent; tmp; tmp = tmp->parent) {
5762 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5763 goto parent_failure;
5765 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5766 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5767 goto parent_failure;
5772 mono_class_setup_parent (class, parent);
5774 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5775 mono_class_setup_mono_type (class);
5777 if (class->generic_container)
5778 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5781 * This might access class->byval_arg for recursion generated by generic constraints,
5782 * so it has to come after setup_mono_type ().
5784 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5785 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5786 if (!mono_error_ok (error)) {
5787 /*FIXME implement a mono_class_set_failure_from_mono_error */
5788 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5789 mono_loader_unlock ();
5790 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5791 g_assert (!mono_loader_get_last_error ());
5796 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5800 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5804 class->cast_class = class->element_class = class;
5806 if (!class->enumtype) {
5807 if (!mono_metadata_interfaces_from_typedef_full (
5808 image, type_token, &interfaces, &icount, FALSE, context)){
5809 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5810 mono_loader_unlock ();
5811 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5815 class->interfaces = interfaces;
5816 class->interface_count = icount;
5817 class->interfaces_inited = 1;
5820 /*g_print ("Load class %s\n", name);*/
5823 * Compute the field and method lists
5825 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5826 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5828 if (tt->rows > tidx){
5829 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5830 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5831 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5833 field_last = image->tables [MONO_TABLE_FIELD].rows;
5834 method_last = image->tables [MONO_TABLE_METHOD].rows;
5837 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5838 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5839 class->field.count = field_last - class->field.first;
5841 class->field.count = 0;
5843 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5844 class->method.count = method_last - class->method.first;
5846 class->method.count = 0;
5848 /* reserve space to store vector pointer in arrays */
5849 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5850 class->instance_size += 2 * sizeof (gpointer);
5851 g_assert (class->field.count == 0);
5854 if (class->enumtype) {
5855 MonoType *enum_basetype = mono_class_find_enum_basetype (class, error);
5856 if (!enum_basetype) {
5857 /*set it to a default value as the whole runtime can't handle this to be null*/
5858 class->cast_class = class->element_class = mono_defaults.int32_class;
5859 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5860 mono_loader_unlock ();
5861 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5862 g_assert (!mono_loader_get_last_error ());
5865 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5869 * If we're a generic type definition, load the constraints.
5870 * We must do this after the class has been constructed to make certain recursive scenarios
5873 if (class->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, class->generic_container, error)) {
5874 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)));
5875 mono_loader_unlock ();
5876 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5877 g_assert (!mono_loader_get_last_error ());
5881 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5882 if (!strncmp (name, "Vector", 6))
5883 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");
5886 mono_loader_unlock ();
5888 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5889 g_assert (!mono_loader_get_last_error ());
5894 mono_class_setup_mono_type (class);
5895 mono_loader_unlock ();
5896 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5897 g_assert (!mono_loader_get_last_error ());
5901 /** is klass Nullable<T>? */
5903 mono_class_is_nullable (MonoClass *klass)
5905 return klass->generic_class != NULL &&
5906 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5910 /** if klass is T? return T */
5912 mono_class_get_nullable_param (MonoClass *klass)
5914 g_assert (mono_class_is_nullable (klass));
5915 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5919 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5923 MonoGenericClass *gclass = klass->generic_class;
5925 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5926 if (!mono_error_ok (&error)) {
5927 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5928 klass->parent = mono_defaults.object_class;
5929 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5930 mono_error_cleanup (&error);
5934 mono_class_setup_parent (klass, klass->parent);
5936 if (klass->enumtype) {
5937 klass->cast_class = gtd->cast_class;
5938 klass->element_class = gtd->element_class;
5944 * Create the `MonoClass' for an instantiation of a generic type.
5945 * We only do this if we actually need it.
5948 mono_generic_class_get_class (MonoGenericClass *gclass)
5950 MonoClass *klass, *gklass;
5952 if (gclass->cached_class)
5953 return gclass->cached_class;
5955 mono_loader_lock ();
5956 if (gclass->cached_class) {
5957 mono_loader_unlock ();
5958 return gclass->cached_class;
5961 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5963 gklass = gclass->container_class;
5965 if (record_gclass_instantiation > 0)
5966 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5968 if (gklass->nested_in) {
5969 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5970 klass->nested_in = gklass->nested_in;
5973 klass->name = gklass->name;
5974 klass->name_space = gklass->name_space;
5976 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5978 klass->image = gklass->image;
5979 klass->flags = gklass->flags;
5980 klass->type_token = gklass->type_token;
5981 klass->field.count = gklass->field.count;
5983 klass->is_inflated = 1;
5984 klass->generic_class = gclass;
5986 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5987 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5988 klass->this_arg.byref = TRUE;
5989 klass->enumtype = gklass->enumtype;
5990 klass->valuetype = gklass->valuetype;
5992 klass->cast_class = klass->element_class = klass;
5994 if (mono_class_is_nullable (klass))
5995 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5998 * We're not interested in the nested classes of a generic instance.
5999 * We use the generic type definition to look for nested classes.
6002 mono_generic_class_setup_parent (klass, gklass);
6004 if (gclass->is_dynamic) {
6007 mono_class_setup_supertypes (klass);
6009 if (klass->enumtype) {
6011 * For enums, gklass->fields might not been set, but instance_size etc. is
6012 * already set in mono_reflection_create_internal_class (). For non-enums,
6013 * these will be computed normally in mono_class_layout_fields ().
6015 klass->instance_size = gklass->instance_size;
6016 klass->sizes.class_size = gklass->sizes.class_size;
6017 mono_memory_barrier ();
6018 klass->size_inited = 1;
6022 mono_memory_barrier ();
6023 gclass->cached_class = klass;
6025 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6027 inflated_classes ++;
6028 inflated_classes_size += sizeof (MonoClass);
6030 mono_loader_unlock ();
6036 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
6038 MonoClass *klass, **ptr;
6040 MonoGenericContainer *container = mono_generic_param_owner (param);
6044 image = mono_defaults.corlib;
6046 klass = mono_image_alloc0 (image, sizeof (MonoClass));
6047 classes_size += sizeof (MonoClass);
6050 klass->name = pinfo->name;
6052 int n = mono_generic_param_num (param);
6053 klass->name = mono_image_alloc0 (image, 16);
6054 sprintf ((char*)klass->name, "%d", n);
6059 MonoMethod *omethod = container->owner.method;
6060 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
6062 MonoClass *oklass = container->owner.klass;
6063 klass->name_space = oklass ? oklass->name_space : "";
6066 klass->name_space = "";
6069 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6073 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6077 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6078 klass->parent = pinfo->constraints [0];
6080 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
6081 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
6083 klass->parent = mono_defaults.object_class;
6086 if (count - pos > 0) {
6087 klass->interface_count = count - pos;
6088 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
6089 klass->interfaces_inited = TRUE;
6090 for (i = pos; i < count; i++)
6091 klass->interfaces [i - pos] = pinfo->constraints [i];
6094 klass->image = image;
6096 klass->inited = TRUE;
6097 klass->cast_class = klass->element_class = klass;
6098 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6100 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6101 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
6102 klass->this_arg.byref = TRUE;
6104 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6105 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6107 /*Init these fields to sane values*/
6108 klass->min_align = 1;
6109 klass->instance_size = sizeof (gpointer);
6110 mono_memory_barrier ();
6111 klass->size_inited = 1;
6113 mono_class_setup_supertypes (klass);
6115 if (count - pos > 0) {
6116 mono_class_setup_vtable (klass->parent);
6117 if (klass->parent->exception_type)
6118 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6120 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6126 #define FAST_CACHE_SIZE 16
6129 * LOCKING: Takes the image lock depending on @take_lock.
6132 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, gboolean take_lock)
6134 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6135 MonoImage *image = param->image;
6140 if (n < FAST_CACHE_SIZE) {
6142 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6144 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6146 MonoClass *klass = NULL;
6147 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6150 mono_image_lock (image);
6151 klass = g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6153 mono_image_unlock (image);
6160 * LOCKING: Image lock (param->image) must be held
6163 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6165 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6166 MonoImage *image = param->image;
6170 if (n < FAST_CACHE_SIZE) {
6172 /* Requires locking to avoid droping an already published class */
6173 if (!image->mvar_cache_fast)
6174 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6175 image->mvar_cache_fast [n] = klass;
6177 if (!image->var_cache_fast)
6178 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6179 image->var_cache_fast [n] = klass;
6182 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6184 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6186 ht = g_hash_table_new (NULL, NULL);
6187 mono_memory_barrier ();
6189 image->mvar_cache_slow = ht;
6191 image->var_cache_slow = ht;
6194 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6199 * LOCKING: Acquires the image lock (@image).
6202 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6204 MonoGenericContainer *container = mono_generic_param_owner (param);
6205 MonoGenericParamInfo *pinfo = NULL;
6206 MonoClass *klass, *klass2;
6209 pinfo = mono_generic_param_info (param);
6210 klass = pinfo->pklass;
6213 klass = get_anon_gparam_class (param, is_mvar, TRUE);
6218 if (!image && container) {
6220 MonoMethod *method = container->owner.method;
6221 image = (method && method->klass) ? method->klass->image : NULL;
6223 MonoClass *klass = container->owner.klass;
6224 // FIXME: 'klass' should not be null
6225 // But, monodis creates GenericContainers without associating a owner to it
6226 image = klass ? klass->image : NULL;
6230 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6232 mono_memory_barrier ();
6234 if (!image) //FIXME is this only needed by monodis? Can't we fix monodis instead of having this hack?
6235 image = mono_defaults.corlib;
6237 mono_image_lock (image);
6239 klass2 = pinfo->pklass;
6241 klass2 = get_anon_gparam_class (param, is_mvar, FALSE);
6247 pinfo->pklass = klass;
6249 set_anon_gparam_class (param, is_mvar, klass);
6251 mono_image_unlock (image);
6253 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6255 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED);
6257 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6263 mono_ptr_class_get (MonoType *type)
6266 MonoClass *el_class;
6270 el_class = mono_class_from_mono_type (type);
6271 image = el_class->image;
6273 mono_image_lock (image);
6274 if (image->ptr_cache) {
6275 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6276 mono_image_unlock (image);
6280 mono_image_unlock (image);
6282 result = mono_image_alloc0 (image, sizeof (MonoClass));
6284 classes_size += sizeof (MonoClass);
6286 result->parent = NULL; /* no parent for PTR types */
6287 result->name_space = el_class->name_space;
6288 name = g_strdup_printf ("%s*", el_class->name);
6289 result->name = mono_image_strdup (image, name);
6292 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6294 result->image = el_class->image;
6295 result->inited = TRUE;
6296 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6297 /* Can pointers get boxed? */
6298 result->instance_size = sizeof (gpointer);
6299 result->cast_class = result->element_class = el_class;
6300 result->blittable = TRUE;
6302 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6303 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6304 result->this_arg.byref = TRUE;
6306 mono_class_setup_supertypes (result);
6308 mono_image_lock (image);
6309 if (image->ptr_cache) {
6311 if ((result2 = g_hash_table_lookup (image->ptr_cache, el_class))) {
6312 mono_image_unlock (image);
6313 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6317 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6319 g_hash_table_insert (image->ptr_cache, el_class, result);
6320 mono_image_unlock (image);
6322 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6328 mono_fnptr_class_get (MonoMethodSignature *sig)
6331 static GHashTable *ptr_hash = NULL;
6333 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6335 mono_loader_lock ();
6338 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6340 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6341 mono_loader_unlock ();
6344 result = g_new0 (MonoClass, 1);
6346 result->parent = NULL; /* no parent for PTR types */
6347 result->name_space = "System";
6348 result->name = "MonoFNPtrFakeClass";
6350 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6352 result->image = mono_defaults.corlib; /* need to fix... */
6353 result->inited = TRUE;
6354 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6355 /* Can pointers get boxed? */
6356 result->instance_size = sizeof (gpointer);
6357 result->cast_class = result->element_class = result;
6358 result->blittable = TRUE;
6360 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6361 result->this_arg.data.method = result->byval_arg.data.method = sig;
6362 result->this_arg.byref = TRUE;
6363 result->blittable = TRUE;
6365 mono_class_setup_supertypes (result);
6367 g_hash_table_insert (ptr_hash, sig, result);
6369 mono_loader_unlock ();
6371 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6377 mono_class_from_mono_type (MonoType *type)
6379 switch (type->type) {
6380 case MONO_TYPE_OBJECT:
6381 return type->data.klass? type->data.klass: mono_defaults.object_class;
6382 case MONO_TYPE_VOID:
6383 return type->data.klass? type->data.klass: mono_defaults.void_class;
6384 case MONO_TYPE_BOOLEAN:
6385 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6386 case MONO_TYPE_CHAR:
6387 return type->data.klass? type->data.klass: mono_defaults.char_class;
6389 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6391 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6393 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6395 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6397 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6399 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6401 return type->data.klass? type->data.klass: mono_defaults.int_class;
6403 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6405 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6407 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6409 return type->data.klass? type->data.klass: mono_defaults.single_class;
6411 return type->data.klass? type->data.klass: mono_defaults.double_class;
6412 case MONO_TYPE_STRING:
6413 return type->data.klass? type->data.klass: mono_defaults.string_class;
6414 case MONO_TYPE_TYPEDBYREF:
6415 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6416 case MONO_TYPE_ARRAY:
6417 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6419 return mono_ptr_class_get (type->data.type);
6420 case MONO_TYPE_FNPTR:
6421 return mono_fnptr_class_get (type->data.method);
6422 case MONO_TYPE_SZARRAY:
6423 return mono_array_class_get (type->data.klass, 1);
6424 case MONO_TYPE_CLASS:
6425 case MONO_TYPE_VALUETYPE:
6426 return type->data.klass;
6427 case MONO_TYPE_GENERICINST:
6428 return mono_generic_class_get_class (type->data.generic_class);
6430 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6431 case MONO_TYPE_MVAR:
6432 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6434 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6435 g_assert_not_reached ();
6442 * mono_type_retrieve_from_typespec
6443 * @image: context where the image is created
6444 * @type_spec: typespec token
6445 * @context: the generic context used to evaluate generic instantiations in
6448 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6450 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6452 *did_inflate = FALSE;
6457 if (context && (context->class_inst || context->method_inst)) {
6458 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6460 if (!mono_error_ok (error)) {
6461 g_assert (!mono_loader_get_last_error ());
6467 *did_inflate = TRUE;
6474 * mono_class_create_from_typespec
6475 * @image: context where the image is created
6476 * @type_spec: typespec token
6477 * @context: the generic context used to evaluate generic instantiations in
6480 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6483 gboolean inflated = FALSE;
6484 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6485 if (!mono_error_ok (error))
6487 ret = mono_class_from_mono_type (t);
6489 mono_metadata_free_type (t);
6494 * mono_bounded_array_class_get:
6495 * @element_class: element class
6496 * @rank: the dimension of the array class
6497 * @bounded: whenever the array has non-zero bounds
6499 * Returns: a class object describing the array with element type @element_type and
6503 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6507 MonoClass *parent = NULL;
6508 GSList *list, *rootlist = NULL;
6511 gboolean corlib_type = FALSE;
6513 g_assert (rank <= 255);
6516 /* bounded only matters for one-dimensional arrays */
6519 image = eclass->image;
6521 if (rank == 1 && !bounded) {
6523 * This case is very frequent not just during compilation because of calls
6524 * from mono_class_from_mono_type (), mono_array_new (),
6525 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6527 mono_mutex_lock (&image->szarray_cache_lock);
6528 if (!image->szarray_cache)
6529 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6530 class = g_hash_table_lookup (image->szarray_cache, eclass);
6531 mono_mutex_unlock (&image->szarray_cache_lock);
6535 mono_loader_lock ();
6537 mono_loader_lock ();
6539 if (!image->array_cache)
6540 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6542 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6543 for (; list; list = list->next) {
6545 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6546 mono_loader_unlock ();
6553 /* for the building corlib use System.Array from it */
6554 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6555 parent = mono_class_from_name (image, "System", "Array");
6558 parent = mono_defaults.array_class;
6559 if (!parent->inited)
6560 mono_class_init (parent);
6563 class = mono_image_alloc0 (image, sizeof (MonoClass));
6565 class->image = image;
6566 class->name_space = eclass->name_space;
6567 nsize = strlen (eclass->name);
6568 name = g_malloc (nsize + 2 + rank + 1);
6569 memcpy (name, eclass->name, nsize);
6572 memset (name + nsize + 1, ',', rank - 1);
6574 name [nsize + rank] = '*';
6575 name [nsize + rank + bounded] = ']';
6576 name [nsize + rank + bounded + 1] = 0;
6577 class->name = mono_image_strdup (image, name);
6580 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6582 classes_size += sizeof (MonoClass);
6584 class->type_token = 0;
6585 /* all arrays are marked serializable and sealed, bug #42779 */
6586 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6587 class->parent = parent;
6588 class->instance_size = mono_class_instance_size (class->parent);
6590 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6591 /*Arrays of those two types are invalid.*/
6592 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6593 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6594 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6595 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6596 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6598 /* element_size -1 is ok as this is not an instantitable type*/
6599 class->sizes.element_size = -1;
6601 class->sizes.element_size = mono_class_array_element_size (eclass);
6603 mono_class_setup_supertypes (class);
6605 if (eclass->generic_class)
6606 mono_class_init (eclass);
6607 if (!eclass->size_inited)
6608 mono_class_setup_fields (eclass);
6609 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6610 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6612 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6616 if (eclass->enumtype)
6617 class->cast_class = eclass->element_class;
6619 class->cast_class = eclass;
6621 switch (class->cast_class->byval_arg.type) {
6623 class->cast_class = mono_defaults.byte_class;
6626 class->cast_class = mono_defaults.int16_class;
6629 #if SIZEOF_VOID_P == 4
6633 class->cast_class = mono_defaults.int32_class;
6636 #if SIZEOF_VOID_P == 8
6640 class->cast_class = mono_defaults.int64_class;
6644 class->element_class = eclass;
6646 if ((rank > 1) || bounded) {
6647 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6648 class->byval_arg.type = MONO_TYPE_ARRAY;
6649 class->byval_arg.data.array = at;
6650 at->eklass = eclass;
6652 /* FIXME: complete.... */
6654 class->byval_arg.type = MONO_TYPE_SZARRAY;
6655 class->byval_arg.data.klass = eclass;
6657 class->this_arg = class->byval_arg;
6658 class->this_arg.byref = 1;
6663 class->generic_container = eclass->generic_container;
6665 if (rank == 1 && !bounded) {
6666 MonoClass *prev_class;
6668 mono_mutex_lock (&image->szarray_cache_lock);
6669 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6671 /* Someone got in before us */
6674 g_hash_table_insert (image->szarray_cache, eclass, class);
6675 mono_mutex_unlock (&image->szarray_cache_lock);
6677 list = g_slist_append (rootlist, class);
6678 g_hash_table_insert (image->array_cache, eclass, list);
6681 mono_loader_unlock ();
6683 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6689 * mono_array_class_get:
6690 * @element_class: element class
6691 * @rank: the dimension of the array class
6693 * Returns: a class object describing the array with element type @element_type and
6697 mono_array_class_get (MonoClass *eclass, guint32 rank)
6699 return mono_bounded_array_class_get (eclass, rank, FALSE);
6703 * mono_class_instance_size:
6706 * Returns: the size of an object instance
6709 mono_class_instance_size (MonoClass *klass)
6711 if (!klass->size_inited)
6712 mono_class_init (klass);
6714 return klass->instance_size;
6718 * mono_class_min_align:
6721 * Returns: minimm alignment requirements
6724 mono_class_min_align (MonoClass *klass)
6726 if (!klass->size_inited)
6727 mono_class_init (klass);
6729 return klass->min_align;
6733 * mono_class_value_size:
6736 * This function is used for value types, and return the
6737 * space and the alignment to store that kind of value object.
6739 * Returns: the size of a value of kind @klass
6742 mono_class_value_size (MonoClass *klass, guint32 *align)
6746 /* fixme: check disable, because we still have external revereces to
6747 * mscorlib and Dummy Objects
6749 /*g_assert (klass->valuetype);*/
6751 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6754 *align = klass->min_align;
6760 * mono_class_data_size:
6763 * Returns: the size of the static class data
6766 mono_class_data_size (MonoClass *klass)
6769 mono_class_init (klass);
6770 /* This can happen with dynamically created types */
6771 if (!klass->fields_inited)
6772 mono_class_setup_fields_locking (klass);
6774 /* in arrays, sizes.class_size is unioned with element_size
6775 * and arrays have no static fields
6779 return klass->sizes.class_size;
6783 * Auxiliary routine to mono_class_get_field
6785 * Takes a field index instead of a field token.
6787 static MonoClassField *
6788 mono_class_get_field_idx (MonoClass *class, int idx)
6790 mono_class_setup_fields_locking (class);
6791 if (class->exception_type)
6795 if (class->image->uncompressed_metadata) {
6797 * class->field.first points to the FieldPtr table, while idx points into the
6798 * Field table, so we have to do a search.
6800 /*FIXME this is broken for types with multiple fields with the same name.*/
6801 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6804 for (i = 0; i < class->field.count; ++i)
6805 if (mono_field_get_name (&class->fields [i]) == name)
6806 return &class->fields [i];
6807 g_assert_not_reached ();
6809 if (class->field.count) {
6810 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6811 return &class->fields [idx - class->field.first];
6815 class = class->parent;
6821 * mono_class_get_field:
6822 * @class: the class to lookup the field.
6823 * @field_token: the field token
6825 * Returns: A MonoClassField representing the type and offset of
6826 * the field, or a NULL value if the field does not belong to this
6830 mono_class_get_field (MonoClass *class, guint32 field_token)
6832 int idx = mono_metadata_token_index (field_token);
6834 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6836 return mono_class_get_field_idx (class, idx - 1);
6840 * mono_class_get_field_from_name:
6841 * @klass: the class to lookup the field.
6842 * @name: the field name
6844 * Search the class @klass and it's parents for a field with the name @name.
6846 * Returns: the MonoClassField pointer of the named field or NULL
6849 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6851 return mono_class_get_field_from_name_full (klass, name, NULL);
6855 * mono_class_get_field_from_name_full:
6856 * @klass: the class to lookup the field.
6857 * @name: the field name
6858 * @type: the type of the fields. This optional.
6860 * Search the class @klass and it's parents for a field with the name @name and type @type.
6862 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6863 * of its generic type definition.
6865 * Returns: the MonoClassField pointer of the named field or NULL
6868 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6872 mono_class_setup_fields_locking (klass);
6873 if (klass->exception_type)
6877 for (i = 0; i < klass->field.count; ++i) {
6878 MonoClassField *field = &klass->fields [i];
6880 if (strcmp (name, mono_field_get_name (field)) != 0)
6884 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6885 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6890 klass = klass->parent;
6896 * mono_class_get_field_token:
6897 * @field: the field we need the token of
6899 * Get the token of a field. Note that the tokesn is only valid for the image
6900 * the field was loaded from. Don't use this function for fields in dynamic types.
6902 * Returns: the token representing the field in the image it was loaded from.
6905 mono_class_get_field_token (MonoClassField *field)
6907 MonoClass *klass = field->parent;
6910 mono_class_setup_fields_locking (klass);
6915 for (i = 0; i < klass->field.count; ++i) {
6916 if (&klass->fields [i] == field) {
6917 int idx = klass->field.first + i + 1;
6919 if (klass->image->uncompressed_metadata)
6920 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6921 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6924 klass = klass->parent;
6927 g_assert_not_reached ();
6932 mono_field_get_index (MonoClassField *field)
6934 int index = field - field->parent->fields;
6936 g_assert (index >= 0 && index < field->parent->field.count);
6942 * mono_class_get_field_default_value:
6944 * Return the default value of the field as a pointer into the metadata blob.
6947 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6950 guint32 constant_cols [MONO_CONSTANT_SIZE];
6952 MonoClass *klass = field->parent;
6954 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6956 if (!klass->ext || !klass->ext->field_def_values) {
6957 MonoFieldDefaultValue *def_values;
6959 mono_class_alloc_ext (klass);
6961 def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6963 mono_image_lock (klass->image);
6964 mono_memory_barrier ();
6965 if (!klass->ext->field_def_values)
6966 klass->ext->field_def_values = def_values;
6967 mono_image_unlock (klass->image);
6970 field_index = mono_field_get_index (field);
6972 if (!klass->ext->field_def_values [field_index].data) {
6973 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6977 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6979 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6980 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6981 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6984 *def_type = klass->ext->field_def_values [field_index].def_type;
6985 return klass->ext->field_def_values [field_index].data;
6989 mono_property_get_index (MonoProperty *prop)
6991 int index = prop - prop->parent->ext->properties;
6993 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6999 * mono_class_get_property_default_value:
7001 * Return the default value of the field as a pointer into the metadata blob.
7004 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7007 guint32 constant_cols [MONO_CONSTANT_SIZE];
7008 MonoClass *klass = property->parent;
7010 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7012 * We don't cache here because it is not used by C# so it's quite rare, but
7013 * we still do the lookup in klass->ext because that is where the data
7014 * is stored for dynamic assemblies.
7017 if (image_is_dynamic (klass->image)) {
7018 int prop_index = mono_property_get_index (property);
7019 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7020 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7021 return klass->ext->prop_def_values [prop_index].data;
7025 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7029 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7030 *def_type = constant_cols [MONO_CONSTANT_TYPE];
7031 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7035 mono_class_get_event_token (MonoEvent *event)
7037 MonoClass *klass = event->parent;
7042 for (i = 0; i < klass->ext->event.count; ++i) {
7043 if (&klass->ext->events [i] == event)
7044 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7047 klass = klass->parent;
7050 g_assert_not_reached ();
7055 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7059 gpointer iter = NULL;
7060 while ((p = mono_class_get_properties (klass, &iter))) {
7061 if (! strcmp (name, p->name))
7064 klass = klass->parent;
7070 mono_class_get_property_token (MonoProperty *prop)
7072 MonoClass *klass = prop->parent;
7076 gpointer iter = NULL;
7077 while ((p = mono_class_get_properties (klass, &iter))) {
7078 if (&klass->ext->properties [i] == prop)
7079 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7083 klass = klass->parent;
7086 g_assert_not_reached ();
7091 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7093 const char *name, *nspace;
7094 if (image_is_dynamic (image))
7095 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7097 switch (type_token & 0xff000000){
7098 case MONO_TOKEN_TYPE_DEF: {
7099 guint32 cols [MONO_TYPEDEF_SIZE];
7100 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7101 guint tidx = mono_metadata_token_index (type_token);
7103 if (tidx > tt->rows)
7104 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7106 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7107 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7108 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7109 if (strlen (nspace) == 0)
7110 return g_strdup_printf ("%s", name);
7112 return g_strdup_printf ("%s.%s", nspace, name);
7115 case MONO_TOKEN_TYPE_REF: {
7117 guint32 cols [MONO_TYPEREF_SIZE];
7118 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7119 guint tidx = mono_metadata_token_index (type_token);
7122 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7124 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7125 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7126 mono_error_cleanup (&error);
7130 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7131 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7132 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7133 if (strlen (nspace) == 0)
7134 return g_strdup_printf ("%s", name);
7136 return g_strdup_printf ("%s.%s", nspace, name);
7139 case MONO_TOKEN_TYPE_SPEC:
7140 return g_strdup_printf ("Typespec 0x%08x", type_token);
7142 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7147 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7149 if (image_is_dynamic (image))
7150 return g_strdup_printf ("DynamicAssembly %s", image->name);
7152 switch (type_token & 0xff000000){
7153 case MONO_TOKEN_TYPE_DEF:
7154 if (image->assembly)
7155 return mono_stringify_assembly_name (&image->assembly->aname);
7156 else if (image->assembly_name)
7157 return g_strdup (image->assembly_name);
7158 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7159 case MONO_TOKEN_TYPE_REF: {
7161 MonoAssemblyName aname;
7162 guint32 cols [MONO_TYPEREF_SIZE];
7163 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7164 guint32 idx = mono_metadata_token_index (type_token);
7167 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7169 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7170 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7171 mono_error_cleanup (&error);
7174 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7176 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7177 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7178 case MONO_RESOLUTION_SCOPE_MODULE:
7180 return g_strdup ("");
7181 case MONO_RESOLUTION_SCOPE_MODULEREF:
7183 return g_strdup ("");
7184 case MONO_RESOLUTION_SCOPE_TYPEREF:
7186 return g_strdup ("");
7187 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7188 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7189 return mono_stringify_assembly_name (&aname);
7191 g_assert_not_reached ();
7195 case MONO_TOKEN_TYPE_SPEC:
7197 return g_strdup ("");
7199 g_assert_not_reached ();
7206 * mono_class_get_full:
7207 * @image: the image where the class resides
7208 * @type_token: the token for the class
7209 * @context: the generic context used to evaluate generic instantiations in
7210 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7212 * Returns: the MonoClass that represents @type_token in @image
7215 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7219 class = mono_class_get_checked (image, type_token, &error);
7221 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7222 class = mono_class_inflate_generic_class_checked (class, context, &error);
7225 mono_loader_set_error_from_mono_error (&error);
7226 mono_error_cleanup (&error); /*FIXME don't swallow this error */
7233 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7237 mono_error_init (error);
7238 class = mono_class_get_checked (image, type_token, error);
7240 if (class && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7241 class = mono_class_inflate_generic_class_checked (class, context, error);
7246 * mono_class_get_checked:
7247 * @image: the image where the class resides
7248 * @type_token: the token for the class
7249 * @error: error object to return any error
7251 * Returns: the MonoClass that represents @type_token in @image
7254 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7256 MonoClass *class = NULL;
7258 mono_error_init (error);
7260 if (image_is_dynamic (image)) {
7261 int table = mono_metadata_token_table (type_token);
7263 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7264 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7267 class = mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7271 switch (type_token & 0xff000000){
7272 case MONO_TOKEN_TYPE_DEF:
7273 class = mono_class_create_from_typedef (image, type_token, error);
7275 case MONO_TOKEN_TYPE_REF:
7276 class = mono_class_from_typeref_checked (image, type_token, error);
7278 case MONO_TOKEN_TYPE_SPEC:
7279 class = mono_class_create_from_typespec (image, type_token, NULL, error);
7282 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7286 /* Generic case, should be avoided for when a better error is possible. */
7287 if (!class && mono_error_ok (error)) {
7288 char *name = mono_class_name_from_token (image, type_token);
7289 char *assembly = mono_assembly_name_from_token (image, type_token);
7290 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7298 * mono_type_get_checked:
7299 * @image: the image where the type resides
7300 * @type_token: the token for the type
7301 * @context: the generic context used to evaluate generic instantiations in
7302 * @error: Error handling context
7304 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7306 * Returns: the MonoType that represents @type_token in @image
7309 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7311 MonoType *type = NULL;
7312 gboolean inflated = FALSE;
7314 mono_error_init (error);
7316 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7317 if (image_is_dynamic (image))
7318 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7320 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7321 MonoClass *class = mono_class_get_checked (image, type_token, error);
7324 g_assert (!mono_loader_get_last_error ());
7329 return mono_class_get_type (class);
7332 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7335 g_assert (!mono_loader_get_last_error ());
7340 MonoType *tmp = type;
7341 type = mono_class_get_type (mono_class_from_mono_type (type));
7342 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7343 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7344 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7346 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7348 if (type->type != tmp->type)
7351 mono_metadata_free_type (tmp);
7358 mono_class_get (MonoImage *image, guint32 type_token)
7360 return mono_class_get_full (image, type_token, NULL);
7364 * mono_image_init_name_cache:
7366 * Initializes the class name cache stored in image->name_cache.
7368 * LOCKING: Acquires the corresponding image lock.
7371 mono_image_init_name_cache (MonoImage *image)
7373 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7374 guint32 cols [MONO_TYPEDEF_SIZE];
7377 guint32 i, visib, nspace_index;
7378 GHashTable *name_cache2, *nspace_table;
7380 mono_image_lock (image);
7382 if (image->name_cache) {
7383 mono_image_unlock (image);
7387 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7389 if (image_is_dynamic (image)) {
7390 mono_image_unlock (image);
7394 /* Temporary hash table to avoid lookups in the nspace_table */
7395 name_cache2 = g_hash_table_new (NULL, NULL);
7397 for (i = 1; i <= t->rows; ++i) {
7398 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7399 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7401 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7402 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7404 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7406 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7407 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7409 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7410 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7411 if (!nspace_table) {
7412 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7413 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7414 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7417 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7420 /* Load type names from EXPORTEDTYPES table */
7422 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7423 guint32 cols [MONO_EXP_TYPE_SIZE];
7426 for (i = 0; i < t->rows; ++i) {
7427 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7428 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7429 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7431 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7432 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7433 if (!nspace_table) {
7434 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7435 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7436 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7439 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7443 g_hash_table_destroy (name_cache2);
7444 mono_image_unlock (image);
7447 /*FIXME Only dynamic assemblies should allow this operation.*/
7449 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7450 const char *name, guint32 index)
7452 GHashTable *nspace_table;
7453 GHashTable *name_cache;
7456 mono_image_lock (image);
7458 if (!image->name_cache)
7459 mono_image_init_name_cache (image);
7461 name_cache = image->name_cache;
7462 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7463 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7464 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7467 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7468 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7470 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7472 mono_image_unlock (image);
7481 find_nocase (gpointer key, gpointer value, gpointer user_data)
7483 char *name = (char*)key;
7484 FindUserData *data = (FindUserData*)user_data;
7486 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7487 data->value = value;
7491 * mono_class_from_name_case:
7492 * @image: The MonoImage where the type is looked up in
7493 * @name_space: the type namespace
7494 * @name: the type short name.
7495 * @deprecated: use the _checked variant
7497 * Obtains a MonoClass with a given namespace and a given name which
7498 * is located in the given MonoImage. The namespace and name
7499 * lookups are case insensitive.
7502 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7505 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7506 g_assert (!mono_error_ok (&error));
7511 mono_class_from_name_case_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7513 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7514 guint32 cols [MONO_TYPEDEF_SIZE];
7519 mono_error_init (error);
7521 if (image_is_dynamic (image)) {
7523 FindUserData user_data;
7525 mono_image_lock (image);
7527 if (!image->name_cache)
7528 mono_image_init_name_cache (image);
7530 user_data.key = name_space;
7531 user_data.value = NULL;
7532 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7534 if (user_data.value) {
7535 GHashTable *nspace_table = (GHashTable*)user_data.value;
7537 user_data.key = name;
7538 user_data.value = NULL;
7540 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7542 if (user_data.value)
7543 token = GPOINTER_TO_UINT (user_data.value);
7546 mono_image_unlock (image);
7549 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7555 /* add a cache if needed */
7556 for (i = 1; i <= t->rows; ++i) {
7557 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7558 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7560 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7561 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7563 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7565 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7566 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7567 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7568 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7574 return_nested_in (MonoClass *class, char *nested)
7577 char *s = strchr (nested, '/');
7578 gpointer iter = NULL;
7585 while ((found = mono_class_get_nested_types (class, &iter))) {
7586 if (strcmp (found->name, nested) == 0) {
7588 return return_nested_in (found, s);
7596 search_modules (MonoImage *image, const char *name_space, const char *name)
7598 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7599 MonoImage *file_image;
7604 * The EXPORTEDTYPES table only contains public types, so have to search the
7606 * Note: image->modules contains the contents of the MODULEREF table, while
7607 * the real module list is in the FILE table.
7609 for (i = 0; i < file_table->rows; i++) {
7610 guint32 cols [MONO_FILE_SIZE];
7611 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7612 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7615 file_image = mono_image_load_file_for_image (image, i + 1);
7617 class = mono_class_from_name (file_image, name_space, name);
7627 * mono_class_from_name:
7628 * @image: The MonoImage where the type is looked up in
7629 * @name_space: the type namespace
7630 * @name: the type short name.
7632 * Obtains a MonoClass with a given namespace and a given name which
7633 * is located in the given MonoImage.
7635 * To reference nested classes, use the "/" character as a separator.
7636 * For example use "Foo/Bar" to reference the class Bar that is nested
7637 * inside Foo, like this: "class Foo { class Bar {} }".
7640 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7642 GHashTable *nspace_table;
7643 MonoImage *loaded_image;
7650 if ((nested = strchr (name, '/'))) {
7651 int pos = nested - name;
7652 int len = strlen (name);
7655 memcpy (buf, name, len + 1);
7657 nested = buf + pos + 1;
7661 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7662 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7663 gboolean res = get_class_from_name (image, name_space, name, &class);
7666 class = search_modules (image, name_space, name);
7668 return class ? return_nested_in (class, nested) : NULL;
7674 mono_image_lock (image);
7676 if (!image->name_cache)
7677 mono_image_init_name_cache (image);
7679 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7682 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7684 mono_image_unlock (image);
7686 if (!token && image_is_dynamic (image) && image->modules) {
7687 /* Search modules as well */
7688 for (i = 0; i < image->module_count; ++i) {
7689 MonoImage *module = image->modules [i];
7691 class = mono_class_from_name (module, name_space, name);
7698 class = search_modules (image, name_space, name);
7706 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7707 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7708 guint32 cols [MONO_EXP_TYPE_SIZE];
7711 idx = mono_metadata_token_index (token);
7713 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7715 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7716 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7717 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7720 class = mono_class_from_name (loaded_image, name_space, name);
7722 return return_nested_in (class, nested);
7724 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7725 guint32 assembly_idx;
7727 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7729 mono_assembly_load_reference (image, assembly_idx - 1);
7730 g_assert (image->references [assembly_idx - 1]);
7731 if (image->references [assembly_idx - 1] == (gpointer)-1)
7734 /* FIXME: Cycle detection */
7735 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7737 g_error ("not yet implemented");
7741 token = MONO_TOKEN_TYPE_DEF | token;
7743 class = mono_class_get (image, token);
7745 return return_nested_in (class, nested);
7750 * mono_class_is_subclass_of:
7751 * @klass: class to probe if it is a subclass of another one
7752 * @klassc: the class we suspect is the base class
7753 * @check_interfaces: whether we should perform interface checks
7755 * This method determines whether @klass is a subclass of @klassc.
7757 * If the @check_interfaces flag is set, then if @klassc is an interface
7758 * this method return true if the @klass implements the interface or
7759 * if @klass is an interface, if one of its base classes is @klass.
7761 * If @check_interfaces is false then, then if @klass is not an interface
7762 * then it returns true if the @klass is a subclass of @klassc.
7764 * if @klass is an interface and @klassc is System.Object, then this function
7769 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7770 gboolean check_interfaces)
7772 /*FIXME test for interfaces with variant generic arguments*/
7774 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7775 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7777 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7780 for (i = 0; i < klass->interface_count; i ++) {
7781 MonoClass *ic = klass->interfaces [i];
7786 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7791 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7794 if (klassc == mono_defaults.object_class)
7801 mono_type_is_generic_argument (MonoType *type)
7803 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7807 mono_class_has_variant_generic_params (MonoClass *klass)
7810 MonoGenericContainer *container;
7812 if (!klass->generic_class)
7815 container = klass->generic_class->container_class->generic_container;
7817 for (i = 0; i < container->type_argc; ++i)
7818 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7825 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7827 if (target == candidate)
7830 if (check_for_reference_conv &&
7831 mono_type_is_generic_argument (&target->byval_arg) &&
7832 mono_type_is_generic_argument (&candidate->byval_arg)) {
7833 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7834 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7836 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7839 if (!mono_class_is_assignable_from (target, candidate))
7845 * @container the generic container from the GTD
7846 * @klass: the class to be assigned to
7847 * @oklass: the source class
7849 * Both klass and oklass must be instances of the same generic interface.
7850 * Return true if @klass can be assigned to a @klass variable
7853 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7856 MonoType **klass_argv, **oklass_argv;
7857 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7858 MonoGenericContainer *container = klass_gtd->generic_container;
7860 if (klass == oklass)
7863 /*Viable candidates are instances of the same generic interface*/
7864 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7867 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7868 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7870 for (j = 0; j < container->type_argc; ++j) {
7871 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7872 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7874 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7878 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7879 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7881 if (param1_class != param2_class) {
7882 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7883 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7885 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7886 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7896 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7898 MonoGenericParam *gparam, *ogparam;
7899 MonoGenericParamInfo *tinfo, *cinfo;
7900 MonoClass **candidate_class;
7901 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7904 if (target == candidate)
7906 if (target->byval_arg.type != candidate->byval_arg.type)
7909 gparam = target->byval_arg.data.generic_param;
7910 ogparam = candidate->byval_arg.data.generic_param;
7911 tinfo = mono_generic_param_info (gparam);
7912 cinfo = mono_generic_param_info (ogparam);
7914 class_constraint_satisfied = FALSE;
7915 valuetype_constraint_satisfied = FALSE;
7917 /*candidate must have a super set of target's special constraints*/
7918 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7919 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7921 if (cinfo->constraints) {
7922 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7923 MonoClass *cc = *candidate_class;
7925 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7926 class_constraint_satisfied = TRUE;
7927 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7928 valuetype_constraint_satisfied = TRUE;
7931 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7932 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7934 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7936 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7938 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7939 valuetype_constraint_satisfied)) {
7944 /*candidate type constraints must be a superset of target's*/
7945 if (tinfo->constraints) {
7946 MonoClass **target_class;
7947 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7948 MonoClass *tc = *target_class;
7951 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7952 * check it's constraints since it satisfy the constraint by itself.
7954 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7957 if (!cinfo->constraints)
7960 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7961 MonoClass *cc = *candidate_class;
7963 if (mono_class_is_assignable_from (tc, cc))
7967 * This happens when we have the following:
7969 * Bar<K> where K : IFace
7970 * Foo<T, U> where T : U where U : IFace
7972 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7975 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7976 if (mono_gparam_is_assignable_from (target, cc))
7980 if (!*candidate_class)
7985 /*candidate itself must have a constraint that satisfy target*/
7986 if (cinfo->constraints) {
7987 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7988 MonoClass *cc = *candidate_class;
7989 if (mono_class_is_assignable_from (target, cc))
7997 * mono_class_is_assignable_from:
7998 * @klass: the class to be assigned to
7999 * @oklass: the source class
8001 * Return: true if an instance of object oklass can be assigned to an
8002 * instance of object @klass
8005 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8007 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8009 mono_class_init (klass);
8011 if (!oklass->inited)
8012 mono_class_init (oklass);
8014 if (klass->exception_type || oklass->exception_type)
8017 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8018 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8020 return mono_gparam_is_assignable_from (klass, oklass);
8023 if (MONO_CLASS_IS_INTERFACE (klass)) {
8024 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8025 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8026 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8030 for (i = 0; constraints [i]; ++i) {
8031 if (mono_class_is_assignable_from (klass, constraints [i]))
8039 /* interface_offsets might not be set for dynamic classes */
8040 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8042 * oklass might be a generic type parameter but they have
8043 * interface_offsets set.
8045 return mono_reflection_call_is_assignable_to (oklass, klass);
8046 if (!oklass->interface_bitmap)
8047 /* Happens with generic instances of not-yet created dynamic types */
8049 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8052 if (mono_class_has_variant_generic_params (klass)) {
8055 mono_class_setup_interfaces (oklass, &error);
8056 if (!mono_error_ok (&error)) {
8057 mono_error_cleanup (&error);
8061 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8062 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8063 MonoClass *iface = oklass->interfaces_packed [i];
8065 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8070 } else if (klass->delegate) {
8071 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8073 }else if (klass->rank) {
8074 MonoClass *eclass, *eoclass;
8076 if (oklass->rank != klass->rank)
8079 /* vectors vs. one dimensional arrays */
8080 if (oklass->byval_arg.type != klass->byval_arg.type)
8083 eclass = klass->cast_class;
8084 eoclass = oklass->cast_class;
8087 * a is b does not imply a[] is b[] when a is a valuetype, and
8088 * b is a reference type.
8091 if (eoclass->valuetype) {
8092 if ((eclass == mono_defaults.enum_class) ||
8093 (eclass == mono_defaults.enum_class->parent) ||
8094 (eclass == mono_defaults.object_class))
8098 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8099 } else if (mono_class_is_nullable (klass)) {
8100 if (mono_class_is_nullable (oklass))
8101 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8103 return mono_class_is_assignable_from (klass->cast_class, oklass);
8104 } else if (klass == mono_defaults.object_class)
8107 return mono_class_has_parent (oklass, klass);
8110 /*Check if @oklass is variant compatible with @klass.*/
8112 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8115 MonoType **klass_argv, **oklass_argv;
8116 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8117 MonoGenericContainer *container = klass_gtd->generic_container;
8119 /*Viable candidates are instances of the same generic interface*/
8120 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8123 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8124 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8126 for (j = 0; j < container->type_argc; ++j) {
8127 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8128 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8130 if (param1_class->valuetype != param2_class->valuetype)
8134 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8135 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8137 if (param1_class != param2_class) {
8138 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8139 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8141 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8142 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8150 /*Check if @candidate implements the interface @target*/
8152 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8156 gboolean is_variant = mono_class_has_variant_generic_params (target);
8158 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8159 if (mono_class_is_variant_compatible_slow (target, candidate))
8164 if (candidate == target)
8167 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8168 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8169 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
8171 if (tb && tb->interfaces) {
8172 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8173 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8174 MonoClass *iface_class;
8176 /* we can't realize the type here since it can do pretty much anything. */
8179 iface_class = mono_class_from_mono_type (iface->type);
8180 if (iface_class == target)
8182 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8184 if (mono_class_implement_interface_slow (target, iface_class))
8189 /*setup_interfaces don't mono_class_init anything*/
8190 /*FIXME this doesn't handle primitive type arrays.
8191 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8192 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8194 mono_class_setup_interfaces (candidate, &error);
8195 if (!mono_error_ok (&error)) {
8196 mono_error_cleanup (&error);
8200 for (i = 0; i < candidate->interface_count; ++i) {
8201 if (candidate->interfaces [i] == target)
8204 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8207 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8211 candidate = candidate->parent;
8212 } while (candidate);
8218 * Check if @oklass can be assigned to @klass.
8219 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8222 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8224 if (candidate == target)
8226 if (target == mono_defaults.object_class)
8229 if (mono_class_has_parent (candidate, target))
8232 /*If target is not an interface there is no need to check them.*/
8233 if (MONO_CLASS_IS_INTERFACE (target))
8234 return mono_class_implement_interface_slow (target, candidate);
8236 if (target->delegate && mono_class_has_variant_generic_params (target))
8237 return mono_class_is_variant_compatible (target, candidate, FALSE);
8240 MonoClass *eclass, *eoclass;
8242 if (target->rank != candidate->rank)
8245 /* vectors vs. one dimensional arrays */
8246 if (target->byval_arg.type != candidate->byval_arg.type)
8249 eclass = target->cast_class;
8250 eoclass = candidate->cast_class;
8253 * a is b does not imply a[] is b[] when a is a valuetype, and
8254 * b is a reference type.
8257 if (eoclass->valuetype) {
8258 if ((eclass == mono_defaults.enum_class) ||
8259 (eclass == mono_defaults.enum_class->parent) ||
8260 (eclass == mono_defaults.object_class))
8264 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8266 /*FIXME properly handle nullables */
8267 /*FIXME properly handle (M)VAR */
8272 * mono_class_get_cctor:
8273 * @klass: A MonoClass pointer
8275 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8278 mono_class_get_cctor (MonoClass *klass)
8280 MonoCachedClassInfo cached_info;
8282 if (image_is_dynamic (klass->image)) {
8284 * has_cctor is not set for these classes because mono_class_init () is
8287 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8290 if (!klass->has_cctor)
8293 if (mono_class_get_cached_class_info (klass, &cached_info))
8294 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8296 if (klass->generic_class && !klass->methods)
8297 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8299 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8303 * mono_class_get_finalizer:
8304 * @klass: The MonoClass pointer
8306 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8309 mono_class_get_finalizer (MonoClass *klass)
8311 MonoCachedClassInfo cached_info;
8314 mono_class_init (klass);
8315 if (!mono_class_has_finalizer (klass))
8318 if (mono_class_get_cached_class_info (klass, &cached_info))
8319 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8321 mono_class_setup_vtable (klass);
8322 return klass->vtable [finalize_slot];
8327 * mono_class_needs_cctor_run:
8328 * @klass: the MonoClass pointer
8329 * @caller: a MonoMethod describing the caller
8331 * Determines whenever the class has a static constructor and whenever it
8332 * needs to be called when executing CALLER.
8335 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8339 method = mono_class_get_cctor (klass);
8341 return (method == caller) ? FALSE : TRUE;
8347 * mono_class_array_element_size:
8350 * Returns: the number of bytes an element of type @klass
8351 * uses when stored into an array.
8354 mono_class_array_element_size (MonoClass *klass)
8356 MonoType *type = &klass->byval_arg;
8359 switch (type->type) {
8362 case MONO_TYPE_BOOLEAN:
8366 case MONO_TYPE_CHAR:
8375 case MONO_TYPE_CLASS:
8376 case MONO_TYPE_STRING:
8377 case MONO_TYPE_OBJECT:
8378 case MONO_TYPE_SZARRAY:
8379 case MONO_TYPE_ARRAY:
8381 case MONO_TYPE_MVAR:
8382 return sizeof (gpointer);
8387 case MONO_TYPE_VALUETYPE:
8388 if (type->data.klass->enumtype) {
8389 type = mono_class_enum_basetype (type->data.klass);
8390 klass = klass->element_class;
8393 return mono_class_instance_size (klass) - sizeof (MonoObject);
8394 case MONO_TYPE_GENERICINST:
8395 type = &type->data.generic_class->container_class->byval_arg;
8398 case MONO_TYPE_VOID:
8402 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8408 * mono_array_element_size:
8409 * @ac: pointer to a #MonoArrayClass
8411 * Returns: the size of single array element.
8414 mono_array_element_size (MonoClass *ac)
8416 g_assert (ac->rank);
8417 return ac->sizes.element_size;
8421 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8422 MonoGenericContext *context)
8424 if (image_is_dynamic (image)) {
8425 MonoClass *tmp_handle_class;
8426 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8428 g_assert (tmp_handle_class);
8430 *handle_class = tmp_handle_class;
8432 if (tmp_handle_class == mono_defaults.typehandle_class)
8433 return &((MonoClass*)obj)->byval_arg;
8438 switch (token & 0xff000000) {
8439 case MONO_TOKEN_TYPE_DEF:
8440 case MONO_TOKEN_TYPE_REF:
8441 case MONO_TOKEN_TYPE_SPEC: {
8445 *handle_class = mono_defaults.typehandle_class;
8446 type = mono_type_get_checked (image, token, context, &error);
8448 mono_loader_set_error_from_mono_error (&error);
8449 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8452 mono_class_init (mono_class_from_mono_type (type));
8453 /* We return a MonoType* as handle */
8456 case MONO_TOKEN_FIELD_DEF: {
8459 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8463 *handle_class = mono_defaults.fieldhandle_class;
8464 class = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, &error);
8466 mono_loader_set_error_from_mono_error (&error);
8467 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8470 mono_class_init (class);
8471 return mono_class_get_field (class, token);
8473 case MONO_TOKEN_METHOD_DEF:
8474 case MONO_TOKEN_METHOD_SPEC: {
8476 meth = mono_get_method_full (image, token, NULL, context);
8478 *handle_class = mono_defaults.methodhandle_class;
8481 case MONO_TOKEN_MEMBER_REF: {
8482 guint32 cols [MONO_MEMBERREF_SIZE];
8484 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8485 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8486 mono_metadata_decode_blob_size (sig, &sig);
8487 if (*sig == 0x6) { /* it's a field */
8490 MonoClassField *field;
8491 field = mono_field_from_token_checked (image, token, &klass, context, &error);
8493 *handle_class = mono_defaults.fieldhandle_class;
8495 mono_loader_set_error_from_mono_error (&error);
8496 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8501 meth = mono_get_method_full (image, token, NULL, context);
8503 *handle_class = mono_defaults.methodhandle_class;
8508 g_warning ("Unknown token 0x%08x in ldtoken", token);
8515 * This function might need to call runtime functions so it can't be part
8516 * of the metadata library.
8518 static MonoLookupDynamicToken lookup_dynamic = NULL;
8521 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8523 lookup_dynamic = func;
8527 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8529 MonoClass *handle_class;
8531 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8535 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8537 return lookup_dynamic (image, token, valid_token, handle_class, context);
8540 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8543 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8545 get_cached_class_info = func;
8549 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8551 if (!get_cached_class_info)
8554 return get_cached_class_info (klass, res);
8558 mono_install_get_class_from_name (MonoGetClassFromName func)
8560 get_class_from_name = func;
8564 mono_class_get_image (MonoClass *klass)
8566 return klass->image;
8570 * mono_class_get_element_class:
8571 * @klass: the MonoClass to act on
8573 * Returns: the element class of an array or an enumeration.
8576 mono_class_get_element_class (MonoClass *klass)
8578 return klass->element_class;
8582 * mono_class_is_valuetype:
8583 * @klass: the MonoClass to act on
8585 * Returns: true if the MonoClass represents a ValueType.
8588 mono_class_is_valuetype (MonoClass *klass)
8590 return klass->valuetype;
8594 * mono_class_is_enum:
8595 * @klass: the MonoClass to act on
8597 * Returns: true if the MonoClass represents an enumeration.
8600 mono_class_is_enum (MonoClass *klass)
8602 return klass->enumtype;
8606 * mono_class_enum_basetype:
8607 * @klass: the MonoClass to act on
8609 * Returns: the underlying type representation for an enumeration.
8612 mono_class_enum_basetype (MonoClass *klass)
8614 if (klass->element_class == klass)
8615 /* SRE or broken types */
8618 return &klass->element_class->byval_arg;
8622 * mono_class_get_parent
8623 * @klass: the MonoClass to act on
8625 * Returns: the parent class for this class.
8628 mono_class_get_parent (MonoClass *klass)
8630 return klass->parent;
8634 * mono_class_get_nesting_type;
8635 * @klass: the MonoClass to act on
8637 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8640 mono_class_get_nesting_type (MonoClass *klass)
8642 return klass->nested_in;
8646 * mono_class_get_rank:
8647 * @klass: the MonoClass to act on
8649 * Returns: the rank for the array (the number of dimensions).
8652 mono_class_get_rank (MonoClass *klass)
8658 * mono_class_get_flags:
8659 * @klass: the MonoClass to act on
8661 * The type flags from the TypeDef table from the metadata.
8662 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8665 * Returns: the flags from the TypeDef table.
8668 mono_class_get_flags (MonoClass *klass)
8670 return klass->flags;
8674 * mono_class_get_name
8675 * @klass: the MonoClass to act on
8677 * Returns: the name of the class.
8680 mono_class_get_name (MonoClass *klass)
8686 * mono_class_get_namespace:
8687 * @klass: the MonoClass to act on
8689 * Returns: the namespace of the class.
8692 mono_class_get_namespace (MonoClass *klass)
8694 return klass->name_space;
8698 * mono_class_get_type:
8699 * @klass: the MonoClass to act on
8701 * This method returns the internal Type representation for the class.
8703 * Returns: the MonoType from the class.
8706 mono_class_get_type (MonoClass *klass)
8708 return &klass->byval_arg;
8712 * mono_class_get_type_token
8713 * @klass: the MonoClass to act on
8715 * This method returns type token for the class.
8717 * Returns: the type token for the class.
8720 mono_class_get_type_token (MonoClass *klass)
8722 return klass->type_token;
8726 * mono_class_get_byref_type:
8727 * @klass: the MonoClass to act on
8732 mono_class_get_byref_type (MonoClass *klass)
8734 return &klass->this_arg;
8738 * mono_class_num_fields:
8739 * @klass: the MonoClass to act on
8741 * Returns: the number of static and instance fields in the class.
8744 mono_class_num_fields (MonoClass *klass)
8746 return klass->field.count;
8750 * mono_class_num_methods:
8751 * @klass: the MonoClass to act on
8753 * Returns: the number of methods in the class.
8756 mono_class_num_methods (MonoClass *klass)
8758 return klass->method.count;
8762 * mono_class_num_properties
8763 * @klass: the MonoClass to act on
8765 * Returns: the number of properties in the class.
8768 mono_class_num_properties (MonoClass *klass)
8770 mono_class_setup_properties (klass);
8772 return klass->ext->property.count;
8776 * mono_class_num_events:
8777 * @klass: the MonoClass to act on
8779 * Returns: the number of events in the class.
8782 mono_class_num_events (MonoClass *klass)
8784 mono_class_setup_events (klass);
8786 return klass->ext->event.count;
8790 * mono_class_get_fields:
8791 * @klass: the MonoClass to act on
8793 * This routine is an iterator routine for retrieving the fields in a class.
8795 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8796 * iterate over all of the elements. When no more values are
8797 * available, the return value is NULL.
8799 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8802 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8804 MonoClassField* field;
8808 mono_class_setup_fields_locking (klass);
8809 if (klass->exception_type)
8811 /* start from the first */
8812 if (klass->field.count) {
8813 return *iter = &klass->fields [0];
8821 if (field < &klass->fields [klass->field.count]) {
8822 return *iter = field;
8828 * mono_class_get_methods
8829 * @klass: the MonoClass to act on
8831 * This routine is an iterator routine for retrieving the fields in a class.
8833 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8834 * iterate over all of the elements. When no more values are
8835 * available, the return value is NULL.
8837 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8840 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8842 MonoMethod** method;
8846 mono_class_setup_methods (klass);
8849 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8850 * FIXME we should better report this error to the caller
8852 if (!klass->methods)
8854 /* start from the first */
8855 if (klass->method.count) {
8856 *iter = &klass->methods [0];
8857 return klass->methods [0];
8865 if (method < &klass->methods [klass->method.count]) {
8873 * mono_class_get_virtual_methods:
8875 * Iterate over the virtual methods of KLASS.
8877 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8880 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8882 MonoMethod** method;
8885 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8887 mono_class_setup_methods (klass);
8889 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8890 * FIXME we should better report this error to the caller
8892 if (!klass->methods)
8894 /* start from the first */
8895 method = &klass->methods [0];
8900 while (method < &klass->methods [klass->method.count]) {
8901 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8905 if (method < &klass->methods [klass->method.count]) {
8912 /* Search directly in metadata to avoid calling setup_methods () */
8913 MonoMethod *res = NULL;
8919 start_index = GPOINTER_TO_UINT (*iter);
8922 for (i = start_index; i < klass->method.count; ++i) {
8925 /* class->method.first points into the methodptr table */
8926 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8928 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8932 if (i < klass->method.count) {
8933 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8934 /* Add 1 here so the if (*iter) check fails */
8935 *iter = GUINT_TO_POINTER (i + 1);
8944 * mono_class_get_properties:
8945 * @klass: the MonoClass to act on
8947 * This routine is an iterator routine for retrieving the properties in a class.
8949 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8950 * iterate over all of the elements. When no more values are
8951 * available, the return value is NULL.
8953 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8956 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8958 MonoProperty* property;
8962 mono_class_setup_properties (klass);
8963 /* start from the first */
8964 if (klass->ext->property.count) {
8965 return *iter = &klass->ext->properties [0];
8973 if (property < &klass->ext->properties [klass->ext->property.count]) {
8974 return *iter = property;
8980 * mono_class_get_events:
8981 * @klass: the MonoClass to act on
8983 * This routine is an iterator routine for retrieving the properties in a class.
8985 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8986 * iterate over all of the elements. When no more values are
8987 * available, the return value is NULL.
8989 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8992 mono_class_get_events (MonoClass* klass, gpointer *iter)
8998 mono_class_setup_events (klass);
8999 /* start from the first */
9000 if (klass->ext->event.count) {
9001 return *iter = &klass->ext->events [0];
9009 if (event < &klass->ext->events [klass->ext->event.count]) {
9010 return *iter = event;
9016 * mono_class_get_interfaces
9017 * @klass: the MonoClass to act on
9019 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9021 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9022 * iterate over all of the elements. When no more values are
9023 * available, the return value is NULL.
9025 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9028 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9036 mono_class_init (klass);
9037 if (!klass->interfaces_inited) {
9038 mono_class_setup_interfaces (klass, &error);
9039 if (!mono_error_ok (&error)) {
9040 mono_error_cleanup (&error);
9044 /* start from the first */
9045 if (klass->interface_count) {
9046 *iter = &klass->interfaces [0];
9047 return klass->interfaces [0];
9055 if (iface < &klass->interfaces [klass->interface_count]) {
9063 setup_nested_types (MonoClass *klass)
9066 GList *classes, *nested_classes, *l;
9069 if (klass->nested_classes_inited)
9072 if (!klass->type_token)
9073 klass->nested_classes_inited = TRUE;
9075 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9079 guint32 cols [MONO_NESTED_CLASS_SIZE];
9080 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9081 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9082 if (!mono_error_ok (&error)) {
9083 /*FIXME don't swallow the error message*/
9084 mono_error_cleanup (&error);
9086 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9090 classes = g_list_prepend (classes, nclass);
9092 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9095 mono_class_alloc_ext (klass);
9097 nested_classes = NULL;
9098 for (l = classes; l; l = l->next)
9099 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9100 g_list_free (classes);
9102 mono_image_lock (klass->image);
9104 mono_memory_barrier ();
9105 if (!klass->nested_classes_inited) {
9106 klass->ext->nested_classes = nested_classes;
9107 mono_memory_barrier ();
9108 klass->nested_classes_inited = TRUE;
9111 mono_image_unlock (klass->image);
9115 * mono_class_get_nested_types
9116 * @klass: the MonoClass to act on
9118 * This routine is an iterator routine for retrieving the nested types of a class.
9119 * This works only if @klass is non-generic, or a generic type definition.
9121 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9122 * iterate over all of the elements. When no more values are
9123 * available, the return value is NULL.
9125 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9128 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9134 if (!klass->nested_classes_inited)
9135 setup_nested_types (klass);
9138 /* start from the first */
9139 if (klass->ext && klass->ext->nested_classes) {
9140 *iter = klass->ext->nested_classes;
9141 return klass->ext->nested_classes->data;
9143 /* no nested types */
9158 * mono_class_is_delegate
9159 * @klass: the MonoClass to act on
9161 * Returns: true if the MonoClass represents a System.Delegate.
9164 mono_class_is_delegate (MonoClass *klass)
9166 return klass->delegate;
9170 * mono_class_implements_interface
9171 * @klass: The MonoClass to act on
9172 * @interface: The interface to check if @klass implements.
9174 * Returns: true if @klass implements @interface.
9177 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9179 return mono_class_is_assignable_from (iface, klass);
9183 * mono_field_get_name:
9184 * @field: the MonoClassField to act on
9186 * Returns: the name of the field.
9189 mono_field_get_name (MonoClassField *field)
9195 * mono_field_get_type:
9196 * @field: the MonoClassField to act on
9198 * Returns: MonoType of the field.
9201 mono_field_get_type (MonoClassField *field)
9204 MonoType *type = mono_field_get_type_checked (field, &error);
9205 if (!mono_error_ok (&error)) {
9206 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9207 mono_error_cleanup (&error);
9214 * mono_field_get_type_checked:
9215 * @field: the MonoClassField to act on
9216 * @error: used to return any erro found while retrieving @field type
9218 * Returns: MonoType of the field.
9221 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9223 mono_error_init (error);
9225 mono_field_resolve_type (field, error);
9230 * mono_field_get_parent:
9231 * @field: the MonoClassField to act on
9233 * Returns: MonoClass where the field was defined.
9236 mono_field_get_parent (MonoClassField *field)
9238 return field->parent;
9242 * mono_field_get_flags;
9243 * @field: the MonoClassField to act on
9245 * The metadata flags for a field are encoded using the
9246 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9248 * Returns: the flags for the field.
9251 mono_field_get_flags (MonoClassField *field)
9254 return mono_field_resolve_flags (field);
9255 return field->type->attrs;
9259 * mono_field_get_offset;
9260 * @field: the MonoClassField to act on
9262 * Returns: the field offset.
9265 mono_field_get_offset (MonoClassField *field)
9267 return field->offset;
9271 mono_field_get_rva (MonoClassField *field)
9275 MonoClass *klass = field->parent;
9276 MonoFieldDefaultValue *field_def_values;
9278 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9280 if (!klass->ext || !klass->ext->field_def_values) {
9281 mono_class_alloc_ext (klass);
9283 field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9285 mono_image_lock (klass->image);
9286 if (!klass->ext->field_def_values)
9287 klass->ext->field_def_values = field_def_values;
9288 mono_image_unlock (klass->image);
9291 field_index = mono_field_get_index (field);
9293 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9294 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9296 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9297 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9300 return klass->ext->field_def_values [field_index].data;
9304 * mono_field_get_data;
9305 * @field: the MonoClassField to act on
9307 * Returns: pointer to the metadata constant value or to the field
9308 * data if it has an RVA flag.
9311 mono_field_get_data (MonoClassField *field)
9313 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9314 MonoTypeEnum def_type;
9316 return mono_class_get_field_default_value (field, &def_type);
9317 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9318 return mono_field_get_rva (field);
9325 * mono_property_get_name:
9326 * @prop: the MonoProperty to act on
9328 * Returns: the name of the property
9331 mono_property_get_name (MonoProperty *prop)
9337 * mono_property_get_set_method
9338 * @prop: the MonoProperty to act on.
9340 * Returns: the setter method of the property (A MonoMethod)
9343 mono_property_get_set_method (MonoProperty *prop)
9349 * mono_property_get_get_method
9350 * @prop: the MonoProperty to act on.
9352 * Returns: the setter method of the property (A MonoMethod)
9355 mono_property_get_get_method (MonoProperty *prop)
9361 * mono_property_get_parent:
9362 * @prop: the MonoProperty to act on.
9364 * Returns: the MonoClass where the property was defined.
9367 mono_property_get_parent (MonoProperty *prop)
9369 return prop->parent;
9373 * mono_property_get_flags:
9374 * @prop: the MonoProperty to act on.
9376 * The metadata flags for a property are encoded using the
9377 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9379 * Returns: the flags for the property.
9382 mono_property_get_flags (MonoProperty *prop)
9388 * mono_event_get_name:
9389 * @event: the MonoEvent to act on
9391 * Returns: the name of the event.
9394 mono_event_get_name (MonoEvent *event)
9400 * mono_event_get_add_method:
9401 * @event: The MonoEvent to act on.
9403 * Returns: the @add' method for the event (a MonoMethod).
9406 mono_event_get_add_method (MonoEvent *event)
9412 * mono_event_get_remove_method:
9413 * @event: The MonoEvent to act on.
9415 * Returns: the @remove method for the event (a MonoMethod).
9418 mono_event_get_remove_method (MonoEvent *event)
9420 return event->remove;
9424 * mono_event_get_raise_method:
9425 * @event: The MonoEvent to act on.
9427 * Returns: the @raise method for the event (a MonoMethod).
9430 mono_event_get_raise_method (MonoEvent *event)
9432 return event->raise;
9436 * mono_event_get_parent:
9437 * @event: the MonoEvent to act on.
9439 * Returns: the MonoClass where the event is defined.
9442 mono_event_get_parent (MonoEvent *event)
9444 return event->parent;
9448 * mono_event_get_flags
9449 * @event: the MonoEvent to act on.
9451 * The metadata flags for an event are encoded using the
9452 * EVENT_* constants. See the tabledefs.h file for details.
9454 * Returns: the flags for the event.
9457 mono_event_get_flags (MonoEvent *event)
9459 return event->attrs;
9463 * mono_class_get_method_from_name:
9464 * @klass: where to look for the method
9465 * @name: name of the method
9466 * @param_count: number of parameters. -1 for any number.
9468 * Obtains a MonoMethod with a given name and number of parameters.
9469 * It only works if there are no multiple signatures for any given method name.
9472 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9474 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9478 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9480 MonoMethod *res = NULL;
9483 /* Search directly in the metadata to avoid calling setup_methods () */
9484 for (i = 0; i < klass->method.count; ++i) {
9485 guint32 cols [MONO_METHOD_SIZE];
9487 MonoMethodSignature *sig;
9489 /* class->method.first points into the methodptr table */
9490 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9492 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9493 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9494 if (param_count == -1) {
9498 sig = mono_method_signature (method);
9499 if (sig && sig->param_count == param_count) {
9510 * mono_class_get_method_from_name_flags:
9511 * @klass: where to look for the method
9512 * @name_space: name of the method
9513 * @param_count: number of parameters. -1 for any number.
9514 * @flags: flags which must be set in the method
9516 * Obtains a MonoMethod with a given name and number of parameters.
9517 * It only works if there are no multiple signatures for any given method name.
9520 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9522 MonoMethod *res = NULL;
9525 mono_class_init (klass);
9527 if (klass->generic_class && !klass->methods) {
9528 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9530 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9534 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9535 mono_class_setup_methods (klass);
9537 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9538 See mono/tests/array_load_exception.il
9539 FIXME we should better report this error to the caller
9541 if (!klass->methods)
9543 for (i = 0; i < klass->method.count; ++i) {
9544 MonoMethod *method = klass->methods [i];
9546 if (method->name[0] == name [0] &&
9547 !strcmp (name, method->name) &&
9548 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9549 ((method->flags & flags) == flags)) {
9556 res = find_method_in_metadata (klass, name, param_count, flags);
9563 * mono_class_set_failure:
9564 * @klass: class in which the failure was detected
9565 * @ex_type: the kind of exception/error to be thrown (later)
9566 * @ex_data: exception data (specific to each type of exception/error)
9568 * Keep a detected failure informations in the class for later processing.
9569 * Note that only the first failure is kept.
9571 * LOCKING: Acquires the loader lock.
9574 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9576 if (klass->exception_type)
9579 mono_loader_lock ();
9580 klass->exception_type = ex_type;
9582 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9583 mono_loader_unlock ();
9589 * mono_class_get_exception_data:
9591 * Return the exception_data property of KLASS.
9593 * LOCKING: Acquires the loader lock.
9596 mono_class_get_exception_data (MonoClass *klass)
9598 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9602 * mono_classes_init:
9604 * Initialize the resources used by this module.
9607 mono_classes_init (void)
9609 mono_mutex_init (&classes_mutex);
9611 mono_counters_register ("Inflated methods size",
9612 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9613 mono_counters_register ("Inflated classes",
9614 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9615 mono_counters_register ("Inflated classes size",
9616 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9617 mono_counters_register ("MonoClass size",
9618 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9619 mono_counters_register ("MonoClassExt size",
9620 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9624 * mono_classes_cleanup:
9626 * Free the resources used by this module.
9629 mono_classes_cleanup (void)
9631 if (global_interface_bitset)
9632 mono_bitset_free (global_interface_bitset);
9633 global_interface_bitset = NULL;
9634 mono_mutex_destroy (&classes_mutex);
9638 * mono_class_get_exception_for_failure:
9639 * @klass: class in which the failure was detected
9641 * Return a constructed MonoException than the caller can then throw
9642 * using mono_raise_exception - or NULL if no failure is present (or
9643 * doesn't result in an exception).
9646 mono_class_get_exception_for_failure (MonoClass *klass)
9648 gpointer exception_data = mono_class_get_exception_data (klass);
9650 switch (klass->exception_type) {
9651 #ifndef DISABLE_SECURITY
9652 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9653 MonoDomain *domain = mono_domain_get ();
9654 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9655 MonoMethod *method = exception_data;
9656 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9657 MonoObject *exc = NULL;
9661 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9662 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9663 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9665 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9666 return (MonoException*) exc;
9669 case MONO_EXCEPTION_TYPE_LOAD: {
9672 char *str = mono_type_get_full_name (klass);
9673 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9674 name = mono_string_new (mono_domain_get (), str);
9676 ex = mono_get_exception_type_load (name, astr);
9680 case MONO_EXCEPTION_MISSING_METHOD: {
9681 char *class_name = exception_data;
9682 char *assembly_name = class_name + strlen (class_name) + 1;
9684 return mono_get_exception_missing_method (class_name, assembly_name);
9686 case MONO_EXCEPTION_MISSING_FIELD: {
9687 char *class_name = exception_data;
9688 char *member_name = class_name + strlen (class_name) + 1;
9690 return mono_get_exception_missing_field (class_name, member_name);
9692 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9693 char *msg_format = exception_data;
9694 char *assembly_name = msg_format + strlen (msg_format) + 1;
9695 char *msg = g_strdup_printf (msg_format, assembly_name);
9698 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9704 case MONO_EXCEPTION_BAD_IMAGE: {
9705 return mono_get_exception_bad_image_format (exception_data);
9708 MonoLoaderError *error;
9711 error = mono_loader_get_last_error ();
9713 ex = mono_loader_error_prepare_exception (error);
9717 /* TODO - handle other class related failures */
9724 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9726 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9727 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9729 if (outer_klass == inner_klass)
9731 inner_klass = inner_klass->nested_in;
9732 } while (inner_klass);
9737 mono_class_get_generic_type_definition (MonoClass *klass)
9739 return klass->generic_class ? klass->generic_class->container_class : klass;
9743 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9745 * Generic instantiations are ignored for all super types of @klass.
9747 * Visibility checks ignoring generic instantiations.
9750 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9753 klass = mono_class_get_generic_type_definition (klass);
9754 parent = mono_class_get_generic_type_definition (parent);
9755 mono_class_setup_supertypes (klass);
9757 for (i = 0; i < klass->idepth; ++i) {
9758 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9764 * Subtype can only access parent members with family protection if the site object
9765 * is subclass of Subtype. For example:
9766 * class A { protected int x; }
9768 * void valid_access () {
9772 * void invalid_access () {
9779 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9781 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9784 if (context_klass == NULL)
9786 /*if access_klass is not member_klass context_klass must be type compat*/
9787 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9793 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9796 if (accessing == accessed)
9798 if (!accessed || !accessing)
9801 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9802 * anywhere so untrusted friends are not safe to access platform's code internals */
9803 if (mono_security_core_clr_enabled ()) {
9804 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9808 mono_assembly_load_friends (accessed);
9809 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9810 MonoAssemblyName *friend = tmp->data;
9811 /* Be conservative with checks */
9814 if (strcmp (accessing->aname.name, friend->name))
9816 if (friend->public_key_token [0]) {
9817 if (!accessing->aname.public_key_token [0])
9819 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9828 * If klass is a generic type or if it is derived from a generic type, return the
9829 * MonoClass of the generic definition
9830 * Returns NULL if not found
9833 get_generic_definition_class (MonoClass *klass)
9836 if (klass->generic_class && klass->generic_class->container_class)
9837 return klass->generic_class->container_class;
9838 klass = klass->parent;
9844 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9847 for (i = 0; i < ginst->type_argc; ++i) {
9848 MonoType *type = ginst->type_argv[i];
9849 switch (type->type) {
9850 case MONO_TYPE_SZARRAY:
9851 if (!can_access_type (access_klass, type->data.klass))
9854 case MONO_TYPE_ARRAY:
9855 if (!can_access_type (access_klass, type->data.array->eklass))
9859 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9862 case MONO_TYPE_CLASS:
9863 case MONO_TYPE_VALUETYPE:
9864 case MONO_TYPE_GENERICINST:
9865 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9873 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9877 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9880 if (access_klass->element_class && !access_klass->enumtype)
9881 access_klass = access_klass->element_class;
9883 if (member_klass->element_class && !member_klass->enumtype)
9884 member_klass = member_klass->element_class;
9886 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9888 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9891 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9894 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9897 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9900 /*Non nested type with nested visibility. We just fail it.*/
9901 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9904 switch (access_level) {
9905 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9906 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9908 case TYPE_ATTRIBUTE_PUBLIC:
9911 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9914 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9915 return is_nesting_type (member_klass, access_klass);
9917 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9918 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9920 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9921 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9923 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9924 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9925 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9927 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9928 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9929 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9934 /* FIXME: check visibility of type, too */
9936 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9938 MonoClass *member_generic_def;
9939 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9942 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9943 access_klass->generic_container) &&
9944 (member_generic_def = get_generic_definition_class (member_klass))) {
9945 MonoClass *access_container;
9947 if (access_klass->generic_container)
9948 access_container = access_klass;
9950 access_container = access_klass->generic_class->container_class;
9952 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9956 /* Partition I 8.5.3.2 */
9957 /* the access level values are the same for fields and methods */
9958 switch (access_level) {
9959 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9960 /* same compilation unit */
9961 return access_klass->image == member_klass->image;
9962 case FIELD_ATTRIBUTE_PRIVATE:
9963 return access_klass == member_klass;
9964 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9965 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9966 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9969 case FIELD_ATTRIBUTE_ASSEMBLY:
9970 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9971 case FIELD_ATTRIBUTE_FAMILY:
9972 if (is_valid_family_access (access_klass, member_klass, context_klass))
9975 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9976 if (is_valid_family_access (access_klass, member_klass, context_klass))
9978 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9979 case FIELD_ATTRIBUTE_PUBLIC:
9986 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9988 /* FIXME: check all overlapping fields */
9989 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9991 MonoClass *nested = method->klass->nested_in;
9993 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9996 nested = nested->nested_in;
10003 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10005 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10007 MonoClass *nested = method->klass->nested_in;
10009 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10012 nested = nested->nested_in;
10017 * with generics calls to explicit interface implementations can be expressed
10018 * directly: the method is private, but we must allow it. This may be opening
10019 * a hole or the generics code should handle this differently.
10020 * Maybe just ensure the interface type is public.
10022 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10028 * mono_method_can_access_method_full:
10029 * @method: The caller method
10030 * @called: The called method
10031 * @context_klass: The static type on stack of the owner @called object used
10033 * This function must be used with instance calls, as they have more strict family accessibility.
10034 * It can be used with static methods, but context_klass should be NULL.
10036 * Returns: TRUE if caller have proper visibility and acessibility to @called
10039 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10041 MonoClass *access_class = method->klass;
10042 MonoClass *member_class = called->klass;
10043 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10045 MonoClass *nested = access_class->nested_in;
10047 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10050 nested = nested->nested_in;
10057 can = can_access_type (access_class, member_class);
10059 MonoClass *nested = access_class->nested_in;
10061 can = can_access_type (nested, member_class);
10064 nested = nested->nested_in;
10071 if (called->is_inflated) {
10072 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10073 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10082 * mono_method_can_access_field_full:
10083 * @method: The caller method
10084 * @field: The accessed field
10085 * @context_klass: The static type on stack of the owner @field object used
10087 * This function must be used with instance fields, as they have more strict family accessibility.
10088 * It can be used with static fields, but context_klass should be NULL.
10090 * Returns: TRUE if caller have proper visibility and acessibility to @field
10093 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10095 MonoClass *access_class = method->klass;
10096 MonoClass *member_class = field->parent;
10097 /* FIXME: check all overlapping fields */
10098 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10100 MonoClass *nested = access_class->nested_in;
10102 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10105 nested = nested->nested_in;
10112 can = can_access_type (access_class, member_class);
10114 MonoClass *nested = access_class->nested_in;
10116 can = can_access_type (nested, member_class);
10119 nested = nested->nested_in;
10129 * mono_class_can_access_class:
10130 * @source_class: The source class
10131 * @target_class: The accessed class
10133 * This function returns is @target_class is visible to @source_class
10135 * Returns: TRUE if source have proper visibility and acessibility to target
10138 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10140 return can_access_type (source_class, target_class);
10144 * mono_type_is_valid_enum_basetype:
10145 * @type: The MonoType to check
10147 * Returns: TRUE if the type can be used as the basetype of an enum
10149 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10150 switch (type->type) {
10153 case MONO_TYPE_BOOLEAN:
10156 case MONO_TYPE_CHAR:
10169 * mono_class_is_valid_enum:
10170 * @klass: An enum class to be validated
10172 * This method verify the required properties an enum should have.
10174 * Returns: TRUE if the informed enum class is valid
10176 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10177 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10178 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10180 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10181 MonoClassField * field;
10182 gpointer iter = NULL;
10183 gboolean found_base_field = FALSE;
10185 g_assert (klass->enumtype);
10186 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10187 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10191 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10194 while ((field = mono_class_get_fields (klass, &iter))) {
10195 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10196 if (found_base_field)
10198 found_base_field = TRUE;
10199 if (!mono_type_is_valid_enum_basetype (field->type))
10204 if (!found_base_field)
10207 if (klass->method.count > 0)
10214 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10216 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10220 * mono_class_setup_interface_id:
10222 * Initializes MonoClass::interface_id if required.
10224 * LOCKING: Acquires the loader lock.
10227 mono_class_setup_interface_id (MonoClass *class)
10229 mono_loader_lock ();
10230 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
10231 class->interface_id = mono_get_unique_iid (class);
10232 mono_loader_unlock ();
10236 * mono_class_alloc_ext:
10238 * Allocate klass->ext if not already done.
10241 mono_class_alloc_ext (MonoClass *klass)
10248 ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
10249 mono_image_lock (klass->image);
10250 mono_memory_barrier ();
10253 class_ext_size += sizeof (MonoClassExt);
10254 mono_image_unlock (klass->image);
10258 * mono_class_setup_interfaces:
10260 * Initialize class->interfaces/interfaces_count.
10261 * LOCKING: Acquires the loader lock.
10262 * This function can fail the type.
10265 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10267 int i, interface_count;
10268 MonoClass **interfaces;
10270 mono_error_init (error);
10272 if (klass->interfaces_inited)
10275 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10276 MonoType *args [1];
10278 /* generic IList, ICollection, IEnumerable */
10279 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10280 interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10282 args [0] = &klass->element_class->byval_arg;
10283 interfaces [0] = mono_class_bind_generic_parameters (
10284 mono_defaults.generic_ilist_class, 1, args, FALSE);
10285 if (interface_count > 1)
10286 interfaces [1] = mono_class_bind_generic_parameters (
10287 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10288 } else if (klass->generic_class) {
10289 MonoClass *gklass = klass->generic_class->container_class;
10291 mono_class_setup_interfaces (gklass, error);
10292 if (!mono_error_ok (error)) {
10293 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10297 interface_count = gklass->interface_count;
10298 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10299 for (i = 0; i < interface_count; i++) {
10300 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10301 if (!mono_error_ok (error)) {
10302 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10307 interface_count = 0;
10311 mono_image_lock (klass->image);
10313 if (!klass->interfaces_inited) {
10314 klass->interface_count = interface_count;
10315 klass->interfaces = interfaces;
10317 mono_memory_barrier ();
10319 klass->interfaces_inited = TRUE;
10322 mono_image_unlock (klass->image);
10326 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10328 MonoClass *class = field->parent;
10329 MonoImage *image = class->image;
10330 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10331 int field_idx = field - class->fields;
10333 mono_error_init (error);
10336 MonoClassField *gfield = >d->fields [field_idx];
10337 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10338 if (!mono_error_ok (error)) {
10339 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10340 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10344 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10345 if (!mono_error_ok (error)) {
10346 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10347 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10352 guint32 cols [MONO_FIELD_SIZE];
10353 MonoGenericContainer *container = NULL;
10354 int idx = class->field.first + field_idx;
10356 /*FIXME, in theory we do not lazy load SRE fields*/
10357 g_assert (!image_is_dynamic (image));
10359 if (class->generic_container) {
10360 container = class->generic_container;
10362 container = gtd->generic_container;
10363 g_assert (container);
10366 /* class->field.first and idx points into the fieldptr table */
10367 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10369 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10370 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10371 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10375 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10377 mono_metadata_decode_value (sig, &sig);
10378 /* FIELD signature == 0x06 */
10379 g_assert (*sig == 0x06);
10380 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10382 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10387 mono_field_resolve_flags (MonoClassField *field)
10389 MonoClass *class = field->parent;
10390 MonoImage *image = class->image;
10391 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10392 int field_idx = field - class->fields;
10396 MonoClassField *gfield = >d->fields [field_idx];
10397 return mono_field_get_flags (gfield);
10399 int idx = class->field.first + field_idx;
10401 /*FIXME, in theory we do not lazy load SRE fields*/
10402 g_assert (!image_is_dynamic (image));
10404 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10409 * mono_class_setup_basic_field_info:
10410 * @class: The class to initialize
10412 * Initializes the class->fields array of fields.
10413 * Aquires the loader lock.
10416 mono_class_setup_basic_field_info_locking (MonoClass *class)
10418 mono_loader_lock ();
10419 mono_class_setup_basic_field_info (class);
10420 mono_loader_unlock ();
10424 * mono_class_get_fields_lazy:
10425 * @klass: the MonoClass to act on
10427 * This routine is an iterator routine for retrieving the fields in a class.
10428 * Only minimal information about fields are loaded. Accessors must be used
10429 * for all MonoClassField returned.
10431 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10432 * iterate over all of the elements. When no more values are
10433 * available, the return value is NULL.
10435 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10438 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10440 MonoClassField* field;
10444 mono_class_setup_basic_field_info_locking (klass);
10445 if (!klass->fields)
10447 /* start from the first */
10448 if (klass->field.count) {
10449 return *iter = &klass->fields [0];
10457 if (field < &klass->fields [klass->field.count]) {
10458 return *iter = field;
10464 mono_class_full_name (MonoClass *klass)
10466 return mono_type_full_name (&klass->byval_arg);