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)
20 #include <mono/io-layer/atomic.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/metadata-internals.h>
26 #include <mono/metadata/profiler-private.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/metadata/security-core-clr.h>
38 #include <mono/metadata/attrdefs.h>
39 #include <mono/metadata/gc-internal.h>
40 #include <mono/metadata/verify-internals.h>
41 #include <mono/metadata/mono-debug.h>
42 #include <mono/utils/mono-counters.h>
43 #include <mono/utils/mono-string.h>
44 #include <mono/utils/mono-error-internals.h>
45 #include <mono/utils/mono-logger-internal.h>
46 #include <mono/utils/mono-memory-model.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 /* Function supplied by the runtime to find classes by name using information from the AOT file */
56 static MonoGetClassFromName get_class_from_name = NULL;
58 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
59 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
60 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
61 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
62 static int generic_array_methods (MonoClass *class);
63 static void setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos);
65 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
66 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
67 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
68 static guint32 mono_field_resolve_flags (MonoClassField *field);
69 static void mono_class_setup_vtable_full (MonoClass *class, GList *in_setup);
70 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
73 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
74 void (*mono_debugger_class_loaded_methods_func) (MonoClass *klass) = NULL;
78 We use gclass recording to allow recursive system f types to be referenced by a parent.
80 Given the following type hierarchy:
82 class TextBox : TextBoxBase<TextBox> {}
83 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
84 class TextInput<T> : Input<T> where T: TextInput<T> {}
87 The runtime tries to load TextBoxBase<>.
88 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
89 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
90 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
92 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
93 at this point, iow, both are registered in the type map and both and a NULL parent. This means
94 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
96 To fix that what we do is to record all generic instantes created while resolving the parent of
97 any generic type definition and, after resolved, correct the parent field if needed.
100 static int record_gclass_instantiation;
101 static GSList *gclass_recorded_list;
102 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
105 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
108 enable_gclass_recording (void)
110 ++record_gclass_instantiation;
114 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
117 disable_gclass_recording (gclass_record_func func, void *user_data)
119 GSList **head = &gclass_recorded_list;
121 g_assert (record_gclass_instantiation > 0);
122 --record_gclass_instantiation;
125 GSList *node = *head;
126 if (func ((MonoClass*)node->data, user_data)) {
128 g_slist_free_1 (node);
134 /* We automatically discard all recorded gclasses when disabled. */
135 if (!record_gclass_instantiation && gclass_recorded_list) {
136 g_slist_free (gclass_recorded_list);
137 gclass_recorded_list = NULL;
142 * mono_class_from_typeref:
143 * @image: a MonoImage
144 * @type_token: a TypeRef token
146 * Creates the MonoClass* structure representing the type defined by
147 * the typeref token valid inside @image.
148 * Returns: the MonoClass* representing the typeref token, NULL ifcould
152 mono_class_from_typeref (MonoImage *image, guint32 type_token)
155 guint32 cols [MONO_TYPEREF_SIZE];
156 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
158 const char *name, *nspace;
162 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
163 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
167 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
169 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
170 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
172 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
173 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
174 case MONO_RESOLTION_SCOPE_MODULE:
176 g_error ("null ResolutionScope not yet handled");
177 /* a typedef in disguise */
178 return mono_class_from_name (image, nspace, name);
179 case MONO_RESOLTION_SCOPE_MODULEREF:
180 module = mono_image_load_module (image, idx);
182 return mono_class_from_name (module, nspace, name);
184 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
187 human_name = mono_stringify_assembly_name (&image->assembly->aname);
188 mono_loader_set_error_type_load (msg, human_name);
194 case MONO_RESOLTION_SCOPE_TYPEREF: {
195 MonoClass *enclosing;
198 if (idx == mono_metadata_token_index (type_token)) {
199 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
203 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
207 if (enclosing->nested_classes_inited && enclosing->ext) {
208 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
209 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
211 if (strcmp (res->name, name) == 0)
215 /* Don't call mono_class_init as we might've been called by it recursively */
216 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
218 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
219 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
220 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
222 if (strcmp (nname, name) == 0)
223 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
225 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
228 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
231 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
235 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
236 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
240 if (!image->references || !image->references [idx - 1])
241 mono_assembly_load_reference (image, idx - 1);
242 g_assert (image->references [idx - 1]);
244 /* If the assembly did not load, register this as a type load exception */
245 if (image->references [idx - 1] == REFERENCE_MISSING){
246 MonoAssemblyName aname;
249 mono_assembly_get_assemblyref (image, idx - 1, &aname);
250 human_name = mono_stringify_assembly_name (&aname);
251 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
257 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
262 mono_image_memdup (MonoImage *image, void *data, guint size)
264 void *res = mono_image_alloc (image, size);
265 memcpy (res, data, size);
269 /* Copy everything mono_metadata_free_array free. */
271 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
274 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
276 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
278 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
280 a = g_memdup (a, sizeof (MonoArrayType));
282 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
284 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
289 /* Copy everything mono_metadata_free_method_signature free. */
291 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
295 sig = mono_metadata_signature_dup_full (image, sig);
297 sig->ret = mono_metadata_type_dup (image, sig->ret);
298 for (i = 0; i < sig->param_count; ++i)
299 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
305 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
307 MonoAssembly *ta = klass->image->assembly;
310 name = mono_stringify_assembly_name (&ta->aname);
311 g_string_append_printf (str, ", %s", name);
316 mono_type_name_check_byref (MonoType *type, GString *str)
319 g_string_append_c (str, '&');
323 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
324 MonoTypeNameFormat format)
328 switch (type->type) {
329 case MONO_TYPE_ARRAY: {
330 int i, rank = type->data.array->rank;
331 MonoTypeNameFormat nested_format;
333 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
334 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
336 mono_type_get_name_recurse (
337 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
338 g_string_append_c (str, '[');
340 g_string_append_c (str, '*');
341 for (i = 1; i < rank; i++)
342 g_string_append_c (str, ',');
343 g_string_append_c (str, ']');
345 mono_type_name_check_byref (type, str);
347 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
348 _mono_type_get_assembly_name (type->data.array->eklass, str);
351 case MONO_TYPE_SZARRAY: {
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.klass->byval_arg, str, FALSE, nested_format);
359 g_string_append (str, "[]");
361 mono_type_name_check_byref (type, str);
363 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
364 _mono_type_get_assembly_name (type->data.klass, str);
367 case MONO_TYPE_PTR: {
368 MonoTypeNameFormat nested_format;
370 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
371 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
373 mono_type_get_name_recurse (
374 type->data.type, str, FALSE, nested_format);
375 g_string_append_c (str, '*');
377 mono_type_name_check_byref (type, str);
379 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
380 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
385 if (!mono_generic_param_info (type->data.generic_param))
386 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
388 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
390 mono_type_name_check_byref (type, str);
394 klass = mono_class_from_mono_type (type);
395 if (klass->nested_in) {
396 mono_type_get_name_recurse (
397 &klass->nested_in->byval_arg, str, TRUE, format);
398 if (format == MONO_TYPE_NAME_FORMAT_IL)
399 g_string_append_c (str, '.');
401 g_string_append_c (str, '+');
402 } else if (*klass->name_space) {
403 g_string_append (str, klass->name_space);
404 g_string_append_c (str, '.');
406 if (format == MONO_TYPE_NAME_FORMAT_IL) {
407 char *s = strchr (klass->name, '`');
408 int len = s ? s - klass->name : strlen (klass->name);
410 g_string_append_len (str, klass->name, len);
412 g_string_append (str, klass->name);
415 if (klass->generic_class) {
416 MonoGenericClass *gclass = klass->generic_class;
417 MonoGenericInst *inst = gclass->context.class_inst;
418 MonoTypeNameFormat nested_format;
421 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
422 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
424 if (format == MONO_TYPE_NAME_FORMAT_IL)
425 g_string_append_c (str, '<');
427 g_string_append_c (str, '[');
428 for (i = 0; i < inst->type_argc; i++) {
429 MonoType *t = inst->type_argv [i];
432 g_string_append_c (str, ',');
433 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
434 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
435 g_string_append_c (str, '[');
436 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
437 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
438 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
439 g_string_append_c (str, ']');
441 if (format == MONO_TYPE_NAME_FORMAT_IL)
442 g_string_append_c (str, '>');
444 g_string_append_c (str, ']');
445 } else if (klass->generic_container &&
446 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
447 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
450 if (format == MONO_TYPE_NAME_FORMAT_IL)
451 g_string_append_c (str, '<');
453 g_string_append_c (str, '[');
454 for (i = 0; i < klass->generic_container->type_argc; i++) {
456 g_string_append_c (str, ',');
457 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
459 if (format == MONO_TYPE_NAME_FORMAT_IL)
460 g_string_append_c (str, '>');
462 g_string_append_c (str, ']');
465 mono_type_name_check_byref (type, str);
467 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
468 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
469 _mono_type_get_assembly_name (klass, str);
475 * mono_type_get_name_full:
477 * @format: the format for the return string.
480 * Returns: the string representation in a number of formats:
482 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
483 * returned in the formatrequired by System.Reflection, this is the
484 * inverse of mono_reflection_parse_type ().
486 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
487 * be used by the IL assembler.
489 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
491 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
494 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
498 result = g_string_new ("");
500 mono_type_get_name_recurse (type, result, FALSE, format);
502 return g_string_free (result, FALSE);
506 * mono_type_get_full_name:
509 * Returns: the string representation for type as required by System.Reflection.
510 * The inverse of mono_reflection_parse_type ().
513 mono_type_get_full_name (MonoClass *class)
515 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
519 * mono_type_get_name:
522 * Returns: the string representation for type as it would be represented in IL code.
525 mono_type_get_name (MonoType *type)
527 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
531 * mono_type_get_underlying_type:
534 * Returns: the MonoType for the underlying integer type if @type
535 * is an enum and byref is false, otherwise the type itself.
538 mono_type_get_underlying_type (MonoType *type)
540 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
541 return mono_class_enum_basetype (type->data.klass);
542 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
543 return mono_class_enum_basetype (type->data.generic_class->container_class);
548 * mono_class_is_open_constructed_type:
551 * Returns TRUE if type represents a generics open constructed type.
552 * IOW, not all type parameters required for the instantiation have
553 * been provided or it's a generic type definition.
555 * An open constructed type means it's a non realizable type. Not to
556 * be mixed up with an abstract type - we can't cast or dispatch to
557 * an open type, for example.
560 mono_class_is_open_constructed_type (MonoType *t)
566 case MONO_TYPE_SZARRAY:
567 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
568 case MONO_TYPE_ARRAY:
569 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
571 return mono_class_is_open_constructed_type (t->data.type);
572 case MONO_TYPE_GENERICINST:
573 return t->data.generic_class->context.class_inst->is_open;
574 case MONO_TYPE_CLASS:
575 case MONO_TYPE_VALUETYPE:
576 return t->data.klass->generic_container != NULL;
583 This is a simple function to catch the most common bad instances of generic types.
584 Specially those that might lead to further failures in the runtime.
587 is_valid_generic_argument (MonoType *type)
589 switch (type->type) {
591 case MONO_TYPE_TYPEDBYREF:
598 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
600 mono_error_init (error);
602 switch (type->type) {
603 case MONO_TYPE_MVAR: {
605 int num = mono_type_get_generic_param_num (type);
606 MonoGenericInst *inst = context->method_inst;
607 if (!inst || !inst->type_argv)
609 if (num >= inst->type_argc) {
610 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
611 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
612 num, info ? info->name : "", inst->type_argc);
616 if (!is_valid_generic_argument (inst->type_argv [num])) {
617 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
618 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
619 num, info ? info->name : "", inst->type_argv [num]->type);
623 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
624 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
625 * ->byref and ->attrs from @type are propagated to the returned type.
627 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
628 nt->byref = type->byref;
629 nt->attrs = type->attrs;
632 case MONO_TYPE_VAR: {
634 int num = mono_type_get_generic_param_num (type);
635 MonoGenericInst *inst = context->class_inst;
638 if (num >= inst->type_argc) {
639 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
640 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
641 num, info ? info->name : "", inst->type_argc);
644 if (!is_valid_generic_argument (inst->type_argv [num])) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
647 num, info ? info->name : "", inst->type_argv [num]->type);
650 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
651 nt->byref = type->byref;
652 nt->attrs = type->attrs;
655 case MONO_TYPE_SZARRAY: {
656 MonoClass *eclass = type->data.klass;
657 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
658 if (!inflated || !mono_error_ok (error))
660 nt = mono_metadata_type_dup (image, type);
661 nt->data.klass = mono_class_from_mono_type (inflated);
662 mono_metadata_free_type (inflated);
665 case MONO_TYPE_ARRAY: {
666 MonoClass *eclass = type->data.array->eklass;
667 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
668 if (!inflated || !mono_error_ok (error))
670 nt = mono_metadata_type_dup (image, type);
671 nt->data.array->eklass = mono_class_from_mono_type (inflated);
672 mono_metadata_free_type (inflated);
675 case MONO_TYPE_GENERICINST: {
676 MonoGenericClass *gclass = type->data.generic_class;
677 MonoGenericInst *inst;
679 if (!gclass->context.class_inst->is_open)
682 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
683 if (!mono_error_ok (error))
685 if (inst != gclass->context.class_inst)
686 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
688 if (gclass == type->data.generic_class)
691 nt = mono_metadata_type_dup (image, type);
692 nt->data.generic_class = gclass;
695 case MONO_TYPE_CLASS:
696 case MONO_TYPE_VALUETYPE: {
697 MonoClass *klass = type->data.klass;
698 MonoGenericContainer *container = klass->generic_container;
699 MonoGenericInst *inst;
700 MonoGenericClass *gclass = NULL;
706 /* We can't use context->class_inst directly, since it can have more elements */
707 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
708 if (!mono_error_ok (error))
710 if (inst == container->context.class_inst)
713 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
715 nt = mono_metadata_type_dup (image, type);
716 nt->type = MONO_TYPE_GENERICINST;
717 nt->data.generic_class = gclass;
727 mono_generic_class_get_context (MonoGenericClass *gclass)
729 return &gclass->context;
733 mono_class_get_context (MonoClass *class)
735 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
739 * mono_class_get_generic_container:
741 * Return the generic container of KLASS which should be a generic type definition.
743 MonoGenericContainer*
744 mono_class_get_generic_container (MonoClass *klass)
746 g_assert (klass->is_generic);
748 return klass->generic_container;
752 * mono_class_get_generic_class:
754 * Return the MonoGenericClass of KLASS, which should be a generic instance.
757 mono_class_get_generic_class (MonoClass *klass)
759 g_assert (klass->is_inflated);
761 return klass->generic_class;
765 * mono_class_inflate_generic_type_with_mempool:
766 * @mempool: a mempool
768 * @context: a generics context
769 * @error: error context
771 * The same as mono_class_inflate_generic_type, but allocates the MonoType
772 * from mempool if it is non-NULL. If it is NULL, the MonoType is
773 * allocated on the heap and is owned by the caller.
774 * The returned type can potentially be the same as TYPE, so it should not be
775 * modified by the caller, and it should be freed using mono_metadata_free_type ().
778 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
780 MonoType *inflated = NULL;
781 mono_error_init (error);
784 inflated = inflate_generic_type (image, type, context, error);
785 if (!mono_error_ok (error))
789 MonoType *shared = mono_metadata_get_shared_type (type);
794 return mono_metadata_type_dup (image, type);
798 mono_stats.inflated_type_count++;
803 * mono_class_inflate_generic_type:
805 * @context: a generics context
807 * If @type is a generic type and @context is not NULL, instantiate it using the
808 * generics context @context.
810 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
811 * on the heap and is owned by the caller. Returns NULL on error.
813 * @deprecated Please use mono_class_inflate_generic_type_checked instead
816 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
820 result = mono_class_inflate_generic_type_checked (type, context, &error);
822 if (!mono_error_ok (&error)) {
823 mono_error_cleanup (&error);
830 * mono_class_inflate_generic_type:
832 * @context: a generics context
833 * @error: error context to use
835 * If @type is a generic type and @context is not NULL, instantiate it using the
836 * generics context @context.
838 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
839 * on the heap and is owned by the caller.
842 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
844 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
848 * mono_class_inflate_generic_type_no_copy:
850 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
854 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
856 MonoType *inflated = NULL;
858 mono_error_init (error);
860 inflated = inflate_generic_type (image, type, context, error);
861 if (!mono_error_ok (error))
868 mono_stats.inflated_type_count++;
873 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
878 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
879 if (!mono_error_ok (error))
882 res = mono_class_from_mono_type (inflated);
883 mono_metadata_free_type (inflated);
888 * mono_class_inflate_generic_class:
890 * Inflate the class GKLASS with CONTEXT.
893 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
898 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
899 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
906 static MonoGenericContext
907 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
909 MonoGenericInst *class_inst = NULL;
910 MonoGenericInst *method_inst = NULL;
911 MonoGenericContext res = { NULL, NULL };
913 mono_error_init (error);
915 if (context->class_inst) {
916 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
917 if (!mono_error_ok (error))
921 if (context->method_inst) {
922 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
923 if (!mono_error_ok (error))
927 res.class_inst = class_inst;
928 res.method_inst = method_inst;
934 * mono_class_inflate_generic_method:
935 * @method: a generic method
936 * @context: a generics context
938 * Instantiate the generic method @method using the generics context @context.
940 * Returns: the new instantiated method
943 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
945 return mono_class_inflate_generic_method_full (method, NULL, context);
949 * mono_class_inflate_generic_method_full:
951 * Instantiate method @method with the generic context @context.
952 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
953 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
956 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
959 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
960 if (!mono_error_ok (&error))
961 /*FIXME do proper error handling - on this case, kill this function. */
962 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
968 * mono_class_inflate_generic_method_full_checked:
969 * Same as mono_class_inflate_generic_method_full but return failure using @error.
972 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
975 MonoMethodInflated *iresult, *cached;
976 MonoMethodSignature *sig;
977 MonoGenericContext tmp_context;
978 gboolean is_mb_open = FALSE;
980 mono_error_init (error);
982 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
983 while (method->is_inflated) {
984 MonoGenericContext *method_context = mono_method_get_context (method);
985 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
987 tmp_context = inflate_generic_context (method_context, context, error);
988 if (!mono_error_ok (error))
990 context = &tmp_context;
992 if (mono_metadata_generic_context_equal (method_context, context))
995 method = imethod->declaring;
999 * A method only needs to be inflated if the context has argument for which it is
1002 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1003 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1006 if (!((method->is_generic && context->method_inst) ||
1007 (method->klass->generic_container && context->class_inst)))
1011 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1012 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1013 * This is opposite to the way non-SRE MethodInfos behave.
1015 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1017 * void Example<T> () {
1021 * In Example, the method token must be encoded as: "void Example<!!0>()"
1023 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1024 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1026 * On the other hand, inflating a non-SRE generic method with its own arguments should
1027 * return itself. For example:
1029 * MethodInfo m = ... //m is a generic method definition
1030 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1033 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1034 * what happens with regular methods.
1036 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1037 * everything should behave like a regular type or method.
1040 is_mb_open = method->is_generic &&
1041 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1042 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1044 iresult = g_new0 (MonoMethodInflated, 1);
1045 iresult->context = *context;
1046 iresult->declaring = method;
1047 iresult->method.method.is_mb_open = is_mb_open;
1049 if (!context->method_inst && method->is_generic)
1050 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1052 if (!context->class_inst) {
1053 g_assert (!iresult->declaring->klass->generic_class);
1054 if (iresult->declaring->klass->generic_container)
1055 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1056 else if (iresult->declaring->klass->generic_class)
1057 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1060 mono_loader_lock ();
1061 cached = mono_method_inflated_lookup (iresult, FALSE);
1063 mono_loader_unlock ();
1065 return (MonoMethod*)cached;
1068 mono_stats.inflated_method_count++;
1070 inflated_methods_size += sizeof (MonoMethodInflated);
1072 sig = mono_method_signature (method);
1074 char *name = mono_type_get_full_name (method->klass);
1075 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1081 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1083 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1086 result = (MonoMethod *) iresult;
1087 result->is_inflated = TRUE;
1088 result->is_generic = FALSE;
1089 result->sre_method = FALSE;
1090 result->signature = NULL;
1091 result->is_mb_open = is_mb_open;
1093 if (!context->method_inst) {
1094 /* Set the generic_container of the result to the generic_container of method */
1095 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1097 if (generic_container) {
1098 result->is_generic = 1;
1099 mono_method_set_generic_container (result, generic_container);
1103 if (!klass_hint || !klass_hint->generic_class ||
1104 klass_hint->generic_class->container_class != method->klass ||
1105 klass_hint->generic_class->context.class_inst != context->class_inst)
1108 if (method->klass->generic_container)
1109 result->klass = klass_hint;
1111 if (!result->klass) {
1112 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1113 if (!mono_error_ok (error))
1116 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1118 mono_metadata_free_type (inflated);
1122 * FIXME: This should hold, but it doesn't:
1124 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1125 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1126 * g_assert (result->is_generic);
1129 * Fixing this here causes other things to break, hence a very
1130 * ugly hack in mini-trampolines.c - see
1131 * is_generic_method_definition().
1134 mono_method_inflated_lookup (iresult, TRUE);
1135 mono_loader_unlock ();
1139 mono_loader_unlock ();
1145 * mono_get_inflated_method:
1147 * Obsolete. We keep it around since it's mentioned in the public API.
1150 mono_get_inflated_method (MonoMethod *method)
1156 * mono_method_get_context_general:
1158 * @uninflated: handle uninflated methods?
1160 * Returns the generic context of a method or NULL if it doesn't have
1161 * one. For an inflated method that's the context stored in the
1162 * method. Otherwise it's in the method's generic container or in the
1163 * generic container of the method's class.
1166 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1168 if (method->is_inflated) {
1169 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1170 return &imethod->context;
1174 if (method->is_generic)
1175 return &(mono_method_get_generic_container (method)->context);
1176 if (method->klass->generic_container)
1177 return &method->klass->generic_container->context;
1182 * mono_method_get_context:
1185 * Returns the generic context for method if it's inflated, otherwise
1189 mono_method_get_context (MonoMethod *method)
1191 return mono_method_get_context_general (method, FALSE);
1195 * mono_method_get_generic_container:
1197 * Returns the generic container of METHOD, which should be a generic method definition.
1198 * Returns NULL if METHOD is not a generic method definition.
1199 * LOCKING: Acquires the loader lock.
1201 MonoGenericContainer*
1202 mono_method_get_generic_container (MonoMethod *method)
1204 MonoGenericContainer *container;
1206 if (!method->is_generic)
1209 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1210 g_assert (container);
1216 * mono_method_set_generic_container:
1218 * Sets the generic container of METHOD to CONTAINER.
1219 * LOCKING: Acquires the loader lock.
1222 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1224 g_assert (method->is_generic);
1226 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1230 * mono_class_find_enum_basetype:
1231 * @class: The enum class
1233 * Determine the basetype of an enum by iterating through its fields. We do this
1234 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1237 mono_class_find_enum_basetype (MonoClass *class)
1239 MonoGenericContainer *container = NULL;
1240 MonoImage *m = class->image;
1241 const int top = class->field.count;
1244 g_assert (class->enumtype);
1246 if (class->generic_container)
1247 container = class->generic_container;
1248 else if (class->generic_class) {
1249 MonoClass *gklass = class->generic_class->container_class;
1251 container = gklass->generic_container;
1252 g_assert (container);
1256 * Fetch all the field information.
1258 for (i = 0; i < top; i++){
1260 guint32 cols [MONO_FIELD_SIZE];
1261 int idx = class->field.first + i;
1264 /* class->field.first and idx points into the fieldptr table */
1265 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1267 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1270 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1273 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1274 mono_metadata_decode_value (sig, &sig);
1275 /* FIELD signature == 0x06 */
1279 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1282 if (class->generic_class) {
1283 //FIXME do we leak here?
1284 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1285 ftype->attrs = cols [MONO_FIELD_FLAGS];
1295 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1298 mono_type_has_exceptions (MonoType *type)
1300 switch (type->type) {
1301 case MONO_TYPE_CLASS:
1302 case MONO_TYPE_VALUETYPE:
1303 case MONO_TYPE_SZARRAY:
1304 return type->data.klass->exception_type;
1305 case MONO_TYPE_ARRAY:
1306 return type->data.array->eklass->exception_type;
1307 case MONO_TYPE_GENERICINST:
1308 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1316 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1320 mono_class_alloc (MonoClass *class, int size)
1322 if (class->generic_class)
1323 return mono_image_set_alloc (class->generic_class->owner, size);
1325 return mono_image_alloc (class->image, size);
1329 mono_class_alloc0 (MonoClass *class, int size)
1333 res = mono_class_alloc (class, size);
1334 memset (res, 0, size);
1338 #define mono_class_new0(class,struct_type, n_structs) \
1339 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1342 * mono_class_setup_basic_field_info:
1343 * @class: The class to initialize
1345 * Initializes the class->fields.
1346 * LOCKING: Assumes the loader lock is held.
1349 mono_class_setup_basic_field_info (MonoClass *class)
1351 MonoClassField *field;
1359 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1360 image = class->image;
1361 top = class->field.count;
1363 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1365 * This happens when a generic instance of an unfinished generic typebuilder
1366 * is used as an element type for creating an array type. We can't initialize
1367 * the fields of this class using the fields of gklass, since gklass is not
1368 * finished yet, fields could be added to it later.
1374 mono_class_setup_basic_field_info (gtd);
1376 top = gtd->field.count;
1377 class->field.first = gtd->field.first;
1378 class->field.count = gtd->field.count;
1381 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1384 * Fetch all the field information.
1386 for (i = 0; i < top; i++){
1387 field = &class->fields [i];
1388 field->parent = class;
1391 field->name = mono_field_get_name (>d->fields [i]);
1393 int idx = class->field.first + i;
1394 /* class->field.first and idx points into the fieldptr table */
1395 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1396 /* The name is needed for fieldrefs */
1397 field->name = mono_metadata_string_heap (image, name_idx);
1403 * mono_class_setup_fields:
1404 * @class: The class to initialize
1406 * Initializes the class->fields.
1407 * LOCKING: Assumes the loader lock is held.
1410 mono_class_setup_fields (MonoClass *class)
1413 MonoImage *m = class->image;
1415 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1416 int i, blittable = TRUE;
1417 guint32 real_size = 0;
1418 guint32 packing_size = 0;
1419 gboolean explicit_size;
1420 MonoClassField *field;
1421 MonoGenericContainer *container = NULL;
1422 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1424 if (class->size_inited)
1427 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1429 * This happens when a generic instance of an unfinished generic typebuilder
1430 * is used as an element type for creating an array type. We can't initialize
1431 * the fields of this class using the fields of gklass, since gklass is not
1432 * finished yet, fields could be added to it later.
1437 mono_class_setup_basic_field_info (class);
1438 top = class->field.count;
1441 mono_class_setup_fields (gtd);
1442 if (gtd->exception_type) {
1443 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1448 class->instance_size = 0;
1450 class->sizes.class_size = 0;
1452 if (class->parent) {
1453 /* For generic instances, class->parent might not have been initialized */
1454 mono_class_init (class->parent);
1455 if (!class->parent->size_inited) {
1456 mono_class_setup_fields (class->parent);
1457 if (class->parent->exception_type) {
1458 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1462 class->instance_size += class->parent->instance_size;
1463 class->min_align = class->parent->min_align;
1464 /* we use |= since it may have been set already */
1465 class->has_references |= class->parent->has_references;
1466 blittable = class->parent->blittable;
1468 class->instance_size = sizeof (MonoObject);
1469 class->min_align = 1;
1472 /* We can't really enable 16 bytes alignment until the GC supports it.
1473 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1474 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1475 Bug #506144 is an example of this issue.
1477 if (class->simd_type)
1478 class->min_align = 16;
1480 /* Get the real size */
1481 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1483 if (explicit_size) {
1484 if ((packing_size & 0xfffffff0) != 0) {
1485 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1486 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1489 class->packing_size = packing_size;
1490 real_size += class->instance_size;
1494 if (explicit_size && real_size) {
1495 class->instance_size = MAX (real_size, class->instance_size);
1497 class->size_inited = 1;
1498 class->blittable = blittable;
1499 mono_memory_barrier ();
1500 class->fields_inited = 1;
1504 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1507 /* Prevent infinite loops if the class references itself */
1508 class->size_inited = 1;
1510 if (class->generic_container) {
1511 container = class->generic_container;
1513 container = gtd->generic_container;
1514 g_assert (container);
1518 * Fetch all the field information.
1520 for (i = 0; i < top; i++){
1521 int idx = class->field.first + i;
1522 field = &class->fields [i];
1524 field->parent = class;
1527 mono_field_resolve_type (field, &error);
1528 if (!mono_error_ok (&error)) {
1529 /*mono_field_resolve_type already failed class*/
1530 mono_error_cleanup (&error);
1534 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1535 g_assert (field->type);
1538 if (mono_field_is_deleted (field))
1541 MonoClassField *gfield = >d->fields [i];
1542 field->offset = gfield->offset;
1544 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1546 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1547 field->offset = offset;
1549 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1550 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1553 if (field->offset < -1) { /*-1 is used to encode special static fields */
1554 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1560 /* Only do these checks if we still think this type is blittable */
1561 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1562 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1565 MonoClass *field_class = mono_class_from_mono_type (field->type);
1567 mono_class_setup_fields (field_class);
1568 if (field_class->exception_type) {
1569 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1573 if (!field_class || !field_class->blittable)
1578 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1579 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1580 blittable = class->element_class->blittable;
1583 if (mono_type_has_exceptions (field->type)) {
1584 char *class_name = mono_type_get_full_name (class);
1585 char *type_name = mono_type_full_name (field->type);
1587 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1588 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1589 g_free (class_name);
1593 /* The def_value of fields is compute lazily during vtable creation */
1596 if (class == mono_defaults.string_class)
1599 class->blittable = blittable;
1601 if (class->enumtype && !mono_class_enum_basetype (class)) {
1602 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1605 if (explicit_size && real_size) {
1606 class->instance_size = MAX (real_size, class->instance_size);
1609 if (class->exception_type)
1611 mono_class_layout_fields (class);
1613 /*valuetypes can't be neither bigger than 1Mb or empty. */
1614 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1615 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1617 mono_memory_barrier ();
1618 class->fields_inited = 1;
1622 * mono_class_setup_fields_locking:
1623 * @class: The class to initialize
1625 * Initializes the class->fields array of fields.
1626 * Aquires the loader lock.
1629 mono_class_setup_fields_locking (MonoClass *class)
1631 /* This can be checked without locks */
1632 if (class->fields_inited)
1634 mono_loader_lock ();
1635 mono_class_setup_fields (class);
1636 mono_loader_unlock ();
1640 * mono_class_has_references:
1642 * Returns whenever @klass->has_references is set, initializing it if needed.
1643 * Aquires the loader lock.
1646 mono_class_has_references (MonoClass *klass)
1648 if (klass->init_pending) {
1649 /* Be conservative */
1652 mono_class_init (klass);
1654 return klass->has_references;
1659 * mono_type_get_basic_type_from_generic:
1662 * Returns a closed type corresponding to the possibly open type
1666 mono_type_get_basic_type_from_generic (MonoType *type)
1668 /* When we do generic sharing we let type variables stand for reference types. */
1669 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1670 return &mono_defaults.object_class->byval_arg;
1675 * mono_class_layout_fields:
1678 * Compute the placement of fields inside an object or struct, according to
1679 * the layout rules and set the following fields in @class:
1680 * - has_references (if the class contains instance references firled or structs that contain references)
1681 * - has_static_refs (same, but for static fields)
1682 * - instance_size (size of the object in memory)
1683 * - class_size (size needed for the static fields)
1684 * - size_inited (flag set when the instance_size is set)
1686 * LOCKING: this is supposed to be called with the loader lock held.
1689 mono_class_layout_fields (MonoClass *class)
1692 const int top = class->field.count;
1693 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1694 guint32 pass, passes, real_size;
1695 gboolean gc_aware_layout = FALSE;
1696 MonoClassField *field;
1699 * When we do generic sharing we need to have layout
1700 * information for open generic classes (either with a generic
1701 * context containing type variables or with a generic
1702 * container), so we don't return in that case anymore.
1706 * Enable GC aware auto layout: in this mode, reference
1707 * fields are grouped together inside objects, increasing collector
1709 * Requires that all classes whose layout is known to native code be annotated
1710 * with [StructLayout (LayoutKind.Sequential)]
1711 * Value types have gc_aware_layout disabled by default, as per
1712 * what the default is for other runtimes.
1714 /* corlib is missing [StructLayout] directives in many places */
1715 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1716 if (!class->valuetype)
1717 gc_aware_layout = TRUE;
1720 /* Compute klass->has_references */
1722 * Process non-static fields first, since static fields might recursively
1723 * refer to the class itself.
1725 for (i = 0; i < top; i++) {
1728 field = &class->fields [i];
1730 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1731 ftype = mono_type_get_underlying_type (field->type);
1732 ftype = mono_type_get_basic_type_from_generic (ftype);
1733 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1734 class->has_references = TRUE;
1738 for (i = 0; i < top; i++) {
1741 field = &class->fields [i];
1743 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1744 ftype = mono_type_get_underlying_type (field->type);
1745 ftype = mono_type_get_basic_type_from_generic (ftype);
1746 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1747 class->has_static_refs = TRUE;
1751 for (i = 0; i < top; i++) {
1754 field = &class->fields [i];
1756 ftype = mono_type_get_underlying_type (field->type);
1757 ftype = mono_type_get_basic_type_from_generic (ftype);
1758 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1759 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1760 class->has_static_refs = TRUE;
1762 class->has_references = TRUE;
1767 * Compute field layout and total size (not considering static fields)
1771 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1772 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1774 if (gc_aware_layout)
1779 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1782 if (class->parent) {
1783 mono_class_setup_fields (class->parent);
1784 if (class->parent->exception_type) {
1785 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1788 real_size = class->parent->instance_size;
1790 real_size = sizeof (MonoObject);
1793 for (pass = 0; pass < passes; ++pass) {
1794 for (i = 0; i < top; i++){
1799 field = &class->fields [i];
1801 if (mono_field_is_deleted (field))
1803 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1806 ftype = mono_type_get_underlying_type (field->type);
1807 ftype = mono_type_get_basic_type_from_generic (ftype);
1808 if (gc_aware_layout) {
1809 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 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1819 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1820 /* This field is a hack inserted by MCS to empty structures */
1824 size = mono_type_size (field->type, &align);
1826 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1827 align = class->packing_size ? MIN (class->packing_size, align): align;
1828 /* if the field has managed references, we need to force-align it
1831 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1832 align = MAX (align, sizeof (gpointer));
1834 class->min_align = MAX (align, class->min_align);
1835 field->offset = real_size;
1837 field->offset += align - 1;
1838 field->offset &= ~(align - 1);
1840 /*TypeBuilders produce all sort of weird things*/
1841 g_assert (class->image->dynamic || field->offset > 0);
1842 real_size = field->offset + size;
1845 class->instance_size = MAX (real_size, class->instance_size);
1847 if (class->instance_size & (class->min_align - 1)) {
1848 class->instance_size += class->min_align - 1;
1849 class->instance_size &= ~(class->min_align - 1);
1853 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1855 for (i = 0; i < top; i++) {
1860 field = &class->fields [i];
1863 * There must be info about all the fields in a type if it
1864 * uses explicit layout.
1867 if (mono_field_is_deleted (field))
1869 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1872 size = mono_type_size (field->type, &align);
1873 align = class->packing_size ? MIN (class->packing_size, align): align;
1874 class->min_align = MAX (align, class->min_align);
1877 * When we get here, field->offset is already set by the
1878 * loader (for either runtime fields or fields loaded from metadata).
1879 * The offset is from the start of the object: this works for both
1880 * classes and valuetypes.
1882 field->offset += sizeof (MonoObject);
1883 ftype = mono_type_get_underlying_type (field->type);
1884 ftype = mono_type_get_basic_type_from_generic (ftype);
1885 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1886 if (field->offset % sizeof (gpointer)) {
1887 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1894 real_size = MAX (real_size, size + field->offset);
1896 class->instance_size = MAX (real_size, class->instance_size);
1897 if (class->instance_size & (class->min_align - 1)) {
1898 class->instance_size += class->min_align - 1;
1899 class->instance_size &= ~(class->min_align - 1);
1904 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1906 * For small structs, set min_align to at least the struct size to improve
1907 * performance, and since the JIT memset/memcpy code assumes this and generates
1908 * unaligned accesses otherwise. See #78990 for a testcase.
1910 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1911 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1914 class->size_inited = 1;
1917 * Compute static field layout and size
1919 for (i = 0; i < top; i++){
1923 field = &class->fields [i];
1925 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1927 if (mono_field_is_deleted (field))
1930 if (mono_type_has_exceptions (field->type)) {
1931 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1935 size = mono_type_size (field->type, &align);
1936 field->offset = class->sizes.class_size;
1937 /*align is always non-zero here*/
1938 field->offset += align - 1;
1939 field->offset &= ~(align - 1);
1940 class->sizes.class_size = field->offset + size;
1945 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
1949 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
1950 method->klass = class;
1951 method->flags = METHOD_ATTRIBUTE_PUBLIC;
1952 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1953 method->signature = sig;
1954 method->name = name;
1957 if (name [0] == '.') {
1958 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1960 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
1966 * mono_class_setup_methods:
1969 * Initializes the 'methods' array in the klass.
1970 * Calling this method should be avoided if possible since it allocates a lot
1971 * of long-living MonoMethod structures.
1972 * Methods belonging to an interface are assigned a sequential slot starting
1975 * On failure this function sets class->exception_type
1978 mono_class_setup_methods (MonoClass *class)
1981 MonoMethod **methods;
1986 mono_loader_lock ();
1988 if (class->methods) {
1989 mono_loader_unlock ();
1993 if (class->generic_class) {
1995 MonoClass *gklass = class->generic_class->container_class;
1997 mono_class_init (gklass);
1998 if (!gklass->exception_type)
1999 mono_class_setup_methods (gklass);
2000 if (gklass->exception_type) {
2001 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2002 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2003 mono_loader_unlock ();
2007 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2008 class->method.count = gklass->method.count;
2009 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2011 for (i = 0; i < class->method.count; i++) {
2012 methods [i] = mono_class_inflate_generic_method_full_checked (
2013 gklass->methods [i], class, mono_class_get_context (class), &error);
2014 if (!mono_error_ok (&error)) {
2015 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2016 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)));
2019 mono_error_cleanup (&error);
2020 mono_loader_unlock ();
2024 } else if (class->rank) {
2026 MonoMethod *amethod;
2027 MonoMethodSignature *sig;
2028 int count_generic = 0, first_generic = 0;
2031 class->method.count = 3 + (class->rank > 1? 2: 1);
2033 mono_class_setup_interfaces (class, &error);
2034 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2036 if (class->interface_count) {
2037 count_generic = generic_array_methods (class);
2038 first_generic = class->method.count;
2039 class->method.count += class->interface_count * count_generic;
2042 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2044 sig = mono_metadata_signature_alloc (class->image, class->rank);
2045 sig->ret = &mono_defaults.void_class->byval_arg;
2046 sig->pinvoke = TRUE;
2047 sig->hasthis = TRUE;
2048 for (i = 0; i < class->rank; ++i)
2049 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2051 amethod = create_array_method (class, ".ctor", sig);
2052 methods [method_num++] = amethod;
2053 if (class->rank > 1) {
2054 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2055 sig->ret = &mono_defaults.void_class->byval_arg;
2056 sig->pinvoke = TRUE;
2057 sig->hasthis = TRUE;
2058 for (i = 0; i < class->rank * 2; ++i)
2059 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2061 amethod = create_array_method (class, ".ctor", sig);
2062 methods [method_num++] = amethod;
2064 /* element Get (idx11, [idx2, ...]) */
2065 sig = mono_metadata_signature_alloc (class->image, class->rank);
2066 sig->ret = &class->element_class->byval_arg;
2067 sig->pinvoke = TRUE;
2068 sig->hasthis = TRUE;
2069 for (i = 0; i < class->rank; ++i)
2070 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2071 amethod = create_array_method (class, "Get", sig);
2072 methods [method_num++] = amethod;
2073 /* element& Address (idx11, [idx2, ...]) */
2074 sig = mono_metadata_signature_alloc (class->image, class->rank);
2075 sig->ret = &class->element_class->this_arg;
2076 sig->pinvoke = TRUE;
2077 sig->hasthis = TRUE;
2078 for (i = 0; i < class->rank; ++i)
2079 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2080 amethod = create_array_method (class, "Address", sig);
2081 methods [method_num++] = amethod;
2082 /* void Set (idx11, [idx2, ...], element) */
2083 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2084 sig->ret = &mono_defaults.void_class->byval_arg;
2085 sig->pinvoke = TRUE;
2086 sig->hasthis = TRUE;
2087 for (i = 0; i < class->rank; ++i)
2088 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2089 sig->params [i] = &class->element_class->byval_arg;
2090 amethod = create_array_method (class, "Set", sig);
2091 methods [method_num++] = amethod;
2093 for (i = 0; i < class->interface_count; i++)
2094 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2096 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2097 for (i = 0; i < class->method.count; ++i) {
2098 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2099 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2103 if (MONO_CLASS_IS_INTERFACE (class)) {
2105 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2106 for (i = 0; i < class->method.count; ++i) {
2107 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2108 methods [i]->slot = slot++;
2112 /* Needed because of the double-checking locking pattern */
2113 mono_memory_barrier ();
2115 class->methods = methods;
2117 if (mono_debugger_class_loaded_methods_func)
2118 mono_debugger_class_loaded_methods_func (class);
2120 mono_loader_unlock ();
2124 * mono_class_get_method_by_index:
2126 * Returns class->methods [index], initializing class->methods if neccesary.
2128 * LOCKING: Acquires the loader lock.
2131 mono_class_get_method_by_index (MonoClass *class, int index)
2133 /* Avoid calling setup_methods () if possible */
2134 if (class->generic_class && !class->methods) {
2135 MonoClass *gklass = class->generic_class->container_class;
2138 m = mono_class_inflate_generic_method_full (
2139 gklass->methods [index], class, mono_class_get_context (class));
2141 * If setup_methods () is called later for this class, no duplicates are created,
2142 * since inflate_generic_method guarantees that only one instance of a method
2143 * is created for each context.
2146 mono_class_setup_methods (class);
2147 g_assert (m == class->methods [index]);
2151 mono_class_setup_methods (class);
2152 if (class->exception_type) /*FIXME do proper error handling*/
2154 g_assert (index >= 0 && index < class->method.count);
2155 return class->methods [index];
2160 * mono_class_get_inflated_method:
2162 * Given an inflated class CLASS and a method METHOD which should be a method of
2163 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2166 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2168 MonoClass *gklass = class->generic_class->container_class;
2171 g_assert (method->klass == gklass);
2173 mono_class_setup_methods (gklass);
2174 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2176 for (i = 0; i < gklass->method.count; ++i) {
2177 if (gklass->methods [i] == method) {
2179 return class->methods [i];
2181 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2189 * mono_class_get_vtable_entry:
2191 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2192 * LOCKING: Acquires the loader lock.
2195 mono_class_get_vtable_entry (MonoClass *class, int offset)
2199 if (class->rank == 1) {
2201 * szarrays do not overwrite any methods of Array, so we can avoid
2202 * initializing their vtables in some cases.
2204 mono_class_setup_vtable (class->parent);
2205 if (offset < class->parent->vtable_size)
2206 return class->parent->vtable [offset];
2209 if (class->generic_class) {
2210 MonoClass *gklass = class->generic_class->container_class;
2211 mono_class_setup_vtable (gklass);
2212 m = gklass->vtable [offset];
2214 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2216 mono_class_setup_vtable (class);
2217 if (class->exception_type)
2219 m = class->vtable [offset];
2226 * mono_class_get_vtable_size:
2228 * Return the vtable size for KLASS.
2231 mono_class_get_vtable_size (MonoClass *klass)
2233 mono_class_setup_vtable (klass);
2235 return klass->vtable_size;
2238 /*This method can fail the class.*/
2240 mono_class_setup_properties (MonoClass *class)
2242 guint startm, endm, i, j;
2243 guint32 cols [MONO_PROPERTY_SIZE];
2244 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2245 MonoProperty *properties;
2248 if (class->ext && class->ext->properties)
2251 mono_loader_lock ();
2253 if (class->ext && class->ext->properties) {
2254 mono_loader_unlock ();
2258 mono_class_alloc_ext (class);
2260 if (class->generic_class) {
2261 MonoClass *gklass = class->generic_class->container_class;
2263 mono_class_init (gklass);
2264 mono_class_setup_properties (gklass);
2265 if (gklass->exception_type) {
2266 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2267 mono_loader_unlock ();
2271 class->ext->property = gklass->ext->property;
2273 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2275 for (i = 0; i < class->ext->property.count; i++) {
2276 MonoProperty *prop = &properties [i];
2278 *prop = gklass->ext->properties [i];
2281 prop->get = mono_class_inflate_generic_method_full (
2282 prop->get, class, mono_class_get_context (class));
2284 prop->set = mono_class_inflate_generic_method_full (
2285 prop->set, class, mono_class_get_context (class));
2287 prop->parent = class;
2290 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2291 int count = last - first;
2294 mono_class_setup_methods (class);
2295 if (class->exception_type) {
2296 mono_loader_unlock ();
2301 class->ext->property.first = first;
2302 class->ext->property.count = count;
2303 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2304 for (i = first; i < last; ++i) {
2305 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2306 properties [i - first].parent = class;
2307 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2308 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2310 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2311 for (j = startm; j < endm; ++j) {
2314 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2316 if (class->image->uncompressed_metadata)
2317 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2318 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2320 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2322 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2323 case METHOD_SEMANTIC_SETTER:
2324 properties [i - first].set = method;
2326 case METHOD_SEMANTIC_GETTER:
2327 properties [i - first].get = method;
2335 /*Flush any pending writes as we do double checked locking on class->properties */
2336 mono_memory_barrier ();
2338 /* Leave this assignment as the last op in the function */
2339 class->ext->properties = properties;
2341 mono_loader_unlock ();
2345 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2347 MonoMethod **om, **retval;
2350 for (om = methods, count = 0; *om; ++om, ++count)
2353 retval = g_new0 (MonoMethod*, count + 1);
2355 for (om = methods, count = 0; *om; ++om, ++count)
2356 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2361 /*This method can fail the class.*/
2363 mono_class_setup_events (MonoClass *class)
2366 guint startm, endm, i, j;
2367 guint32 cols [MONO_EVENT_SIZE];
2368 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2372 if (class->ext && class->ext->events)
2375 mono_loader_lock ();
2377 if (class->ext && class->ext->events) {
2378 mono_loader_unlock ();
2382 mono_class_alloc_ext (class);
2384 if (class->generic_class) {
2385 MonoClass *gklass = class->generic_class->container_class;
2386 MonoGenericContext *context;
2388 mono_class_setup_events (gklass);
2389 if (gklass->exception_type) {
2390 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2391 mono_loader_unlock ();
2395 class->ext->event = gklass->ext->event;
2396 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2398 if (class->ext->event.count)
2399 context = mono_class_get_context (class);
2401 for (i = 0; i < class->ext->event.count; i++) {
2402 MonoEvent *event = &class->ext->events [i];
2403 MonoEvent *gevent = &gklass->ext->events [i];
2405 event->parent = class;
2406 event->name = gevent->name;
2407 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2408 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2409 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2410 #ifndef MONO_SMALL_CONFIG
2411 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2413 event->attrs = gevent->attrs;
2416 mono_loader_unlock ();
2420 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2421 count = last - first;
2424 mono_class_setup_methods (class);
2425 if (class->exception_type) {
2426 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2427 mono_loader_unlock ();
2431 class->ext->event.first = first;
2432 class->ext->event.count = count;
2433 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2434 for (i = first; i < last; ++i) {
2435 MonoEvent *event = &events [i - first];
2437 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2438 event->parent = class;
2439 event->attrs = cols [MONO_EVENT_FLAGS];
2440 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2442 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2443 for (j = startm; j < endm; ++j) {
2446 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2448 if (class->image->uncompressed_metadata)
2449 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2450 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2452 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2454 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2455 case METHOD_SEMANTIC_ADD_ON:
2456 event->add = method;
2458 case METHOD_SEMANTIC_REMOVE_ON:
2459 event->remove = method;
2461 case METHOD_SEMANTIC_FIRE:
2462 event->raise = method;
2464 case METHOD_SEMANTIC_OTHER: {
2465 #ifndef MONO_SMALL_CONFIG
2468 if (event->other == NULL) {
2469 event->other = g_new0 (MonoMethod*, 2);
2471 while (event->other [n])
2473 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2475 event->other [n] = method;
2476 /* NULL terminated */
2477 event->other [n + 1] = NULL;
2486 /*Flush any pending writes as we do double checked locking on class->properties */
2487 mono_memory_barrier ();
2489 /* Leave this assignment as the last op in the function */
2490 class->ext->events = events;
2492 mono_loader_unlock ();
2496 * Global pool of interface IDs, represented as a bitset.
2497 * LOCKING: this is supposed to be accessed with the loader lock held.
2499 static MonoBitSet *global_interface_bitset = NULL;
2502 * mono_unload_interface_ids:
2503 * @bitset: bit set of interface IDs
2505 * When an image is unloaded, the interface IDs associated with
2506 * the image are put back in the global pool of IDs so the numbers
2510 mono_unload_interface_ids (MonoBitSet *bitset)
2512 mono_loader_lock ();
2513 mono_bitset_sub (global_interface_bitset, bitset);
2514 mono_loader_unlock ();
2518 mono_unload_interface_id (MonoClass *class)
2520 if (global_interface_bitset && class->interface_id) {
2521 mono_loader_lock ();
2522 mono_bitset_clear (global_interface_bitset, class->interface_id);
2523 mono_loader_unlock ();
2528 * mono_get_unique_iid:
2531 * Assign a unique integer ID to the interface represented by @class.
2532 * The ID will positive and as small as possible.
2533 * LOCKING: this is supposed to be called with the loader lock held.
2534 * Returns: the new ID.
2537 mono_get_unique_iid (MonoClass *class)
2541 g_assert (MONO_CLASS_IS_INTERFACE (class));
2543 if (!global_interface_bitset) {
2544 global_interface_bitset = mono_bitset_new (128, 0);
2547 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2549 int old_size = mono_bitset_size (global_interface_bitset);
2550 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2551 mono_bitset_free (global_interface_bitset);
2552 global_interface_bitset = new_set;
2555 mono_bitset_set (global_interface_bitset, iid);
2556 /* set the bit also in the per-image set */
2557 if (!class->generic_class) {
2558 if (class->image->interface_bitset) {
2559 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2560 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2561 mono_bitset_free (class->image->interface_bitset);
2562 class->image->interface_bitset = new_set;
2565 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2567 mono_bitset_set (class->image->interface_bitset, iid);
2570 #ifndef MONO_SMALL_CONFIG
2571 if (mono_print_vtable) {
2573 char *type_name = mono_type_full_name (&class->byval_arg);
2574 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2575 generic_id = class->generic_class->context.class_inst->id;
2576 g_assert (generic_id != 0);
2580 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2585 g_assert (iid <= 65535);
2590 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2595 mono_class_setup_interfaces (klass, error);
2596 if (!mono_error_ok (error))
2599 for (i = 0; i < klass->interface_count; i++) {
2600 ic = klass->interfaces [i];
2603 *res = g_ptr_array_new ();
2604 g_ptr_array_add (*res, ic);
2605 mono_class_init (ic);
2606 if (ic->exception_type) {
2607 mono_error_set_type_load_class (error, ic, "Error Loading class");
2611 collect_implemented_interfaces_aux (ic, res, error);
2612 if (!mono_error_ok (error))
2618 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2620 GPtrArray *res = NULL;
2622 collect_implemented_interfaces_aux (klass, &res, error);
2623 if (!mono_error_ok (error)) {
2625 g_ptr_array_free (res, TRUE);
2632 compare_interface_ids (const void *p_key, const void *p_element) {
2633 const MonoClass *key = p_key;
2634 const MonoClass *element = *(MonoClass**) p_element;
2636 return (key->interface_id - element->interface_id);
2639 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2641 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2642 MonoClass **result = bsearch (
2644 klass->interfaces_packed,
2645 klass->interface_offsets_count,
2646 sizeof (MonoClass *),
2647 compare_interface_ids);
2649 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2656 * mono_class_interface_offset_with_variance:
2658 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2659 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2661 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2663 * FIXME figure out MS disambiguation rules and fix this function.
2666 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2667 int i = mono_class_interface_offset (klass, itf);
2668 *non_exact_match = FALSE;
2672 if (!mono_class_has_variant_generic_params (itf))
2675 for (i = 0; i < klass->interface_offsets_count; i++) {
2676 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2677 *non_exact_match = TRUE;
2678 return klass->interface_offsets_packed [i];
2686 print_implemented_interfaces (MonoClass *klass) {
2689 GPtrArray *ifaces = NULL;
2691 int ancestor_level = 0;
2693 name = mono_type_get_full_name (klass);
2694 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2697 for (i = 0; i < klass->interface_offsets_count; i++)
2698 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2699 klass->interfaces_packed [i]->interface_id,
2700 klass->interface_offsets_packed [i],
2701 klass->interfaces_packed [i]->method.count,
2702 klass->interfaces_packed [i]->name_space,
2703 klass->interfaces_packed [i]->name );
2704 printf ("Interface flags: ");
2705 for (i = 0; i <= klass->max_interface_id; i++)
2706 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2707 printf ("(%d,T)", i);
2709 printf ("(%d,F)", i);
2711 printf ("Dump interface flags:");
2712 #ifdef COMPRESSED_INTERFACE_BITMAP
2714 const uint8_t* p = klass->interface_bitmap;
2715 i = klass->max_interface_id;
2717 printf (" %d x 00 %02X", p [0], p [1]);
2723 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2724 printf (" %02X", klass->interface_bitmap [i]);
2727 while (klass != NULL) {
2728 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2729 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2730 if (!mono_error_ok (&error)) {
2731 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2732 mono_error_cleanup (&error);
2733 } else if (ifaces) {
2734 for (i = 0; i < ifaces->len; i++) {
2735 MonoClass *ic = g_ptr_array_index (ifaces, i);
2736 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2737 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2739 mono_class_interface_offset (klass, ic),
2744 g_ptr_array_free (ifaces, TRUE);
2747 klass = klass->parent;
2752 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2755 args [0] = &arg0->byval_arg;
2757 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2761 array_class_get_if_rank (MonoClass *class, guint rank)
2763 return rank ? mono_array_class_get (class, rank) : class;
2767 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2769 valuetype_types [0] = eclass;
2770 if (eclass == mono_defaults.int16_class)
2771 valuetype_types [1] = mono_defaults.uint16_class;
2772 else if (eclass == mono_defaults.uint16_class)
2773 valuetype_types [1] = mono_defaults.int16_class;
2774 else if (eclass == mono_defaults.int32_class)
2775 valuetype_types [1] = mono_defaults.uint32_class;
2776 else if (eclass == mono_defaults.uint32_class)
2777 valuetype_types [1] = mono_defaults.int32_class;
2778 else if (eclass == mono_defaults.int64_class)
2779 valuetype_types [1] = mono_defaults.uint64_class;
2780 else if (eclass == mono_defaults.uint64_class)
2781 valuetype_types [1] = mono_defaults.int64_class;
2782 else if (eclass == mono_defaults.byte_class)
2783 valuetype_types [1] = mono_defaults.sbyte_class;
2784 else if (eclass == mono_defaults.sbyte_class)
2785 valuetype_types [1] = mono_defaults.byte_class;
2786 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2787 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2790 /* this won't be needed once bug #325495 is completely fixed
2791 * though we'll need something similar to know which interfaces to allow
2792 * in arrays when they'll be lazyly created
2794 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2795 * MS returns diferrent types based on which instance is called. For example:
2796 * object obj = new byte[10][];
2797 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2798 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2801 * Fixing this should kill quite some code, save some bits and improve compatibility.
2804 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2806 MonoClass *eclass = class->element_class;
2807 static MonoClass* generic_icollection_class = NULL;
2808 static MonoClass* generic_ienumerable_class = NULL;
2809 static MonoClass* generic_ienumerator_class = NULL;
2810 MonoClass *valuetype_types[2] = { NULL, NULL };
2811 MonoClass **interfaces = NULL;
2812 int i, interface_count, real_count, original_rank;
2814 gboolean internal_enumerator;
2815 gboolean eclass_is_valuetype;
2817 if (!mono_defaults.generic_ilist_class) {
2821 internal_enumerator = FALSE;
2822 eclass_is_valuetype = FALSE;
2823 original_rank = eclass->rank;
2824 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2825 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2827 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2829 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2830 original_rank = eclass->rank;
2832 eclass = eclass->element_class;
2833 internal_enumerator = TRUE;
2834 *is_enumerator = TRUE;
2842 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2843 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2845 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2847 if (!generic_icollection_class) {
2848 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2849 "System.Collections.Generic", "ICollection`1");
2850 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2851 "System.Collections.Generic", "IEnumerable`1");
2852 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2853 "System.Collections.Generic", "IEnumerator`1");
2856 mono_class_init (eclass);
2859 * Arrays in 2.0 need to implement a number of generic interfaces
2860 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2861 * on the element class). We collect the types needed to build the
2862 * instantiations in interfaces at intervals of 3, because 3 are
2863 * the generic interfaces needed to implement.
2865 if (eclass->valuetype) {
2866 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2868 /* IList, ICollection, IEnumerable */
2869 real_count = interface_count = valuetype_types [1] ? 6 : 3;
2870 if (internal_enumerator) {
2872 if (valuetype_types [1])
2876 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2877 interfaces [0] = valuetype_types [0];
2878 if (valuetype_types [1])
2879 interfaces [3] = valuetype_types [1];
2881 eclass_is_valuetype = TRUE;
2884 int idepth = eclass->idepth;
2885 if (!internal_enumerator)
2888 // FIXME: This doesn't seem to work/required for generic params
2889 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2890 mono_class_setup_interface_offsets (eclass);
2892 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2893 /* we add object for interfaces and the supertypes for the other
2894 * types. The last of the supertypes is the element class itself which we
2895 * already created the explicit interfaces for (so we include it for IEnumerator
2896 * and exclude it for arrays).
2898 if (MONO_CLASS_IS_INTERFACE (eclass))
2901 interface_count += idepth;
2902 if (eclass->rank && eclass->element_class->valuetype) {
2903 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2904 if (valuetype_types [1])
2907 /* IList, ICollection, IEnumerable */
2908 interface_count *= 3;
2909 real_count = interface_count;
2910 if (internal_enumerator) {
2911 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2912 if (valuetype_types [1])
2915 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2916 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2917 interfaces [0] = mono_defaults.object_class;
2921 for (i = 0; i < idepth; i++) {
2922 mono_class_init (eclass->supertypes [i]);
2923 interfaces [j] = eclass->supertypes [i];
2927 if (all_interfaces) {
2928 for (i = 0; i < eclass->interface_offsets_count; i++) {
2929 interfaces [j] = eclass->interfaces_packed [i];
2933 for (i = 0; i < eclass->interface_count; i++) {
2934 interfaces [j] = eclass->interfaces [i];
2938 if (valuetype_types [1]) {
2939 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
2944 /* instantiate the generic interfaces */
2945 for (i = 0; i < interface_count; i += 3) {
2946 MonoClass *iface = interfaces [i];
2948 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
2949 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
2950 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
2952 if (internal_enumerator) {
2954 /* instantiate IEnumerator<iface> */
2955 for (i = 0; i < interface_count; i++) {
2956 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
2958 j = interface_count;
2959 if (!eclass_is_valuetype) {
2960 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2961 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
2964 for (i = 0; i < eclass->idepth; i++) {
2965 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
2969 for (i = 0; i < eclass->interface_offsets_count; i++) {
2970 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
2974 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
2976 if (valuetype_types [1])
2977 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
2981 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
2982 for (i = 0; i < real_count; ++i) {
2983 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
2984 g_print ("%s implements %s\n", type_name, name);
2995 find_array_interface (MonoClass *klass, const char *name)
2998 for (i = 0; i < klass->interface_count; ++i) {
2999 if (strcmp (klass->interfaces [i]->name, name) == 0)
3006 * Return the number of virtual methods.
3007 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3008 * Return -1 on failure.
3009 * FIXME It would be nice if this information could be cached somewhere.
3012 count_virtual_methods (MonoClass *class)
3016 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3018 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3019 mono_class_setup_methods (class);
3020 if (class->exception_type)
3023 for (i = 0; i < class->method.count; ++i) {
3024 flags = class->methods [i]->flags;
3025 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3029 for (i = 0; i < class->method.count; ++i) {
3030 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3032 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3040 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3048 m = (l + num_ifaces) / 2;
3049 if (interfaces_full [m] == ic)
3051 if (l == num_ifaces)
3053 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3062 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3064 int i = find_interface (num_ifaces, interfaces_full, ic);
3066 return interface_offsets_full [i];
3071 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3073 int i = find_interface (num_ifaces, interfaces_full, ic);
3077 interface_offsets_full [i] = offset;
3080 for (i = 0; i < num_ifaces; ++i) {
3081 if (interfaces_full [i]) {
3083 if (interfaces_full [i]->interface_id < ic->interface_id)
3086 while (end < num_ifaces && interfaces_full [end]) end++;
3087 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3088 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3090 interfaces_full [i] = ic;
3091 interface_offsets_full [i] = offset;
3097 #ifdef COMPRESSED_INTERFACE_BITMAP
3100 * Compressed interface bitmap design.
3102 * Interface bitmaps take a large amount of memory, because their size is
3103 * linear with the maximum interface id assigned in the process (each interface
3104 * is assigned a unique id as it is loaded). The number of interface classes
3105 * is high because of the many implicit interfaces implemented by arrays (we'll
3106 * need to lazy-load them in the future).
3107 * Most classes implement a very small number of interfaces, so the bitmap is
3108 * sparse. This bitmap needs to be checked by interface casts, so access to the
3109 * needed bit must be fast and doable with few jit instructions.
3111 * The current compression format is as follows:
3112 * *) it is a sequence of one or more two-byte elements
3113 * *) the first byte in the element is the count of empty bitmap bytes
3114 * at the current bitmap position
3115 * *) the second byte in the element is an actual bitmap byte at the current
3118 * As an example, the following compressed bitmap bytes:
3119 * 0x07 0x01 0x00 0x7
3120 * correspond to the following bitmap:
3121 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3123 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3124 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3125 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3129 * mono_compress_bitmap:
3130 * @dest: destination buffer
3131 * @bitmap: bitmap buffer
3132 * @size: size of @bitmap in bytes
3134 * This is a mono internal function.
3135 * The @bitmap data is compressed into a format that is small but
3136 * still searchable in few instructions by the JIT and runtime.
3137 * The compressed data is stored in the buffer pointed to by the
3138 * @dest array. Passing a #NULL value for @dest allows to just compute
3139 * the size of the buffer.
3140 * This compression algorithm assumes the bits set in the bitmap are
3141 * few and far between, like in interface bitmaps.
3142 * Returns: the size of the compressed bitmap in bytes.
3145 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3149 const uint8_t *end = bitmap + size;
3150 while (bitmap < end) {
3151 if (*bitmap || numz == 255) {
3175 * mono_class_interface_match:
3176 * @bitmap: a compressed bitmap buffer
3177 * @id: the index to check in the bitmap
3179 * This is a mono internal function.
3180 * Checks if a bit is set in a compressed interface bitmap. @id must
3181 * be already checked for being smaller than the maximum id encoded in the
3184 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3188 mono_class_interface_match (const uint8_t *bitmap, int id)
3191 id -= bitmap [0] * 8;
3195 return bitmap [1] & (1 << id);
3204 * LOCKING: this is supposed to be called with the loader lock held.
3205 * Return -1 on failure and set exception_type
3208 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3212 int i, j, max_iid, num_ifaces;
3213 MonoClass **interfaces_full = NULL;
3214 int *interface_offsets_full = NULL;
3216 GPtrArray **ifaces_array = NULL;
3217 int interface_offsets_count;
3218 MonoClass **array_interfaces = NULL;
3219 int num_array_interfaces;
3220 int is_enumerator = FALSE;
3222 mono_class_setup_supertypes (class);
3224 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3225 * implicit interfaces have the property that they are assigned the same slot in the
3226 * vtables for compatible interfaces
3228 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3230 /* compute maximum number of slots and maximum interface id */
3232 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3233 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3234 for (j = 0; j < class->idepth; j++) {
3235 k = class->supertypes [j];
3236 num_ifaces += k->interface_count;
3237 for (i = 0; i < k->interface_count; i++) {
3238 ic = k->interfaces [i];
3241 mono_class_init (ic);
3243 if (max_iid < ic->interface_id)
3244 max_iid = ic->interface_id;
3246 ifaces = mono_class_get_implemented_interfaces (k, &error);
3247 if (!mono_error_ok (&error)) {
3248 char *name = mono_type_get_full_name (k);
3249 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)));
3251 mono_error_cleanup (&error);
3256 num_ifaces += ifaces->len;
3257 for (i = 0; i < ifaces->len; ++i) {
3258 ic = g_ptr_array_index (ifaces, i);
3259 if (max_iid < ic->interface_id)
3260 max_iid = ic->interface_id;
3262 ifaces_array [j] = ifaces;
3266 for (i = 0; i < num_array_interfaces; ++i) {
3267 ic = array_interfaces [i];
3268 mono_class_init (ic);
3269 if (max_iid < ic->interface_id)
3270 max_iid = ic->interface_id;
3273 if (MONO_CLASS_IS_INTERFACE (class)) {
3275 if (max_iid < class->interface_id)
3276 max_iid = class->interface_id;
3278 class->max_interface_id = max_iid;
3279 /* compute vtable offset for interfaces */
3280 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3281 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3283 for (i = 0; i < num_ifaces; i++) {
3284 interface_offsets_full [i] = -1;
3287 /* skip the current class */
3288 for (j = 0; j < class->idepth - 1; j++) {
3289 k = class->supertypes [j];
3290 ifaces = ifaces_array [j];
3293 for (i = 0; i < ifaces->len; ++i) {
3295 ic = g_ptr_array_index (ifaces, i);
3297 /*Force the sharing of interface offsets between parent and subtypes.*/
3298 io = mono_class_interface_offset (k, ic);
3300 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3305 g_assert (class == class->supertypes [class->idepth - 1]);
3306 ifaces = ifaces_array [class->idepth - 1];
3308 for (i = 0; i < ifaces->len; ++i) {
3310 ic = g_ptr_array_index (ifaces, i);
3311 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3313 count = count_virtual_methods (ic);
3315 char *name = mono_type_get_full_name (ic);
3316 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3325 if (MONO_CLASS_IS_INTERFACE (class))
3326 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3328 if (num_array_interfaces) {
3329 if (is_enumerator) {
3330 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3331 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3332 g_assert (ienumerator_offset >= 0);
3333 for (i = 0; i < num_array_interfaces; ++i) {
3334 ic = array_interfaces [i];
3335 if (strcmp (ic->name, "IEnumerator`1") == 0)
3336 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3338 g_assert_not_reached ();
3339 /*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);*/
3342 int ilist_offset, icollection_offset, ienumerable_offset;
3343 int ilist_iface_idx = find_array_interface (class, "IList`1");
3344 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3345 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3346 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3347 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3348 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3349 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3350 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3351 for (i = 0; i < num_array_interfaces; ++i) {
3353 ic = array_interfaces [i];
3354 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3355 offset = ilist_offset;
3356 else if (strcmp (ic->name, "ICollection`1") == 0)
3357 offset = icollection_offset;
3358 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3359 offset = ienumerable_offset;
3361 g_assert_not_reached ();
3362 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3363 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3368 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3369 if (interface_offsets_full [i] != -1) {
3370 interface_offsets_count ++;
3375 * We might get called multiple times:
3376 * - mono_class_init ()
3377 * - mono_class_setup_vtable ().
3378 * - mono_class_setup_interface_offsets ().
3379 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3380 * means we have to overwrite those when called from other places (#4440).
3382 if (class->interfaces_packed && !overwrite) {
3383 g_assert (class->interface_offsets_count == interface_offsets_count);
3387 class->interface_offsets_count = interface_offsets_count;
3388 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3389 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3390 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3391 #ifdef COMPRESSED_INTERFACE_BITMAP
3392 bitmap = g_malloc0 (bsize);
3394 bitmap = mono_class_alloc0 (class, bsize);
3396 for (i = 0; i < interface_offsets_count; i++) {
3397 int id = interfaces_full [i]->interface_id;
3398 bitmap [id >> 3] |= (1 << (id & 7));
3399 class->interfaces_packed [i] = interfaces_full [i];
3400 class->interface_offsets_packed [i] = interface_offsets_full [i];
3401 /*if (num_array_interfaces)
3402 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]);*/
3404 #ifdef COMPRESSED_INTERFACE_BITMAP
3405 i = mono_compress_bitmap (NULL, bitmap, bsize);
3406 class->interface_bitmap = mono_class_alloc0 (class, i);
3407 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3410 class->interface_bitmap = bitmap;
3415 g_free (interfaces_full);
3416 g_free (interface_offsets_full);
3417 g_free (array_interfaces);
3418 for (i = 0; i < class->idepth; i++) {
3419 ifaces = ifaces_array [i];
3421 g_ptr_array_free (ifaces, TRUE);
3423 g_free (ifaces_array);
3425 //printf ("JUST DONE: ");
3426 //print_implemented_interfaces (class);
3432 * Setup interface offsets for interfaces.
3434 * - class->max_interface_id
3435 * - class->interface_offsets_count
3436 * - class->interfaces_packed
3437 * - class->interface_offsets_packed
3438 * - class->interface_bitmap
3440 * This function can fail @class.
3443 mono_class_setup_interface_offsets (MonoClass *class)
3445 mono_loader_lock ();
3447 setup_interface_offsets (class, 0, FALSE);
3449 mono_loader_unlock ();
3452 /*Checks if @klass has @parent as one of it's parents type gtd
3456 * Bar<T> : Foo<Bar<Bar<T>>>
3460 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3462 klass = mono_class_get_generic_type_definition (klass);
3463 parent = mono_class_get_generic_type_definition (parent);
3464 mono_class_setup_supertypes (klass);
3465 mono_class_setup_supertypes (parent);
3467 return klass->idepth >= parent->idepth &&
3468 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3472 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3474 MonoGenericInst *ginst;
3476 if (!class->generic_class) {
3477 mono_class_setup_vtable_full (class, in_setup);
3478 return class->exception_type == 0;
3481 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3482 if (class->generic_class->container_class->exception_type) {
3483 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3487 ginst = class->generic_class->context.class_inst;
3488 for (i = 0; i < ginst->type_argc; ++i) {
3490 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3492 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3493 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3494 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3496 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3497 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3505 * mono_class_setup_vtable:
3507 * Creates the generic vtable of CLASS.
3508 * Initializes the following fields in MonoClass:
3511 * Plus all the fields initialized by setup_interface_offsets ().
3512 * If there is an error during vtable construction, class->exception_type is set.
3514 * LOCKING: Acquires the loader lock.
3517 mono_class_setup_vtable (MonoClass *class)
3519 mono_class_setup_vtable_full (class, NULL);
3523 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3525 MonoMethod **overrides;
3526 MonoGenericContext *context;
3534 if (mono_debug_using_mono_debugger ())
3535 /* The debugger currently depends on this */
3536 mono_class_setup_methods (class);
3538 if (MONO_CLASS_IS_INTERFACE (class)) {
3539 /* This sets method->slot for all methods if this is an interface */
3540 mono_class_setup_methods (class);
3544 if (class->exception_type)
3547 if (g_list_find (in_setup, class))
3550 mono_loader_lock ();
3552 if (class->vtable) {
3553 mono_loader_unlock ();
3557 mono_stats.generic_vtable_count ++;
3558 in_setup = g_list_prepend (in_setup, class);
3560 if (class->generic_class) {
3561 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3562 mono_loader_unlock ();
3563 g_list_remove (in_setup, class);
3567 context = mono_class_get_context (class);
3568 type_token = class->generic_class->container_class->type_token;
3570 context = (MonoGenericContext *) class->generic_container;
3571 type_token = class->type_token;
3574 if (class->image->dynamic) {
3575 /* Generic instances can have zero method overrides without causing any harm.
3576 * This is true since we don't do layout all over again for them, we simply inflate
3577 * the layout of the parent.
3579 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3581 /* The following call fails if there are missing methods in the type */
3582 /* FIXME it's probably a good idea to avoid this for generic instances. */
3583 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3587 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3589 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3593 mono_loader_unlock ();
3594 g_list_remove (in_setup, class);
3599 #define DEBUG_INTERFACE_VTABLE_CODE 0
3600 #define TRACE_INTERFACE_VTABLE_CODE 0
3601 #define VERIFY_INTERFACE_VTABLE_CODE 0
3602 #define VTABLE_SELECTOR (1)
3604 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3605 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3606 if (!(VTABLE_SELECTOR)) break; \
3610 #define DEBUG_INTERFACE_VTABLE(stmt)
3613 #if TRACE_INTERFACE_VTABLE_CODE
3614 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3615 if (!(VTABLE_SELECTOR)) break; \
3619 #define TRACE_INTERFACE_VTABLE(stmt)
3622 #if VERIFY_INTERFACE_VTABLE_CODE
3623 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3624 if (!(VTABLE_SELECTOR)) break; \
3628 #define VERIFY_INTERFACE_VTABLE(stmt)
3632 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3634 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3638 GString *res = g_string_new ("");
3640 g_string_append_c (res, '(');
3641 for (i = 0; i < sig->param_count; ++i) {
3643 g_string_append_c (res, ',');
3644 mono_type_get_desc (res, sig->params [i], include_namespace);
3646 g_string_append (res, ")=>");
3647 if (sig->ret != NULL) {
3648 mono_type_get_desc (res, sig->ret, include_namespace);
3650 g_string_append (res, "NULL");
3653 g_string_free (res, FALSE);
3657 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3658 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3659 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3660 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3668 is_wcf_hack_disabled (void)
3670 static gboolean disabled;
3671 static gboolean inited = FALSE;
3673 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3680 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) {
3681 MonoMethodSignature *cmsig, *imsig;
3682 if (strcmp (im->name, cm->name) == 0) {
3683 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3684 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3687 if (! slot_is_empty) {
3688 if (require_newslot) {
3689 if (! interface_is_explicitly_implemented_by_class) {
3690 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3693 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3694 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3698 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3701 cmsig = mono_method_signature (cm);
3702 imsig = mono_method_signature (im);
3703 if (!cmsig || !imsig) {
3704 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3708 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3709 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3710 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3711 TRACE_INTERFACE_VTABLE (printf ("]"));
3714 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3715 /* CAS - SecurityAction.InheritanceDemand on interface */
3716 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3717 mono_secman_inheritancedemand_method (cm, im);
3720 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3721 mono_security_core_clr_check_override (class, cm, im);
3722 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3723 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3724 char *body_name = mono_method_full_name (cm, TRUE);
3725 char *decl_name = mono_method_full_name (im, TRUE);
3726 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));
3734 MonoClass *ic = im->klass;
3735 const char *ic_name_space = ic->name_space;
3736 const char *ic_name = ic->name;
3739 if (! require_newslot) {
3740 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3743 if (cm->klass->rank == 0) {
3744 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3747 cmsig = mono_method_signature (cm);
3748 imsig = mono_method_signature (im);
3749 if (!cmsig || !imsig) {
3750 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3754 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3755 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3756 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3757 TRACE_INTERFACE_VTABLE (printf ("]"));
3760 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3761 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3764 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3765 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3768 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0))) {
3769 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3773 subname = strstr (cm->name, ic_name_space);
3774 if (subname != cm->name) {
3775 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3778 subname += strlen (ic_name_space);
3779 if (subname [0] != '.') {
3780 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3784 if (strstr (subname, ic_name) != subname) {
3785 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3788 subname += strlen (ic_name);
3789 if (subname [0] != '.') {
3790 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3794 if (strcmp (subname, im->name) != 0) {
3795 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3799 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3800 /* CAS - SecurityAction.InheritanceDemand on interface */
3801 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3802 mono_secman_inheritancedemand_method (cm, im);
3805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3806 mono_security_core_clr_check_override (class, cm, im);
3808 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3809 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3810 char *body_name = mono_method_full_name (cm, TRUE);
3811 char *decl_name = mono_method_full_name (im, TRUE);
3812 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));
3822 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3824 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3825 MonoMethod *method = key;
3826 MonoMethod *override = value;
3827 MonoClass *method_class = mono_method_get_class (method);
3828 MonoClass *override_class = mono_method_get_class (override);
3830 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3831 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3832 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3835 print_overrides (GHashTable *override_map, const char *message) {
3837 printf ("Override map \"%s\" START:\n", message);
3838 g_hash_table_foreach (override_map, foreach_override, NULL);
3839 printf ("Override map \"%s\" END.\n", message);
3841 printf ("Override map \"%s\" EMPTY.\n", message);
3845 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3846 char *full_name = mono_type_full_name (&class->byval_arg);
3850 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3852 if (print_interfaces) {
3853 print_implemented_interfaces (class);
3854 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3857 if (class->parent) {
3858 parent_size = class->parent->vtable_size;
3862 for (i = 0; i < size; ++i) {
3863 MonoMethod *cm = vtable [i];
3864 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3865 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3867 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3875 #if VERIFY_INTERFACE_VTABLE_CODE
3877 mono_method_try_get_vtable_index (MonoMethod *method)
3879 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3880 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3881 if (imethod->declaring->is_generic)
3882 return imethod->declaring->slot;
3884 return method->slot;
3888 mono_class_verify_vtable (MonoClass *class)
3891 char *full_name = mono_type_full_name (&class->byval_arg);
3893 printf ("*** Verifying VTable of class '%s' \n", full_name);
3897 if (!class->methods)
3900 for (i = 0; i < class->method.count; ++i) {
3901 MonoMethod *cm = class->methods [i];
3904 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3908 full_name = mono_method_full_name (cm, TRUE);
3910 slot = mono_method_try_get_vtable_index (cm);
3912 if (slot >= class->vtable_size) {
3913 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3917 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3918 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3919 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3920 g_free (other_name);
3923 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
3930 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
3932 char *method_signature;
3935 for (index = 0; index < onum; ++index) {
3936 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
3937 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
3939 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
3940 type_name = mono_type_full_name (&class->byval_arg);
3941 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
3942 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
3943 g_free (method_signature);
3945 mono_class_setup_methods (class);
3946 if (class->exception_type) {
3947 char *name = mono_type_get_full_name (class);
3948 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
3952 for (index = 0; index < class->method.count; ++index) {
3953 MonoMethod *cm = class->methods [index];
3954 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
3956 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
3957 g_free (method_signature);
3962 mono_method_get_method_definition (MonoMethod *method)
3964 while (method->is_inflated)
3965 method = ((MonoMethodInflated*)method)->declaring;
3970 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
3974 for (i = 0; i < onum; ++i) {
3975 MonoMethod *decl = overrides [i * 2];
3976 MonoMethod *body = overrides [i * 2 + 1];
3978 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
3979 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
3983 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
3984 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
3987 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
3991 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
3992 if (body->flags & METHOD_ATTRIBUTE_STATIC)
3993 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
3995 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
3999 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4000 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4004 body = mono_method_get_method_definition (body);
4005 decl = mono_method_get_method_definition (decl);
4007 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4008 char *body_name = mono_method_full_name (body, TRUE);
4009 char *decl_name = mono_method_full_name (decl, TRUE);
4010 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));
4020 mono_class_need_stelemref_method (MonoClass *class)
4022 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4026 * LOCKING: this is supposed to be called with the loader lock held.
4029 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4033 MonoMethod **vtable;
4034 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4035 GPtrArray *ifaces = NULL;
4036 GHashTable *override_map = NULL;
4037 gboolean security_enabled = mono_is_security_manager_active ();
4039 gpointer class_iter;
4040 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4041 int first_non_interface_slot;
4043 GSList *virt_methods = NULL, *l;
4044 int stelemref_slot = 0;
4049 if (overrides && !verify_class_overrides (class, overrides, onum))
4052 ifaces = mono_class_get_implemented_interfaces (class, &error);
4053 if (!mono_error_ok (&error)) {
4054 char *name = mono_type_get_full_name (class);
4055 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)));
4057 mono_error_cleanup (&error);
4059 } else if (ifaces) {
4060 for (i = 0; i < ifaces->len; i++) {
4061 MonoClass *ic = g_ptr_array_index (ifaces, i);
4062 max_vtsize += ic->method.count;
4064 g_ptr_array_free (ifaces, TRUE);
4068 if (class->parent) {
4069 mono_class_init (class->parent);
4070 mono_class_setup_vtable_full (class->parent, in_setup);
4072 if (class->parent->exception_type) {
4073 char *name = mono_type_get_full_name (class->parent);
4074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4079 max_vtsize += class->parent->vtable_size;
4080 cur_slot = class->parent->vtable_size;
4083 max_vtsize += class->method.count;
4085 /*Array have a slot for stelemref*/
4086 if (mono_class_need_stelemref_method (class)) {
4087 stelemref_slot = cur_slot;
4092 vtable = alloca (sizeof (gpointer) * max_vtsize);
4093 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4095 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4097 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4098 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4101 max_iid = class->max_interface_id;
4102 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4104 /* Optimized version for generic instances */
4105 if (class->generic_class) {
4107 MonoClass *gklass = class->generic_class->container_class;
4110 mono_class_setup_vtable_full (gklass, in_setup);
4111 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4112 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4116 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4117 class->vtable_size = gklass->vtable_size;
4118 for (i = 0; i < gklass->vtable_size; ++i)
4119 if (gklass->vtable [i]) {
4120 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4121 if (!mono_error_ok (&error)) {
4122 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4123 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4125 mono_error_cleanup (&error);
4129 tmp [i]->slot = gklass->vtable [i]->slot;
4131 mono_memory_barrier ();
4132 class->vtable = tmp;
4134 /* Have to set method->slot for abstract virtual methods */
4135 if (class->methods && gklass->methods) {
4136 for (i = 0; i < class->method.count; ++i)
4137 if (class->methods [i]->slot == -1)
4138 class->methods [i]->slot = gklass->methods [i]->slot;
4144 if (class->parent && class->parent->vtable_size) {
4145 MonoClass *parent = class->parent;
4148 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4150 // Also inherit parent interface vtables, just as a starting point.
4151 // This is needed otherwise bug-77127.exe fails when the property methods
4152 // have different names in the iterface and the class, because for child
4153 // classes the ".override" information is not used anymore.
4154 for (i = 0; i < parent->interface_offsets_count; i++) {
4155 MonoClass *parent_interface = parent->interfaces_packed [i];
4156 int interface_offset = mono_class_interface_offset (class, parent_interface);
4157 /*FIXME this is now dead code as this condition will never hold true.
4158 Since interface offsets are inherited then the offset of an interface implemented
4159 by a parent will never be the out of it's vtable boundary.
4161 if (interface_offset >= parent->vtable_size) {
4162 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4165 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4166 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4167 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4168 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4169 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4170 parent_interface_offset + j, parent_interface_offset, j,
4171 interface_offset + j, interface_offset, j));
4178 /*Array have a slot for stelemref*/
4179 if (mono_class_need_stelemref_method (class)) {
4180 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4182 method->slot = stelemref_slot;
4184 g_assert (method->slot == stelemref_slot);
4186 vtable [stelemref_slot] = method;
4189 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4190 /* override interface methods */
4191 for (i = 0; i < onum; i++) {
4192 MonoMethod *decl = overrides [i*2];
4193 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4195 dslot = mono_method_get_vtable_slot (decl);
4197 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4201 dslot += mono_class_interface_offset (class, decl->klass);
4202 vtable [dslot] = overrides [i*2 + 1];
4203 vtable [dslot]->slot = dslot;
4205 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4207 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4209 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
4210 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4213 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4214 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4217 * Create a list of virtual methods to avoid calling
4218 * mono_class_get_virtual_methods () which is slow because of the metadata
4222 gpointer iter = NULL;
4225 virt_methods = NULL;
4226 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4227 virt_methods = g_slist_prepend (virt_methods, cm);
4229 if (class->exception_type)
4233 // Loop on all implemented interfaces...
4234 for (i = 0; i < class->interface_offsets_count; i++) {
4235 MonoClass *parent = class->parent;
4237 gboolean interface_is_explicitly_implemented_by_class;
4240 ic = class->interfaces_packed [i];
4241 ic_offset = mono_class_interface_offset (class, ic);
4243 mono_class_setup_methods (ic);
4244 if (ic->exception_type)
4247 // Check if this interface is explicitly implemented (instead of just inherited)
4248 if (parent != NULL) {
4249 int implemented_interfaces_index;
4250 interface_is_explicitly_implemented_by_class = FALSE;
4251 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4252 if (ic == class->interfaces [implemented_interfaces_index]) {
4253 interface_is_explicitly_implemented_by_class = TRUE;
4258 interface_is_explicitly_implemented_by_class = TRUE;
4261 // Loop on all interface methods...
4262 for (im_index = 0; im_index < ic->method.count; im_index++) {
4263 MonoMethod *im = ic->methods [im_index];
4264 int im_slot = ic_offset + im->slot;
4265 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4267 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4270 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4272 // If there is an explicit implementation, just use it right away,
4273 // otherwise look for a matching method
4274 if (override_im == NULL) {
4279 // First look for a suitable method among the class methods
4281 for (l = virt_methods; l; l = l->next) {
4283 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)));
4284 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4285 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4286 vtable [im_slot] = cm;
4287 /* Why do we need this? */
4292 TRACE_INTERFACE_VTABLE (printf ("\n"));
4293 if (class->exception_type) /*Might be set by check_interface_method_override*/
4297 // If the slot is still empty, look in all the inherited virtual methods...
4298 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4299 MonoClass *parent = class->parent;
4300 // Reverse order, so that last added methods are preferred
4301 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4302 MonoMethod *cm = parent->vtable [cm_index];
4304 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));
4305 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4306 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4307 vtable [im_slot] = cm;
4308 /* Why do we need this? */
4314 if (class->exception_type) /*Might be set by check_interface_method_override*/
4316 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4320 g_assert (vtable [im_slot] == override_im);
4325 // If the class is not abstract, check that all its interface slots are full.
4326 // The check is done here and not directly at the end of the loop above because
4327 // it can happen (for injected generic array interfaces) that the same slot is
4328 // processed multiple times (those interfaces have overlapping slots), and it
4329 // will not always be the first pass the one that fills the slot.
4330 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4331 for (i = 0; i < class->interface_offsets_count; i++) {
4335 ic = class->interfaces_packed [i];
4336 ic_offset = mono_class_interface_offset (class, ic);
4338 for (im_index = 0; im_index < ic->method.count; im_index++) {
4339 MonoMethod *im = ic->methods [im_index];
4340 int im_slot = ic_offset + im->slot;
4342 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4345 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4346 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4347 if (vtable [im_slot] == NULL) {
4348 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4355 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4357 for (l = virt_methods; l; l = l->next) {
4360 * If the method is REUSE_SLOT, we must check in the
4361 * base class for a method to override.
4363 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4365 for (k = class->parent; k ; k = k->parent) {
4370 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4371 MonoMethodSignature *cmsig, *m1sig;
4373 cmsig = mono_method_signature (cm);
4374 m1sig = mono_method_signature (m1);
4376 if (!cmsig || !m1sig) {
4377 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4381 if (!strcmp(cm->name, m1->name) &&
4382 mono_metadata_signature_equal (cmsig, m1sig)) {
4384 /* CAS - SecurityAction.InheritanceDemand */
4385 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4386 mono_secman_inheritancedemand_method (cm, m1);
4389 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
4390 mono_security_core_clr_check_override (class, cm, m1);
4392 slot = mono_method_get_vtable_slot (m1);
4396 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4397 char *body_name = mono_method_full_name (cm, TRUE);
4398 char *decl_name = mono_method_full_name (m1, TRUE);
4399 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));
4405 g_assert (cm->slot < max_vtsize);
4407 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4408 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4409 mono_method_full_name (m1, 1), m1,
4410 mono_method_full_name (cm, 1), cm));
4411 g_hash_table_insert (override_map, m1, cm);
4415 if (k->exception_type)
4425 /*Non final newslot methods must be given a non-interface vtable slot*/
4426 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4430 cm->slot = cur_slot++;
4432 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4433 vtable [cm->slot] = cm;
4436 /* override non interface methods */
4437 for (i = 0; i < onum; i++) {
4438 MonoMethod *decl = overrides [i*2];
4439 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4440 g_assert (decl->slot != -1);
4441 vtable [decl->slot] = overrides [i*2 + 1];
4442 overrides [i * 2 + 1]->slot = decl->slot;
4444 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4445 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4446 mono_method_full_name (decl, 1), decl,
4447 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4448 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4450 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
4451 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4456 * If a method occupies more than one place in the vtable, and it is
4457 * overriden, then change the other occurances too.
4462 for (i = 0; i < max_vtsize; ++i)
4464 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4466 cm = g_hash_table_lookup (override_map, vtable [i]);
4471 g_hash_table_destroy (override_map);
4472 override_map = NULL;
4475 g_slist_free (virt_methods);
4476 virt_methods = NULL;
4478 /* Ensure that all vtable slots are filled with concrete instance methods */
4479 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4480 for (i = 0; i < cur_slot; ++i) {
4481 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4482 char *type_name = mono_type_get_full_name (class);
4483 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4484 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));
4486 g_free (method_name);
4492 if (class->generic_class) {
4493 MonoClass *gklass = class->generic_class->container_class;
4495 mono_class_init (gklass);
4497 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4499 /* Check that the vtable_size value computed in mono_class_init () is correct */
4500 if (class->vtable_size)
4501 g_assert (cur_slot == class->vtable_size);
4502 class->vtable_size = cur_slot;
4505 /* Try to share the vtable with our parent. */
4506 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4507 mono_memory_barrier ();
4508 class->vtable = class->parent->vtable;
4510 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4511 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4512 mono_memory_barrier ();
4513 class->vtable = tmp;
4516 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4517 if (mono_print_vtable) {
4520 print_implemented_interfaces (class);
4522 for (i = 0; i <= max_iid; i++)
4523 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4526 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4527 class->vtable_size, icount);
4529 for (i = 0; i < cur_slot; ++i) {
4534 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4535 mono_method_full_name (cm, TRUE));
4541 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4542 class->name, max_iid);
4544 for (i = 0; i < class->interface_count; i++) {
4545 ic = class->interfaces [i];
4546 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4547 mono_class_interface_offset (class, ic),
4548 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4551 for (k = class->parent; k ; k = k->parent) {
4552 for (i = 0; i < k->interface_count; i++) {
4553 ic = k->interfaces [i];
4554 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4555 mono_class_interface_offset (class, ic),
4556 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4562 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4567 char *name = mono_type_get_full_name (class);
4568 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4571 g_hash_table_destroy (override_map);
4573 g_slist_free (virt_methods);
4578 * mono_method_get_vtable_slot:
4580 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4581 * LOCKING: Acquires the loader lock.
4583 * FIXME Use proper MonoError machinery here.
4586 mono_method_get_vtable_slot (MonoMethod *method)
4588 if (method->slot == -1) {
4589 mono_class_setup_vtable (method->klass);
4590 if (method->klass->exception_type)
4592 g_assert (method->slot != -1);
4594 return method->slot;
4598 * mono_method_get_vtable_index:
4601 * Returns the index into the runtime vtable to access the method or,
4602 * in the case of a virtual generic method, the virtual generic method
4603 * thunk. Returns -1 on failure.
4605 * FIXME Use proper MonoError machinery here.
4608 mono_method_get_vtable_index (MonoMethod *method)
4610 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4611 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4612 if (imethod->declaring->is_generic)
4613 return mono_method_get_vtable_slot (imethod->declaring);
4615 return mono_method_get_vtable_slot (method);
4618 static MonoMethod *default_ghc = NULL;
4619 static MonoMethod *default_finalize = NULL;
4620 static int finalize_slot = -1;
4621 static int ghc_slot = -1;
4624 initialize_object_slots (MonoClass *class)
4629 if (class == mono_defaults.object_class) {
4630 mono_class_setup_vtable (class);
4631 for (i = 0; i < class->vtable_size; ++i) {
4632 MonoMethod *cm = class->vtable [i];
4634 if (!strcmp (cm->name, "GetHashCode"))
4636 else if (!strcmp (cm->name, "Finalize"))
4640 g_assert (ghc_slot > 0);
4641 default_ghc = class->vtable [ghc_slot];
4643 g_assert (finalize_slot > 0);
4644 default_finalize = class->vtable [finalize_slot];
4649 MonoMethod *array_method;
4651 } GenericArrayMethodInfo;
4653 static int generic_array_method_num = 0;
4654 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4657 generic_array_methods (MonoClass *class)
4659 int i, count_generic = 0;
4660 GList *list = NULL, *tmp;
4661 if (generic_array_method_num)
4662 return generic_array_method_num;
4663 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4664 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4665 for (i = 0; i < class->parent->method.count; i++) {
4666 MonoMethod *m = class->parent->methods [i];
4667 if (!strncmp (m->name, "InternalArray__", 15)) {
4669 list = g_list_prepend (list, m);
4672 list = g_list_reverse (list);
4673 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4675 for (tmp = list; tmp; tmp = tmp->next) {
4676 const char *mname, *iname;
4678 MonoMethod *m = tmp->data;
4679 generic_array_method_info [i].array_method = m;
4680 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4681 iname = "System.Collections.Generic.ICollection`1.";
4682 mname = m->name + 27;
4683 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4684 iname = "System.Collections.Generic.IEnumerable`1.";
4685 mname = m->name + 27;
4686 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4687 iname = "System.Collections.Generic.IList`1.";
4688 mname = m->name + 15;
4690 g_assert_not_reached ();
4693 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4694 strcpy (name, iname);
4695 strcpy (name + strlen (iname), mname);
4696 generic_array_method_info [i].name = name;
4699 /*g_print ("array generic methods: %d\n", count_generic);*/
4701 generic_array_method_num = count_generic;
4703 return generic_array_method_num;
4707 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4709 MonoGenericContext tmp_context;
4712 tmp_context.class_inst = NULL;
4713 tmp_context.method_inst = iface->generic_class->context.class_inst;
4714 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4716 for (i = 0; i < generic_array_method_num; i++) {
4717 MonoMethod *m = generic_array_method_info [i].array_method;
4718 MonoMethod *inflated;
4720 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4721 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4726 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4728 int null_length = strlen ("(null)");
4729 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4730 char *s = mono_image_alloc (image, len);
4733 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4734 g_assert (result == len - 1);
4740 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4742 gpointer exception_data = NULL;
4744 switch (error->exception_type) {
4745 case MONO_EXCEPTION_TYPE_LOAD:
4746 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4749 case MONO_EXCEPTION_MISSING_METHOD:
4750 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4753 case MONO_EXCEPTION_MISSING_FIELD: {
4754 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4755 const char *class_name;
4758 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4760 class_name = error->klass->name;
4762 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4765 g_free ((void*)class_name);
4769 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4772 if (error->ref_only)
4773 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.";
4775 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4777 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4781 case MONO_EXCEPTION_BAD_IMAGE:
4782 exception_data = error->msg;
4786 g_assert_not_reached ();
4789 mono_class_set_failure (class, error->exception_type, exception_data);
4794 * @class: the class to initialize
4796 * Compute the instance_size, class_size and other infos that cannot be
4797 * computed at mono_class_get() time. Also compute vtable_size if possible.
4798 * Returns TRUE on success or FALSE if there was a problem in loading
4799 * the type (incorrect assemblies, missing assemblies, methods, etc).
4801 * LOCKING: Acquires the loader lock.
4804 mono_class_init (MonoClass *class)
4807 MonoCachedClassInfo cached_info;
4808 gboolean has_cached_info;
4812 /* Double-checking locking pattern */
4813 if (class->inited || class->exception_type)
4814 return class->exception_type == MONO_EXCEPTION_NONE;
4816 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4818 /* We do everything inside the lock to prevent races */
4819 mono_loader_lock ();
4821 if (class->inited || class->exception_type) {
4822 mono_loader_unlock ();
4823 /* Somebody might have gotten in before us */
4824 return class->exception_type == MONO_EXCEPTION_NONE;
4827 if (class->init_pending) {
4828 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4832 class->init_pending = 1;
4834 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4835 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4840 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4841 MonoClass *element_class = class->element_class;
4842 if (!element_class->inited)
4843 mono_class_init (element_class);
4844 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4845 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4850 /* CAS - SecurityAction.InheritanceDemand */
4851 if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4852 mono_secman_inheritancedemand_class (class, class->parent);
4855 mono_stats.initialized_class_count++;
4857 if (class->generic_class && !class->generic_class->is_dynamic) {
4858 MonoClass *gklass = class->generic_class->container_class;
4860 mono_stats.generic_class_count++;
4862 class->method = gklass->method;
4863 class->field = gklass->field;
4865 mono_class_init (gklass);
4866 // FIXME: Why is this needed ?
4867 if (!gklass->exception_type)
4868 mono_class_setup_methods (gklass);
4869 if (gklass->exception_type) {
4870 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4874 if (MONO_CLASS_IS_INTERFACE (class))
4875 class->interface_id = mono_get_unique_iid (class);
4878 if (class->parent && !class->parent->inited)
4879 mono_class_init (class->parent);
4881 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4883 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4884 class->nested_classes_inited = TRUE;
4887 * Computes the size used by the fields, and their locations
4889 if (has_cached_info) {
4890 class->instance_size = cached_info.instance_size;
4891 class->sizes.class_size = cached_info.class_size;
4892 class->packing_size = cached_info.packing_size;
4893 class->min_align = cached_info.min_align;
4894 class->blittable = cached_info.blittable;
4895 class->has_references = cached_info.has_references;
4896 class->has_static_refs = cached_info.has_static_refs;
4897 class->no_special_static_fields = cached_info.no_special_static_fields;
4900 if (!class->size_inited){
4901 mono_class_setup_fields (class);
4902 if (class->exception_type || mono_loader_get_last_error ())
4906 /* Initialize arrays */
4908 class->method.count = 3 + (class->rank > 1? 2: 1);
4910 if (class->interface_count) {
4911 int count_generic = generic_array_methods (class);
4912 class->method.count += class->interface_count * count_generic;
4916 mono_class_setup_supertypes (class);
4919 initialize_object_slots (class);
4922 * Initialize the rest of the data without creating a generic vtable if possible.
4923 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4924 * also avoid computing a generic vtable.
4926 if (has_cached_info) {
4928 class->vtable_size = cached_info.vtable_size;
4929 class->has_finalize = cached_info.has_finalize;
4930 class->has_finalize_inited = TRUE;
4931 class->ghcimpl = cached_info.ghcimpl;
4932 class->has_cctor = cached_info.has_cctor;
4933 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
4934 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4935 * The first slot if for array with.
4937 static int szarray_vtable_size[2] = { 0 };
4939 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
4942 if (!szarray_vtable_size [slot]) {
4943 mono_class_setup_vtable (class);
4944 szarray_vtable_size [slot] = class->vtable_size;
4946 class->vtable_size = szarray_vtable_size[slot];
4948 class->has_finalize_inited = TRUE;
4949 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
4950 MonoClass *gklass = class->generic_class->container_class;
4952 /* Generic instance case */
4953 class->ghcimpl = gklass->ghcimpl;
4954 class->has_finalize = mono_class_has_finalizer (gklass);
4955 class->has_finalize_inited = TRUE;
4956 class->has_cctor = gklass->has_cctor;
4958 mono_class_setup_vtable (gklass);
4959 if (gklass->exception_type) {
4960 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4964 class->vtable_size = gklass->vtable_size;
4968 /* ghcimpl is not currently used
4970 if (class->parent) {
4971 MonoMethod *cmethod = class->vtable [ghc_slot];
4972 if (cmethod->is_inflated)
4973 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4974 if (cmethod == default_ghc) {
4980 /* C# doesn't allow interfaces to have cctors */
4981 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
4982 MonoMethod *cmethod = NULL;
4984 if (class->type_token) {
4985 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4986 /* The find_method function ignores the 'flags' argument */
4987 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
4988 class->has_cctor = 1;
4990 mono_class_setup_methods (class);
4991 if (class->exception_type)
4994 for (i = 0; i < class->method.count; ++i) {
4995 MonoMethod *method = class->methods [i];
4996 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
4997 (strcmp (".cctor", method->name) == 0)) {
4998 class->has_cctor = 1;
5006 if (class->parent) {
5007 int first_iface_slot;
5008 /* This will compute class->parent->vtable_size for some classes */
5009 mono_class_init (class->parent);
5010 if (class->parent->exception_type) {
5011 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5014 if (mono_loader_get_last_error ())
5016 if (!class->parent->vtable_size) {
5017 /* FIXME: Get rid of this somehow */
5018 mono_class_setup_vtable (class->parent);
5019 if (class->parent->exception_type) {
5020 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5023 if (mono_loader_get_last_error ())
5026 first_iface_slot = class->parent->vtable_size;
5027 if (mono_class_need_stelemref_method (class))
5029 setup_interface_offsets (class, first_iface_slot, TRUE);
5031 setup_interface_offsets (class, 0, TRUE);
5034 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
5035 mono_security_core_clr_check_inheritance (class);
5037 if (mono_loader_get_last_error ()) {
5038 if (class->exception_type == MONO_EXCEPTION_NONE) {
5039 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5041 mono_loader_clear_error ();
5044 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5045 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5050 /* Because of the double-checking locking pattern */
5051 mono_memory_barrier ();
5053 class->init_pending = 0;
5055 mono_loader_unlock ();
5057 if (mono_debugger_class_init_func)
5058 mono_debugger_class_init_func (class);
5060 return class->exception_type == MONO_EXCEPTION_NONE;
5064 * mono_class_has_finalizer:
5066 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5070 mono_class_has_finalizer (MonoClass *klass)
5072 if (!klass->has_finalize_inited) {
5073 MonoClass *class = klass;
5075 mono_loader_lock ();
5077 /* Interfaces and valuetypes are not supposed to have finalizers */
5078 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5079 MonoMethod *cmethod = NULL;
5081 if (class->parent && class->parent->has_finalize) {
5082 class->has_finalize = 1;
5084 if (class->parent) {
5086 * Can't search in metadata for a method named Finalize, because that
5087 * ignores overrides.
5089 mono_class_setup_vtable (class);
5090 if (class->exception_type || mono_loader_get_last_error ())
5092 cmethod = class->vtable [finalize_slot];
5096 g_assert (class->vtable_size > finalize_slot);
5098 class->has_finalize = 0;
5099 if (class->parent) {
5100 if (cmethod->is_inflated)
5101 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5102 if (cmethod != default_finalize) {
5103 class->has_finalize = 1;
5110 mono_memory_barrier ();
5111 klass->has_finalize_inited = TRUE;
5113 mono_loader_unlock ();
5116 return klass->has_finalize;
5119 mono_loader_unlock ();
5124 mono_is_corlib_image (MonoImage *image)
5126 /* FIXME: allow the dynamic case for our compilers and with full trust */
5128 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5130 return image == mono_defaults.corlib;
5134 * LOCKING: this assumes the loader lock is held
5137 mono_class_setup_mono_type (MonoClass *class)
5139 const char *name = class->name;
5140 const char *nspace = class->name_space;
5141 gboolean is_corlib = mono_is_corlib_image (class->image);
5143 class->this_arg.byref = 1;
5144 class->this_arg.data.klass = class;
5145 class->this_arg.type = MONO_TYPE_CLASS;
5146 class->byval_arg.data.klass = class;
5147 class->byval_arg.type = MONO_TYPE_CLASS;
5149 if (is_corlib && !strcmp (nspace, "System")) {
5150 if (!strcmp (name, "ValueType")) {
5152 * do not set the valuetype bit for System.ValueType.
5153 * class->valuetype = 1;
5155 class->blittable = TRUE;
5156 } else if (!strcmp (name, "Enum")) {
5158 * do not set the valuetype bit for System.Enum.
5159 * class->valuetype = 1;
5161 class->valuetype = 0;
5162 class->enumtype = 0;
5163 } else if (!strcmp (name, "Object")) {
5164 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5165 } else if (!strcmp (name, "String")) {
5166 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5167 } else if (!strcmp (name, "TypedReference")) {
5168 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5172 if (class->valuetype) {
5173 int t = MONO_TYPE_VALUETYPE;
5175 if (is_corlib && !strcmp (nspace, "System")) {
5178 if (!strcmp (name, "Boolean")) {
5179 t = MONO_TYPE_BOOLEAN;
5180 } else if (!strcmp(name, "Byte")) {
5182 class->blittable = TRUE;
5186 if (!strcmp (name, "Char")) {
5191 if (!strcmp (name, "Double")) {
5193 class->blittable = TRUE;
5197 if (!strcmp (name, "Int32")) {
5199 class->blittable = TRUE;
5200 } else if (!strcmp(name, "Int16")) {
5202 class->blittable = TRUE;
5203 } else if (!strcmp(name, "Int64")) {
5205 class->blittable = TRUE;
5206 } else if (!strcmp(name, "IntPtr")) {
5208 class->blittable = TRUE;
5212 if (!strcmp (name, "Single")) {
5214 class->blittable = TRUE;
5215 } else if (!strcmp(name, "SByte")) {
5217 class->blittable = TRUE;
5221 if (!strcmp (name, "UInt32")) {
5223 class->blittable = TRUE;
5224 } else if (!strcmp(name, "UInt16")) {
5226 class->blittable = TRUE;
5227 } else if (!strcmp(name, "UInt64")) {
5229 class->blittable = TRUE;
5230 } else if (!strcmp(name, "UIntPtr")) {
5232 class->blittable = TRUE;
5236 if (!strcmp (name, "TypedReference")) {
5237 t = MONO_TYPE_TYPEDBYREF;
5238 class->blittable = TRUE;
5242 if (!strcmp (name, "Void")) {
5250 class->this_arg.type = class->byval_arg.type = t;
5253 if (MONO_CLASS_IS_INTERFACE (class))
5254 class->interface_id = mono_get_unique_iid (class);
5260 * COM initialization (using mono_init_com_types) is delayed until needed.
5261 * However when a [ComImport] attribute is present on a type it will trigger
5262 * the initialization. This is not a problem unless the BCL being executed
5263 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5266 init_com_from_comimport (MonoClass *class)
5268 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5269 if ((mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)) {
5270 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5271 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5272 /* but it can not be made available for application (i.e. user code) since all COM calls
5273 * are considered native calls. In this case we fail with a TypeLoadException (just like
5274 * Silverlight 2 does */
5275 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5279 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5280 mono_init_com_types ();
5282 #endif /*DISABLE_COM*/
5285 * LOCKING: this assumes the loader lock is held
5288 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5290 gboolean system_namespace;
5291 gboolean is_corlib = mono_is_corlib_image (class->image);
5293 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5295 /* if root of the hierarchy */
5296 if (system_namespace && !strcmp (class->name, "Object")) {
5297 class->parent = NULL;
5298 class->instance_size = sizeof (MonoObject);
5301 if (!strcmp (class->name, "<Module>")) {
5302 class->parent = NULL;
5303 class->instance_size = 0;
5307 if (!MONO_CLASS_IS_INTERFACE (class)) {
5308 /* Imported COM Objects always derive from __ComObject. */
5310 if (MONO_CLASS_IS_IMPORT (class)) {
5311 init_com_from_comimport (class);
5312 if (parent == mono_defaults.object_class)
5313 parent = mono_defaults.com_object_class;
5317 /* set the parent to something useful and safe, but mark the type as broken */
5318 parent = mono_defaults.object_class;
5319 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5322 class->parent = parent;
5324 if (parent->generic_class && !parent->name) {
5326 * If the parent is a generic instance, we may get
5327 * called before it is fully initialized, especially
5328 * before it has its name.
5333 class->marshalbyref = parent->marshalbyref;
5334 class->contextbound = parent->contextbound;
5335 class->delegate = parent->delegate;
5336 if (MONO_CLASS_IS_IMPORT (class))
5337 class->is_com_object = 1;
5339 class->is_com_object = parent->is_com_object;
5341 if (system_namespace) {
5342 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5343 class->marshalbyref = 1;
5345 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5346 class->contextbound = 1;
5348 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5349 class->delegate = 1;
5352 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5353 (strcmp (class->parent->name_space, "System") == 0)))
5354 class->valuetype = 1;
5355 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5356 class->valuetype = class->enumtype = 1;
5358 /*class->enumtype = class->parent->enumtype; */
5360 /* initialize com types if COM interfaces are present */
5362 if (MONO_CLASS_IS_IMPORT (class))
5363 init_com_from_comimport (class);
5365 class->parent = NULL;
5371 * mono_class_setup_supertypes:
5374 * Build the data structure needed to make fast type checks work.
5375 * This currently sets two fields in @class:
5376 * - idepth: distance between @class and System.Object in the type
5378 * - supertypes: array of classes: each element has a class in the hierarchy
5379 * starting from @class up to System.Object
5381 * LOCKING: this assumes the loader lock is held
5384 mono_class_setup_supertypes (MonoClass *class)
5387 MonoClass **supertypes;
5389 if (class->supertypes)
5392 if (class->parent && !class->parent->supertypes)
5393 mono_class_setup_supertypes (class->parent);
5395 class->idepth = class->parent->idepth + 1;
5399 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5400 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5402 if (class->parent) {
5403 supertypes [class->idepth - 1] = class;
5404 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5406 supertypes [0] = class;
5409 mono_atomic_store_release (&class->supertypes, supertypes);
5413 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5415 MonoClass *gtd = (MonoClass*)user_data;
5416 /* Only try to fix generic instances of @gtd */
5417 if (gclass->generic_class->container_class != gtd)
5420 /* Check if the generic instance has no parent. */
5421 if (gtd->parent && !gclass->parent)
5422 mono_generic_class_setup_parent (gclass, gtd);
5428 * mono_class_create_from_typedef:
5429 * @image: image where the token is valid
5430 * @type_token: typedef token
5432 * Create the MonoClass* representing the specified type token.
5433 * @type_token must be a TypeDef token.
5435 * FIXME: don't return NULL on failure, just the the caller figure it out.
5438 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
5440 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5441 MonoClass *class, *parent = NULL;
5442 guint32 cols [MONO_TYPEDEF_SIZE];
5443 guint32 cols_next [MONO_TYPEDEF_SIZE];
5444 guint tidx = mono_metadata_token_index (type_token);
5445 MonoGenericContext *context = NULL;
5446 const char *name, *nspace;
5448 MonoClass **interfaces;
5449 guint32 field_last, method_last;
5450 guint32 nesting_tokeen;
5452 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows)
5455 mono_loader_lock ();
5457 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5458 mono_loader_unlock ();
5462 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5464 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5465 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5467 class = mono_image_alloc0 (image, sizeof (MonoClass));
5470 class->name_space = nspace;
5472 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5474 class->image = image;
5475 class->type_token = type_token;
5476 class->flags = cols [MONO_TYPEDEF_FLAGS];
5478 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5480 classes_size += sizeof (MonoClass);
5483 * Check whether we're a generic type definition.
5485 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5486 if (class->generic_container) {
5487 class->is_generic = 1;
5488 class->generic_container->owner.klass = class;
5489 context = &class->generic_container->context;
5492 if (class->generic_container)
5493 enable_gclass_recording ();
5495 if (cols [MONO_TYPEDEF_EXTENDS]) {
5497 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5499 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5500 /*WARNING: this must satisfy mono_metadata_type_hash*/
5501 class->this_arg.byref = 1;
5502 class->this_arg.data.klass = class;
5503 class->this_arg.type = MONO_TYPE_CLASS;
5504 class->byval_arg.data.klass = class;
5505 class->byval_arg.type = MONO_TYPE_CLASS;
5507 parent = mono_class_get_full (image, parent_token, context);
5509 if (parent == NULL){
5510 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load parent type"));
5511 mono_loader_clear_error ();
5512 goto parent_failure;
5515 for (tmp = parent; tmp; tmp = tmp->parent) {
5517 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cycle found while resolving parent"));
5518 goto parent_failure;
5520 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5521 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Parent extends generic instance of this type"));
5522 goto parent_failure;
5527 mono_class_setup_parent (class, parent);
5529 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5530 mono_class_setup_mono_type (class);
5532 if (class->generic_container)
5533 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5536 * This might access class->byval_arg for recursion generated by generic constraints,
5537 * so it has to come after setup_mono_type ().
5539 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5540 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
5541 if (!class->nested_in) {
5542 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load nestedin type"));
5543 mono_loader_unlock ();
5544 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5549 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5553 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5557 class->cast_class = class->element_class = class;
5559 if (!class->enumtype) {
5560 if (!mono_metadata_interfaces_from_typedef_full (
5561 image, type_token, &interfaces, &icount, FALSE, context)){
5562 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load interfaces"));
5563 mono_loader_unlock ();
5564 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5568 class->interfaces = interfaces;
5569 class->interface_count = icount;
5570 class->interfaces_inited = 1;
5573 /*g_print ("Load class %s\n", name);*/
5576 * Compute the field and method lists
5578 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5579 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5581 if (tt->rows > tidx){
5582 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5583 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5584 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5586 field_last = image->tables [MONO_TABLE_FIELD].rows;
5587 method_last = image->tables [MONO_TABLE_METHOD].rows;
5590 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5591 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5592 class->field.count = field_last - class->field.first;
5594 class->field.count = 0;
5596 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5597 class->method.count = method_last - class->method.first;
5599 class->method.count = 0;
5601 /* reserve space to store vector pointer in arrays */
5602 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5603 class->instance_size += 2 * sizeof (gpointer);
5604 g_assert (class->field.count == 0);
5607 if (class->enumtype) {
5608 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5609 if (!enum_basetype) {
5610 /*set it to a default value as the whole runtime can't handle this to be null*/
5611 class->cast_class = class->element_class = mono_defaults.int32_class;
5612 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5613 mono_loader_unlock ();
5614 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5617 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5621 * If we're a generic type definition, load the constraints.
5622 * We must do this after the class has been constructed to make certain recursive scenarios
5625 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5626 char *class_name = g_strdup_printf("%s.%s", class->name_space, class->name);
5627 char *error = concat_two_strings_with_zero (class->image, class_name, class->image->assembly_name);
5628 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, error);
5629 g_free (class_name);
5630 mono_loader_unlock ();
5631 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5635 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5636 if (!strncmp (name, "Vector", 6))
5637 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");
5640 mono_loader_unlock ();
5642 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5647 mono_class_setup_mono_type (class);
5648 mono_loader_unlock ();
5649 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5654 /** is klass Nullable<T>? */
5656 mono_class_is_nullable (MonoClass *klass)
5658 return klass->generic_class != NULL &&
5659 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5663 /** if klass is T? return T */
5665 mono_class_get_nullable_param (MonoClass *klass)
5667 g_assert (mono_class_is_nullable (klass));
5668 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5672 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5676 MonoGenericClass *gclass = klass->generic_class;
5678 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5679 if (!mono_error_ok (&error)) {
5680 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5681 klass->parent = mono_defaults.object_class;
5682 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5683 mono_error_cleanup (&error);
5687 mono_class_setup_parent (klass, klass->parent);
5689 if (klass->enumtype) {
5690 klass->cast_class = gtd->cast_class;
5691 klass->element_class = gtd->element_class;
5697 * Create the `MonoClass' for an instantiation of a generic type.
5698 * We only do this if we actually need it.
5701 mono_generic_class_get_class (MonoGenericClass *gclass)
5703 MonoClass *klass, *gklass;
5705 if (gclass->cached_class)
5706 return gclass->cached_class;
5708 mono_loader_lock ();
5709 if (gclass->cached_class) {
5710 mono_loader_unlock ();
5711 return gclass->cached_class;
5714 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5716 gklass = gclass->container_class;
5718 if (record_gclass_instantiation > 0)
5719 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5721 if (gklass->nested_in) {
5722 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5723 klass->nested_in = gklass->nested_in;
5726 klass->name = gklass->name;
5727 klass->name_space = gklass->name_space;
5729 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5731 klass->image = gklass->image;
5732 klass->flags = gklass->flags;
5733 klass->type_token = gklass->type_token;
5734 klass->field.count = gklass->field.count;
5736 klass->is_inflated = 1;
5737 klass->generic_class = gclass;
5739 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5740 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5741 klass->this_arg.byref = TRUE;
5742 klass->enumtype = gklass->enumtype;
5743 klass->valuetype = gklass->valuetype;
5745 klass->cast_class = klass->element_class = klass;
5747 if (mono_class_is_nullable (klass))
5748 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5751 * We're not interested in the nested classes of a generic instance.
5752 * We use the generic type definition to look for nested classes.
5755 mono_generic_class_setup_parent (klass, gklass);
5757 if (gclass->is_dynamic) {
5760 mono_class_setup_supertypes (klass);
5762 if (klass->enumtype) {
5764 * For enums, gklass->fields might not been set, but instance_size etc. is
5765 * already set in mono_reflection_create_internal_class (). For non-enums,
5766 * these will be computed normally in mono_class_layout_fields ().
5768 klass->instance_size = gklass->instance_size;
5769 klass->sizes.class_size = gklass->sizes.class_size;
5770 klass->size_inited = 1;
5774 mono_memory_barrier ();
5775 gclass->cached_class = klass;
5777 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5779 inflated_classes ++;
5780 inflated_classes_size += sizeof (MonoClass);
5782 mono_loader_unlock ();
5788 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5790 MonoClass *klass, **ptr;
5792 MonoGenericContainer *container = mono_generic_param_owner (param);
5796 image = mono_defaults.corlib;
5798 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5799 classes_size += sizeof (MonoClass);
5802 klass->name = pinfo->name;
5804 int n = mono_generic_param_num (param);
5805 klass->name = mono_image_alloc0 (image, 16);
5806 sprintf ((char*)klass->name, "%d", n);
5811 MonoMethod *omethod = container->owner.method;
5812 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5814 MonoClass *oklass = container->owner.klass;
5815 klass->name_space = oklass ? oklass->name_space : "";
5818 klass->name_space = "";
5821 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5825 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5829 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5830 klass->parent = pinfo->constraints [0];
5832 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5833 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5835 klass->parent = mono_defaults.object_class;
5838 if (count - pos > 0) {
5839 klass->interface_count = count - pos;
5840 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5841 klass->interfaces_inited = TRUE;
5842 for (i = pos; i < count; i++)
5843 klass->interfaces [i - pos] = pinfo->constraints [i];
5846 klass->image = image;
5848 klass->inited = TRUE;
5849 klass->cast_class = klass->element_class = klass;
5850 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5852 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5853 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5854 klass->this_arg.byref = TRUE;
5856 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5857 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5859 /*Init these fields to sane values*/
5860 klass->min_align = 1;
5861 klass->instance_size = sizeof (gpointer);
5862 klass->size_inited = 1;
5864 mono_class_setup_supertypes (klass);
5866 if (count - pos > 0) {
5867 mono_class_setup_vtable (klass->parent);
5868 if (klass->parent->exception_type)
5869 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
5871 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
5877 #define FAST_CACHE_SIZE 16
5880 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
5882 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5883 MonoImage *image = param->image;
5888 if (n < FAST_CACHE_SIZE) {
5890 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
5892 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
5894 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5895 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
5900 * LOCKING: Acquires the loader lock.
5903 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
5905 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
5906 MonoImage *image = param->image;
5911 if (n < FAST_CACHE_SIZE) {
5913 /* No locking needed */
5914 if (!image->mvar_cache_fast)
5915 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
5916 image->mvar_cache_fast [n] = klass;
5918 if (!image->var_cache_fast)
5919 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
5920 image->var_cache_fast [n] = klass;
5924 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5926 mono_loader_lock ();
5927 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
5929 ht = g_hash_table_new (NULL, NULL);
5930 mono_memory_barrier ();
5932 image->mvar_cache_slow = ht;
5934 image->var_cache_slow = ht;
5936 mono_loader_unlock ();
5939 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
5943 * LOCKING: Acquires the loader lock.
5946 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
5948 MonoGenericContainer *container = mono_generic_param_owner (param);
5949 MonoGenericParamInfo *pinfo;
5952 mono_loader_lock ();
5955 pinfo = mono_generic_param_info (param);
5956 if (pinfo->pklass) {
5957 mono_loader_unlock ();
5958 return pinfo->pklass;
5964 klass = get_anon_gparam_class (param, is_mvar);
5966 mono_loader_unlock ();
5971 if (!image && container) {
5973 MonoMethod *method = container->owner.method;
5974 image = (method && method->klass) ? method->klass->image : NULL;
5976 MonoClass *klass = container->owner.klass;
5977 // FIXME: 'klass' should not be null
5978 // But, monodis creates GenericContainers without associating a owner to it
5979 image = klass ? klass->image : NULL;
5983 klass = make_generic_param_class (param, image, is_mvar, pinfo);
5985 mono_memory_barrier ();
5988 pinfo->pklass = klass;
5990 set_anon_gparam_class (param, is_mvar, klass);
5992 mono_loader_unlock ();
5994 /* FIXME: Should this go inside 'make_generic_param_klass'? */
5995 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6001 mono_ptr_class_get (MonoType *type)
6004 MonoClass *el_class;
6008 el_class = mono_class_from_mono_type (type);
6009 image = el_class->image;
6011 mono_loader_lock ();
6013 if (!image->ptr_cache)
6014 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6016 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6017 mono_loader_unlock ();
6020 result = mono_image_alloc0 (image, sizeof (MonoClass));
6022 classes_size += sizeof (MonoClass);
6024 result->parent = NULL; /* no parent for PTR types */
6025 result->name_space = el_class->name_space;
6026 name = g_strdup_printf ("%s*", el_class->name);
6027 result->name = mono_image_strdup (image, name);
6030 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6032 result->image = el_class->image;
6033 result->inited = TRUE;
6034 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6035 /* Can pointers get boxed? */
6036 result->instance_size = sizeof (gpointer);
6037 result->cast_class = result->element_class = el_class;
6038 result->blittable = TRUE;
6040 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6041 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6042 result->this_arg.byref = TRUE;
6044 mono_class_setup_supertypes (result);
6046 g_hash_table_insert (image->ptr_cache, el_class, result);
6048 mono_loader_unlock ();
6050 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6056 mono_fnptr_class_get (MonoMethodSignature *sig)
6059 static GHashTable *ptr_hash = NULL;
6061 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6063 mono_loader_lock ();
6066 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6068 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6069 mono_loader_unlock ();
6072 result = g_new0 (MonoClass, 1);
6074 result->parent = NULL; /* no parent for PTR types */
6075 result->name_space = "System";
6076 result->name = "MonoFNPtrFakeClass";
6078 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6080 result->image = mono_defaults.corlib; /* need to fix... */
6081 result->inited = TRUE;
6082 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6083 /* Can pointers get boxed? */
6084 result->instance_size = sizeof (gpointer);
6085 result->cast_class = result->element_class = result;
6086 result->blittable = TRUE;
6088 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6089 result->this_arg.data.method = result->byval_arg.data.method = sig;
6090 result->this_arg.byref = TRUE;
6091 result->blittable = TRUE;
6093 mono_class_setup_supertypes (result);
6095 g_hash_table_insert (ptr_hash, sig, result);
6097 mono_loader_unlock ();
6099 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6105 mono_class_from_mono_type (MonoType *type)
6107 switch (type->type) {
6108 case MONO_TYPE_OBJECT:
6109 return type->data.klass? type->data.klass: mono_defaults.object_class;
6110 case MONO_TYPE_VOID:
6111 return type->data.klass? type->data.klass: mono_defaults.void_class;
6112 case MONO_TYPE_BOOLEAN:
6113 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6114 case MONO_TYPE_CHAR:
6115 return type->data.klass? type->data.klass: mono_defaults.char_class;
6117 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6119 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6121 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6123 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6125 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6127 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6129 return type->data.klass? type->data.klass: mono_defaults.int_class;
6131 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6133 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6135 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6137 return type->data.klass? type->data.klass: mono_defaults.single_class;
6139 return type->data.klass? type->data.klass: mono_defaults.double_class;
6140 case MONO_TYPE_STRING:
6141 return type->data.klass? type->data.klass: mono_defaults.string_class;
6142 case MONO_TYPE_TYPEDBYREF:
6143 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6144 case MONO_TYPE_ARRAY:
6145 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6147 return mono_ptr_class_get (type->data.type);
6148 case MONO_TYPE_FNPTR:
6149 return mono_fnptr_class_get (type->data.method);
6150 case MONO_TYPE_SZARRAY:
6151 return mono_array_class_get (type->data.klass, 1);
6152 case MONO_TYPE_CLASS:
6153 case MONO_TYPE_VALUETYPE:
6154 return type->data.klass;
6155 case MONO_TYPE_GENERICINST:
6156 return mono_generic_class_get_class (type->data.generic_class);
6158 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6159 case MONO_TYPE_MVAR:
6160 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6162 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6163 g_assert_not_reached ();
6170 * mono_type_retrieve_from_typespec
6171 * @image: context where the image is created
6172 * @type_spec: typespec token
6173 * @context: the generic context used to evaluate generic instantiations in
6176 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6178 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6180 mono_error_init (error);
6181 *did_inflate = FALSE;
6184 char *name = mono_class_name_from_token (image, type_spec);
6185 char *assembly = mono_assembly_name_from_token (image, type_spec);
6186 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6190 if (context && (context->class_inst || context->method_inst)) {
6191 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6193 if (!mono_error_ok (error))
6198 *did_inflate = TRUE;
6205 * mono_class_create_from_typespec
6206 * @image: context where the image is created
6207 * @type_spec: typespec token
6208 * @context: the generic context used to evaluate generic instantiations in
6211 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6214 gboolean inflated = FALSE;
6215 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6216 if (!mono_error_ok (error))
6218 ret = mono_class_from_mono_type (t);
6220 mono_metadata_free_type (t);
6225 * mono_bounded_array_class_get:
6226 * @element_class: element class
6227 * @rank: the dimension of the array class
6228 * @bounded: whenever the array has non-zero bounds
6230 * Returns: a class object describing the array with element type @element_type and
6234 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6238 MonoClass *parent = NULL;
6239 GSList *list, *rootlist = NULL;
6242 gboolean corlib_type = FALSE;
6244 g_assert (rank <= 255);
6247 /* bounded only matters for one-dimensional arrays */
6250 image = eclass->image;
6252 if (rank == 1 && !bounded) {
6254 * This case is very frequent not just during compilation because of calls
6255 * from mono_class_from_mono_type (), mono_array_new (),
6256 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6258 EnterCriticalSection (&image->szarray_cache_lock);
6259 if (!image->szarray_cache)
6260 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6261 class = g_hash_table_lookup (image->szarray_cache, eclass);
6262 LeaveCriticalSection (&image->szarray_cache_lock);
6266 mono_loader_lock ();
6268 mono_loader_lock ();
6270 if (!image->array_cache)
6271 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6273 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6274 for (; list; list = list->next) {
6276 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6277 mono_loader_unlock ();
6284 /* for the building corlib use System.Array from it */
6285 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6286 parent = mono_class_from_name (image, "System", "Array");
6289 parent = mono_defaults.array_class;
6290 if (!parent->inited)
6291 mono_class_init (parent);
6294 class = mono_image_alloc0 (image, sizeof (MonoClass));
6296 class->image = image;
6297 class->name_space = eclass->name_space;
6298 nsize = strlen (eclass->name);
6299 name = g_malloc (nsize + 2 + rank + 1);
6300 memcpy (name, eclass->name, nsize);
6303 memset (name + nsize + 1, ',', rank - 1);
6305 name [nsize + rank] = '*';
6306 name [nsize + rank + bounded] = ']';
6307 name [nsize + rank + bounded + 1] = 0;
6308 class->name = mono_image_strdup (image, name);
6311 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6313 classes_size += sizeof (MonoClass);
6315 class->type_token = 0;
6316 /* all arrays are marked serializable and sealed, bug #42779 */
6317 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6318 class->parent = parent;
6319 class->instance_size = mono_class_instance_size (class->parent);
6321 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6322 /*Arrays of those two types are invalid.*/
6323 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6324 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6325 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6326 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6327 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6329 /* element_size -1 is ok as this is not an instantitable type*/
6330 class->sizes.element_size = -1;
6332 class->sizes.element_size = mono_class_array_element_size (eclass);
6334 mono_class_setup_supertypes (class);
6336 if (eclass->generic_class)
6337 mono_class_init (eclass);
6338 if (!eclass->size_inited)
6339 mono_class_setup_fields (eclass);
6340 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6341 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6343 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6347 if (eclass->enumtype)
6348 class->cast_class = eclass->element_class;
6350 class->cast_class = eclass;
6352 switch (class->cast_class->byval_arg.type) {
6354 class->cast_class = mono_defaults.byte_class;
6357 class->cast_class = mono_defaults.int16_class;
6360 #if SIZEOF_VOID_P == 4
6364 class->cast_class = mono_defaults.int32_class;
6367 #if SIZEOF_VOID_P == 8
6371 class->cast_class = mono_defaults.int64_class;
6375 class->element_class = eclass;
6377 if ((rank > 1) || bounded) {
6378 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6379 class->byval_arg.type = MONO_TYPE_ARRAY;
6380 class->byval_arg.data.array = at;
6381 at->eklass = eclass;
6383 /* FIXME: complete.... */
6385 class->byval_arg.type = MONO_TYPE_SZARRAY;
6386 class->byval_arg.data.klass = eclass;
6388 class->this_arg = class->byval_arg;
6389 class->this_arg.byref = 1;
6394 class->generic_container = eclass->generic_container;
6396 if (rank == 1 && !bounded) {
6397 MonoClass *prev_class;
6399 EnterCriticalSection (&image->szarray_cache_lock);
6400 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6402 /* Someone got in before us */
6405 g_hash_table_insert (image->szarray_cache, eclass, class);
6406 LeaveCriticalSection (&image->szarray_cache_lock);
6408 list = g_slist_append (rootlist, class);
6409 g_hash_table_insert (image->array_cache, eclass, list);
6412 mono_loader_unlock ();
6414 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6420 * mono_array_class_get:
6421 * @element_class: element class
6422 * @rank: the dimension of the array class
6424 * Returns: a class object describing the array with element type @element_type and
6428 mono_array_class_get (MonoClass *eclass, guint32 rank)
6430 return mono_bounded_array_class_get (eclass, rank, FALSE);
6434 * mono_class_instance_size:
6437 * Returns: the size of an object instance
6440 mono_class_instance_size (MonoClass *klass)
6442 if (!klass->size_inited)
6443 mono_class_init (klass);
6445 return klass->instance_size;
6449 * mono_class_min_align:
6452 * Returns: minimm alignment requirements
6455 mono_class_min_align (MonoClass *klass)
6457 if (!klass->size_inited)
6458 mono_class_init (klass);
6460 return klass->min_align;
6464 * mono_class_value_size:
6467 * This function is used for value types, and return the
6468 * space and the alignment to store that kind of value object.
6470 * Returns: the size of a value of kind @klass
6473 mono_class_value_size (MonoClass *klass, guint32 *align)
6477 /* fixme: check disable, because we still have external revereces to
6478 * mscorlib and Dummy Objects
6480 /*g_assert (klass->valuetype);*/
6482 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6485 *align = klass->min_align;
6491 * mono_class_data_size:
6494 * Returns: the size of the static class data
6497 mono_class_data_size (MonoClass *klass)
6500 mono_class_init (klass);
6502 /* in arrays, sizes.class_size is unioned with element_size
6503 * and arrays have no static fields
6507 return klass->sizes.class_size;
6511 * Auxiliary routine to mono_class_get_field
6513 * Takes a field index instead of a field token.
6515 static MonoClassField *
6516 mono_class_get_field_idx (MonoClass *class, int idx)
6518 mono_class_setup_fields_locking (class);
6519 if (class->exception_type)
6523 if (class->image->uncompressed_metadata) {
6525 * class->field.first points to the FieldPtr table, while idx points into the
6526 * Field table, so we have to do a search.
6528 /*FIXME this is broken for types with multiple fields with the same name.*/
6529 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6532 for (i = 0; i < class->field.count; ++i)
6533 if (mono_field_get_name (&class->fields [i]) == name)
6534 return &class->fields [i];
6535 g_assert_not_reached ();
6537 if (class->field.count) {
6538 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6539 return &class->fields [idx - class->field.first];
6543 class = class->parent;
6549 * mono_class_get_field:
6550 * @class: the class to lookup the field.
6551 * @field_token: the field token
6553 * Returns: A MonoClassField representing the type and offset of
6554 * the field, or a NULL value if the field does not belong to this
6558 mono_class_get_field (MonoClass *class, guint32 field_token)
6560 int idx = mono_metadata_token_index (field_token);
6562 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6564 return mono_class_get_field_idx (class, idx - 1);
6568 * mono_class_get_field_from_name:
6569 * @klass: the class to lookup the field.
6570 * @name: the field name
6572 * Search the class @klass and it's parents for a field with the name @name.
6574 * Returns: the MonoClassField pointer of the named field or NULL
6577 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6579 return mono_class_get_field_from_name_full (klass, name, NULL);
6583 * mono_class_get_field_from_name_full:
6584 * @klass: the class to lookup the field.
6585 * @name: the field name
6586 * @type: the type of the fields. This optional.
6588 * Search the class @klass and it's parents for a field with the name @name and type @type.
6590 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6591 * of its generic type definition.
6593 * Returns: the MonoClassField pointer of the named field or NULL
6596 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6600 mono_class_setup_fields_locking (klass);
6601 if (klass->exception_type)
6605 for (i = 0; i < klass->field.count; ++i) {
6606 MonoClassField *field = &klass->fields [i];
6608 if (strcmp (name, mono_field_get_name (field)) != 0)
6612 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6613 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6618 klass = klass->parent;
6624 * mono_class_get_field_token:
6625 * @field: the field we need the token of
6627 * Get the token of a field. Note that the tokesn is only valid for the image
6628 * the field was loaded from. Don't use this function for fields in dynamic types.
6630 * Returns: the token representing the field in the image it was loaded from.
6633 mono_class_get_field_token (MonoClassField *field)
6635 MonoClass *klass = field->parent;
6638 mono_class_setup_fields_locking (klass);
6643 for (i = 0; i < klass->field.count; ++i) {
6644 if (&klass->fields [i] == field) {
6645 int idx = klass->field.first + i + 1;
6647 if (klass->image->uncompressed_metadata)
6648 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6649 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6652 klass = klass->parent;
6655 g_assert_not_reached ();
6660 mono_field_get_index (MonoClassField *field)
6662 int index = field - field->parent->fields;
6664 g_assert (index >= 0 && index < field->parent->field.count);
6670 * mono_class_get_field_default_value:
6672 * Return the default value of the field as a pointer into the metadata blob.
6675 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6678 guint32 constant_cols [MONO_CONSTANT_SIZE];
6680 MonoClass *klass = field->parent;
6682 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6684 if (!klass->ext || !klass->ext->field_def_values) {
6685 mono_loader_lock ();
6686 mono_class_alloc_ext (klass);
6687 if (!klass->ext->field_def_values)
6688 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6689 mono_loader_unlock ();
6692 field_index = mono_field_get_index (field);
6694 if (!klass->ext->field_def_values [field_index].data) {
6695 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6699 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6701 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6702 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6703 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6706 *def_type = klass->ext->field_def_values [field_index].def_type;
6707 return klass->ext->field_def_values [field_index].data;
6711 mono_property_get_index (MonoProperty *prop)
6713 int index = prop - prop->parent->ext->properties;
6715 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6721 * mono_class_get_property_default_value:
6723 * Return the default value of the field as a pointer into the metadata blob.
6726 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6729 guint32 constant_cols [MONO_CONSTANT_SIZE];
6730 MonoClass *klass = property->parent;
6732 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6734 * We don't cache here because it is not used by C# so it's quite rare, but
6735 * we still do the lookup in klass->ext because that is where the data
6736 * is stored for dynamic assemblies.
6739 if (klass->image->dynamic) {
6740 int prop_index = mono_property_get_index (property);
6741 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6742 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6743 return klass->ext->prop_def_values [prop_index].data;
6747 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6751 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6752 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6753 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6757 mono_class_get_event_token (MonoEvent *event)
6759 MonoClass *klass = event->parent;
6764 for (i = 0; i < klass->ext->event.count; ++i) {
6765 if (&klass->ext->events [i] == event)
6766 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6769 klass = klass->parent;
6772 g_assert_not_reached ();
6777 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6781 gpointer iter = NULL;
6782 while ((p = mono_class_get_properties (klass, &iter))) {
6783 if (! strcmp (name, p->name))
6786 klass = klass->parent;
6792 mono_class_get_property_token (MonoProperty *prop)
6794 MonoClass *klass = prop->parent;
6798 gpointer iter = NULL;
6799 while ((p = mono_class_get_properties (klass, &iter))) {
6800 if (&klass->ext->properties [i] == prop)
6801 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6805 klass = klass->parent;
6808 g_assert_not_reached ();
6813 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6815 const char *name, *nspace;
6817 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6819 switch (type_token & 0xff000000){
6820 case MONO_TOKEN_TYPE_DEF: {
6821 guint32 cols [MONO_TYPEDEF_SIZE];
6822 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6823 guint tidx = mono_metadata_token_index (type_token);
6825 if (tidx > tt->rows)
6826 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6828 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6829 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6830 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6831 if (strlen (nspace) == 0)
6832 return g_strdup_printf ("%s", name);
6834 return g_strdup_printf ("%s.%s", nspace, name);
6837 case MONO_TOKEN_TYPE_REF: {
6839 guint32 cols [MONO_TYPEREF_SIZE];
6840 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6841 guint tidx = mono_metadata_token_index (type_token);
6844 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6846 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6847 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6848 mono_error_cleanup (&error);
6852 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6853 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6854 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6855 if (strlen (nspace) == 0)
6856 return g_strdup_printf ("%s", name);
6858 return g_strdup_printf ("%s.%s", nspace, name);
6861 case MONO_TOKEN_TYPE_SPEC:
6862 return g_strdup_printf ("Typespec 0x%08x", type_token);
6864 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6869 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
6872 return g_strdup_printf ("DynamicAssembly %s", image->name);
6874 switch (type_token & 0xff000000){
6875 case MONO_TOKEN_TYPE_DEF:
6876 if (image->assembly)
6877 return mono_stringify_assembly_name (&image->assembly->aname);
6878 else if (image->assembly_name)
6879 return g_strdup (image->assembly_name);
6880 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
6881 case MONO_TOKEN_TYPE_REF: {
6883 MonoAssemblyName aname;
6884 guint32 cols [MONO_TYPEREF_SIZE];
6885 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6886 guint32 idx = mono_metadata_token_index (type_token);
6889 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6891 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
6892 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6893 mono_error_cleanup (&error);
6896 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
6898 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
6899 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
6900 case MONO_RESOLTION_SCOPE_MODULE:
6902 return g_strdup ("");
6903 case MONO_RESOLTION_SCOPE_MODULEREF:
6905 return g_strdup ("");
6906 case MONO_RESOLTION_SCOPE_TYPEREF:
6908 return g_strdup ("");
6909 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
6910 mono_assembly_get_assemblyref (image, idx - 1, &aname);
6911 return mono_stringify_assembly_name (&aname);
6913 g_assert_not_reached ();
6917 case MONO_TOKEN_TYPE_SPEC:
6919 return g_strdup ("");
6921 g_assert_not_reached ();
6928 * mono_class_get_full:
6929 * @image: the image where the class resides
6930 * @type_token: the token for the class
6931 * @context: the generic context used to evaluate generic instantiations in
6933 * Returns: the MonoClass that represents @type_token in @image
6936 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
6939 MonoClass *class = NULL;
6941 if (image->dynamic) {
6942 int table = mono_metadata_token_table (type_token);
6944 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
6945 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
6948 return mono_lookup_dynamic_token (image, type_token, context);
6951 switch (type_token & 0xff000000){
6952 case MONO_TOKEN_TYPE_DEF:
6953 class = mono_class_create_from_typedef (image, type_token);
6955 case MONO_TOKEN_TYPE_REF:
6956 class = mono_class_from_typeref (image, type_token);
6958 case MONO_TOKEN_TYPE_SPEC:
6959 class = mono_class_create_from_typespec (image, type_token, context, &error);
6960 if (!mono_error_ok (&error)) {
6961 /*FIXME don't swallow the error message*/
6962 mono_error_cleanup (&error);
6966 g_warning ("unknown token type %x", type_token & 0xff000000);
6967 g_assert_not_reached ();
6971 char *name = mono_class_name_from_token (image, type_token);
6972 char *assembly = mono_assembly_name_from_token (image, type_token);
6973 mono_loader_set_error_type_load (name, assembly);
6983 * mono_type_get_full:
6984 * @image: the image where the type resides
6985 * @type_token: the token for the type
6986 * @context: the generic context used to evaluate generic instantiations in
6988 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
6990 * Returns: the MonoType that represents @type_token in @image
6993 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
6996 MonoType *type = NULL;
6997 gboolean inflated = FALSE;
6999 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7001 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7003 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7004 MonoClass *class = mono_class_get_full (image, type_token, context);
7005 return class ? mono_class_get_type (class) : NULL;
7008 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7010 if (!mono_error_ok (&error)) {
7011 /*FIXME don't swalloc the error message.*/
7012 char *name = mono_class_name_from_token (image, type_token);
7013 char *assembly = mono_assembly_name_from_token (image, type_token);
7015 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7017 mono_error_cleanup (&error);
7018 mono_loader_set_error_type_load (name, assembly);
7023 MonoType *tmp = type;
7024 type = mono_class_get_type (mono_class_from_mono_type (type));
7025 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7026 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7027 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7029 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7031 if (type->type != tmp->type)
7034 mono_metadata_free_type (tmp);
7041 mono_class_get (MonoImage *image, guint32 type_token)
7043 return mono_class_get_full (image, type_token, NULL);
7047 * mono_image_init_name_cache:
7049 * Initializes the class name cache stored in image->name_cache.
7051 * LOCKING: Acquires the corresponding image lock.
7054 mono_image_init_name_cache (MonoImage *image)
7056 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7057 guint32 cols [MONO_TYPEDEF_SIZE];
7060 guint32 i, visib, nspace_index;
7061 GHashTable *name_cache2, *nspace_table;
7063 mono_image_lock (image);
7065 if (image->name_cache) {
7066 mono_image_unlock (image);
7070 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7072 if (image->dynamic) {
7073 mono_image_unlock (image);
7077 /* Temporary hash table to avoid lookups in the nspace_table */
7078 name_cache2 = g_hash_table_new (NULL, NULL);
7080 for (i = 1; i <= t->rows; ++i) {
7081 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7082 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7084 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7085 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7087 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7089 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7090 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7092 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7093 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7094 if (!nspace_table) {
7095 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7096 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7097 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7100 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7103 /* Load type names from EXPORTEDTYPES table */
7105 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7106 guint32 cols [MONO_EXP_TYPE_SIZE];
7109 for (i = 0; i < t->rows; ++i) {
7110 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7111 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7112 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7114 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7115 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7116 if (!nspace_table) {
7117 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7118 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7119 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7122 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7126 g_hash_table_destroy (name_cache2);
7127 mono_image_unlock (image);
7130 /*FIXME Only dynamic assemblies should allow this operation.*/
7132 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7133 const char *name, guint32 index)
7135 GHashTable *nspace_table;
7136 GHashTable *name_cache;
7139 mono_image_lock (image);
7141 if (!image->name_cache)
7142 mono_image_init_name_cache (image);
7144 name_cache = image->name_cache;
7145 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7146 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7147 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7150 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7151 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7153 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7155 mono_image_unlock (image);
7164 find_nocase (gpointer key, gpointer value, gpointer user_data)
7166 char *name = (char*)key;
7167 FindUserData *data = (FindUserData*)user_data;
7169 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7170 data->value = value;
7174 * mono_class_from_name_case:
7175 * @image: The MonoImage where the type is looked up in
7176 * @name_space: the type namespace
7177 * @name: the type short name.
7179 * Obtains a MonoClass with a given namespace and a given name which
7180 * is located in the given MonoImage. The namespace and name
7181 * lookups are case insensitive.
7184 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7186 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7187 guint32 cols [MONO_TYPEDEF_SIZE];
7192 if (image->dynamic) {
7194 FindUserData user_data;
7196 mono_image_lock (image);
7198 if (!image->name_cache)
7199 mono_image_init_name_cache (image);
7201 user_data.key = name_space;
7202 user_data.value = NULL;
7203 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7205 if (user_data.value) {
7206 GHashTable *nspace_table = (GHashTable*)user_data.value;
7208 user_data.key = name;
7209 user_data.value = NULL;
7211 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7213 if (user_data.value)
7214 token = GPOINTER_TO_UINT (user_data.value);
7217 mono_image_unlock (image);
7220 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7226 /* add a cache if needed */
7227 for (i = 1; i <= t->rows; ++i) {
7228 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7229 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7231 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7232 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7234 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7236 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7237 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7238 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7239 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7245 return_nested_in (MonoClass *class, char *nested)
7248 char *s = strchr (nested, '/');
7249 gpointer iter = NULL;
7256 while ((found = mono_class_get_nested_types (class, &iter))) {
7257 if (strcmp (found->name, nested) == 0) {
7259 return return_nested_in (found, s);
7267 search_modules (MonoImage *image, const char *name_space, const char *name)
7269 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7270 MonoImage *file_image;
7275 * The EXPORTEDTYPES table only contains public types, so have to search the
7277 * Note: image->modules contains the contents of the MODULEREF table, while
7278 * the real module list is in the FILE table.
7280 for (i = 0; i < file_table->rows; i++) {
7281 guint32 cols [MONO_FILE_SIZE];
7282 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7283 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7286 file_image = mono_image_load_file_for_image (image, i + 1);
7288 class = mono_class_from_name (file_image, name_space, name);
7298 * mono_class_from_name:
7299 * @image: The MonoImage where the type is looked up in
7300 * @name_space: the type namespace
7301 * @name: the type short name.
7303 * Obtains a MonoClass with a given namespace and a given name which
7304 * is located in the given MonoImage.
7307 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7309 GHashTable *nspace_table;
7310 MonoImage *loaded_image;
7317 if ((nested = strchr (name, '/'))) {
7318 int pos = nested - name;
7319 int len = strlen (name);
7322 memcpy (buf, name, len + 1);
7324 nested = buf + pos + 1;
7328 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7329 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7330 gboolean res = get_class_from_name (image, name_space, name, &class);
7333 class = search_modules (image, name_space, name);
7335 return class ? return_nested_in (class, nested) : NULL;
7341 mono_image_lock (image);
7343 if (!image->name_cache)
7344 mono_image_init_name_cache (image);
7346 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7349 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7351 mono_image_unlock (image);
7353 if (!token && image->dynamic && image->modules) {
7354 /* Search modules as well */
7355 for (i = 0; i < image->module_count; ++i) {
7356 MonoImage *module = image->modules [i];
7358 class = mono_class_from_name (module, name_space, name);
7365 class = search_modules (image, name_space, name);
7373 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7374 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7375 guint32 cols [MONO_EXP_TYPE_SIZE];
7378 idx = mono_metadata_token_index (token);
7380 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7382 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7383 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7384 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7387 class = mono_class_from_name (loaded_image, name_space, name);
7389 return return_nested_in (class, nested);
7391 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7392 guint32 assembly_idx;
7394 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7396 mono_assembly_load_reference (image, assembly_idx - 1);
7397 g_assert (image->references [assembly_idx - 1]);
7398 if (image->references [assembly_idx - 1] == (gpointer)-1)
7401 /* FIXME: Cycle detection */
7402 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7404 g_error ("not yet implemented");
7408 token = MONO_TOKEN_TYPE_DEF | token;
7410 class = mono_class_get (image, token);
7412 return return_nested_in (class, nested);
7416 /*FIXME test for interfaces with variant generic arguments*/
7418 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7419 gboolean check_interfaces)
7421 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7422 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7424 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7427 for (i = 0; i < klass->interface_count; i ++) {
7428 MonoClass *ic = klass->interfaces [i];
7433 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7438 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7441 if (klassc == mono_defaults.object_class)
7448 mono_type_is_generic_argument (MonoType *type)
7450 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7454 mono_class_has_variant_generic_params (MonoClass *klass)
7457 MonoGenericContainer *container;
7459 if (!klass->generic_class)
7462 container = klass->generic_class->container_class->generic_container;
7464 for (i = 0; i < container->type_argc; ++i)
7465 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7472 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7474 if (target == candidate)
7477 if (check_for_reference_conv &&
7478 mono_type_is_generic_argument (&target->byval_arg) &&
7479 mono_type_is_generic_argument (&candidate->byval_arg)) {
7480 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7481 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7483 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7486 if (!mono_class_is_assignable_from (target, candidate))
7492 * @container the generic container from the GTD
7493 * @klass: the class to be assigned to
7494 * @oklass: the source class
7496 * Both klass and oklass must be instances of the same generic interface.
7497 * Return true if @klass can be assigned to a @klass variable
7500 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7503 MonoType **klass_argv, **oklass_argv;
7504 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7505 MonoGenericContainer *container = klass_gtd->generic_container;
7507 if (klass == oklass)
7510 /*Viable candidates are instances of the same generic interface*/
7511 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7514 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7515 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7517 for (j = 0; j < container->type_argc; ++j) {
7518 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7519 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7521 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7525 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7526 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7528 if (param1_class != param2_class) {
7529 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7530 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7532 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7533 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7543 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7545 MonoGenericParam *gparam, *ogparam;
7546 MonoGenericParamInfo *tinfo, *cinfo;
7547 MonoClass **candidate_class;
7548 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7551 if (target == candidate)
7553 if (target->byval_arg.type != candidate->byval_arg.type)
7556 gparam = target->byval_arg.data.generic_param;
7557 ogparam = candidate->byval_arg.data.generic_param;
7558 tinfo = mono_generic_param_info (gparam);
7559 cinfo = mono_generic_param_info (ogparam);
7561 class_constraint_satisfied = FALSE;
7562 valuetype_constraint_satisfied = FALSE;
7564 /*candidate must have a super set of target's special constraints*/
7565 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7566 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7568 if (cinfo->constraints) {
7569 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7570 MonoClass *cc = *candidate_class;
7572 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7573 class_constraint_satisfied = TRUE;
7574 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7575 valuetype_constraint_satisfied = TRUE;
7578 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7579 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7581 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7583 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7585 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7586 valuetype_constraint_satisfied)) {
7591 /*candidate type constraints must be a superset of target's*/
7592 if (tinfo->constraints) {
7593 MonoClass **target_class;
7594 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7595 MonoClass *tc = *target_class;
7598 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7599 * check it's constraints since it satisfy the constraint by itself.
7601 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7604 if (!cinfo->constraints)
7607 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7608 MonoClass *cc = *candidate_class;
7610 if (mono_class_is_assignable_from (tc, cc))
7614 * This happens when we have the following:
7616 * Bar<K> where K : IFace
7617 * Foo<T, U> where T : U where U : IFace
7619 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7622 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7623 if (mono_gparam_is_assignable_from (target, cc))
7627 if (!*candidate_class)
7632 /*candidate itself must have a constraint that satisfy target*/
7633 if (cinfo->constraints) {
7634 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7635 MonoClass *cc = *candidate_class;
7636 if (mono_class_is_assignable_from (target, cc))
7644 * mono_class_is_assignable_from:
7645 * @klass: the class to be assigned to
7646 * @oklass: the source class
7648 * Return: true if an instance of object oklass can be assigned to an
7649 * instance of object @klass
7652 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7654 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7656 mono_class_init (klass);
7658 if (!oklass->inited)
7659 mono_class_init (oklass);
7661 if (klass->exception_type || oklass->exception_type)
7664 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7665 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7667 return mono_gparam_is_assignable_from (klass, oklass);
7670 if (MONO_CLASS_IS_INTERFACE (klass)) {
7671 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7672 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7673 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7677 for (i = 0; constraints [i]; ++i) {
7678 if (mono_class_is_assignable_from (klass, constraints [i]))
7686 /* interface_offsets might not be set for dynamic classes */
7687 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7689 * oklass might be a generic type parameter but they have
7690 * interface_offsets set.
7692 return mono_reflection_call_is_assignable_to (oklass, klass);
7693 if (!oklass->interface_bitmap)
7694 /* Happens with generic instances of not-yet created dynamic types */
7696 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7699 if (mono_class_has_variant_generic_params (klass)) {
7702 mono_class_setup_interfaces (oklass, &error);
7703 if (!mono_error_ok (&error)) {
7704 mono_error_cleanup (&error);
7708 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7709 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7710 MonoClass *iface = oklass->interfaces_packed [i];
7712 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7717 } else if (klass->delegate) {
7718 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7720 }else if (klass->rank) {
7721 MonoClass *eclass, *eoclass;
7723 if (oklass->rank != klass->rank)
7726 /* vectors vs. one dimensional arrays */
7727 if (oklass->byval_arg.type != klass->byval_arg.type)
7730 eclass = klass->cast_class;
7731 eoclass = oklass->cast_class;
7734 * a is b does not imply a[] is b[] when a is a valuetype, and
7735 * b is a reference type.
7738 if (eoclass->valuetype) {
7739 if ((eclass == mono_defaults.enum_class) ||
7740 (eclass == mono_defaults.enum_class->parent) ||
7741 (eclass == mono_defaults.object_class))
7745 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7746 } else if (mono_class_is_nullable (klass)) {
7747 if (mono_class_is_nullable (oklass))
7748 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7750 return mono_class_is_assignable_from (klass->cast_class, oklass);
7751 } else if (klass == mono_defaults.object_class)
7754 return mono_class_has_parent (oklass, klass);
7757 /*Check if @oklass is variant compatible with @klass.*/
7759 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7762 MonoType **klass_argv, **oklass_argv;
7763 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7764 MonoGenericContainer *container = klass_gtd->generic_container;
7766 /*Viable candidates are instances of the same generic interface*/
7767 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7770 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7771 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7773 for (j = 0; j < container->type_argc; ++j) {
7774 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7775 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7777 if (param1_class->valuetype != param2_class->valuetype)
7781 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7782 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7784 if (param1_class != param2_class) {
7785 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7786 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7788 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7789 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7797 /*Check if @candidate implements the interface @target*/
7799 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7803 gboolean is_variant = mono_class_has_variant_generic_params (target);
7805 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7806 if (mono_class_is_variant_compatible_slow (target, candidate))
7811 if (candidate == target)
7814 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7815 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7816 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7818 if (tb && tb->interfaces) {
7819 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7820 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7821 MonoClass *iface_class;
7823 /* we can't realize the type here since it can do pretty much anything. */
7826 iface_class = mono_class_from_mono_type (iface->type);
7827 if (iface_class == target)
7829 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
7831 if (mono_class_implement_interface_slow (target, iface_class))
7836 /*setup_interfaces don't mono_class_init anything*/
7837 mono_class_setup_interfaces (candidate, &error);
7838 if (!mono_error_ok (&error)) {
7839 mono_error_cleanup (&error);
7843 for (i = 0; i < candidate->interface_count; ++i) {
7844 if (candidate->interfaces [i] == target)
7847 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
7850 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
7854 candidate = candidate->parent;
7855 } while (candidate);
7861 * Check if @oklass can be assigned to @klass.
7862 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
7865 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
7867 if (candidate == target)
7869 if (target == mono_defaults.object_class)
7872 if (mono_class_has_parent (candidate, target))
7875 /*If target is not an interface there is no need to check them.*/
7876 if (MONO_CLASS_IS_INTERFACE (target))
7877 return mono_class_implement_interface_slow (target, candidate);
7879 if (target->delegate && mono_class_has_variant_generic_params (target))
7880 return mono_class_is_variant_compatible (target, candidate, FALSE);
7882 /*FIXME properly handle nullables and arrays */
7883 /*FIXME properly handle (M)VAR */
7888 * mono_class_get_cctor:
7889 * @klass: A MonoClass pointer
7891 * Returns: the static constructor of @klass if it exists, NULL otherwise.
7894 mono_class_get_cctor (MonoClass *klass)
7896 MonoCachedClassInfo cached_info;
7898 if (klass->image->dynamic) {
7900 * has_cctor is not set for these classes because mono_class_init () is
7903 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
7906 if (!klass->has_cctor)
7909 if (mono_class_get_cached_class_info (klass, &cached_info))
7910 return mono_get_method (klass->image, cached_info.cctor_token, klass);
7912 if (klass->generic_class && !klass->methods)
7913 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
7915 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
7919 * mono_class_get_finalizer:
7920 * @klass: The MonoClass pointer
7922 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
7925 mono_class_get_finalizer (MonoClass *klass)
7927 MonoCachedClassInfo cached_info;
7930 mono_class_init (klass);
7931 if (!mono_class_has_finalizer (klass))
7934 if (mono_class_get_cached_class_info (klass, &cached_info))
7935 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
7937 mono_class_setup_vtable (klass);
7938 return klass->vtable [finalize_slot];
7943 * mono_class_needs_cctor_run:
7944 * @klass: the MonoClass pointer
7945 * @caller: a MonoMethod describing the caller
7947 * Determines whenever the class has a static constructor and whenever it
7948 * needs to be called when executing CALLER.
7951 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
7955 method = mono_class_get_cctor (klass);
7957 return (method == caller) ? FALSE : TRUE;
7963 * mono_class_array_element_size:
7966 * Returns: the number of bytes an element of type @klass
7967 * uses when stored into an array.
7970 mono_class_array_element_size (MonoClass *klass)
7972 MonoType *type = &klass->byval_arg;
7975 switch (type->type) {
7978 case MONO_TYPE_BOOLEAN:
7982 case MONO_TYPE_CHAR:
7991 case MONO_TYPE_CLASS:
7992 case MONO_TYPE_STRING:
7993 case MONO_TYPE_OBJECT:
7994 case MONO_TYPE_SZARRAY:
7995 case MONO_TYPE_ARRAY:
7997 case MONO_TYPE_MVAR:
7998 return sizeof (gpointer);
8003 case MONO_TYPE_VALUETYPE:
8004 if (type->data.klass->enumtype) {
8005 type = mono_class_enum_basetype (type->data.klass);
8006 klass = klass->element_class;
8009 return mono_class_instance_size (klass) - sizeof (MonoObject);
8010 case MONO_TYPE_GENERICINST:
8011 type = &type->data.generic_class->container_class->byval_arg;
8014 case MONO_TYPE_VOID:
8018 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8024 * mono_array_element_size:
8025 * @ac: pointer to a #MonoArrayClass
8027 * Returns: the size of single array element.
8030 mono_array_element_size (MonoClass *ac)
8032 g_assert (ac->rank);
8033 return ac->sizes.element_size;
8037 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8038 MonoGenericContext *context)
8040 if (image->dynamic) {
8041 MonoClass *tmp_handle_class;
8042 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8044 g_assert (tmp_handle_class);
8046 *handle_class = tmp_handle_class;
8048 if (tmp_handle_class == mono_defaults.typehandle_class)
8049 return &((MonoClass*)obj)->byval_arg;
8054 switch (token & 0xff000000) {
8055 case MONO_TOKEN_TYPE_DEF:
8056 case MONO_TOKEN_TYPE_REF:
8057 case MONO_TOKEN_TYPE_SPEC: {
8060 *handle_class = mono_defaults.typehandle_class;
8061 type = mono_type_get_full (image, token, context);
8064 mono_class_init (mono_class_from_mono_type (type));
8065 /* We return a MonoType* as handle */
8068 case MONO_TOKEN_FIELD_DEF: {
8070 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8074 *handle_class = mono_defaults.fieldhandle_class;
8075 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8078 mono_class_init (class);
8079 return mono_class_get_field (class, token);
8081 case MONO_TOKEN_METHOD_DEF:
8082 case MONO_TOKEN_METHOD_SPEC: {
8084 meth = mono_get_method_full (image, token, NULL, context);
8086 *handle_class = mono_defaults.methodhandle_class;
8089 case MONO_TOKEN_MEMBER_REF: {
8090 guint32 cols [MONO_MEMBERREF_SIZE];
8092 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8093 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8094 mono_metadata_decode_blob_size (sig, &sig);
8095 if (*sig == 0x6) { /* it's a field */
8097 MonoClassField *field;
8098 field = mono_field_from_token (image, token, &klass, context);
8100 *handle_class = mono_defaults.fieldhandle_class;
8104 meth = mono_get_method_full (image, token, NULL, context);
8106 *handle_class = mono_defaults.methodhandle_class;
8111 g_warning ("Unknown token 0x%08x in ldtoken", token);
8118 * This function might need to call runtime functions so it can't be part
8119 * of the metadata library.
8121 static MonoLookupDynamicToken lookup_dynamic = NULL;
8124 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8126 lookup_dynamic = func;
8130 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8132 MonoClass *handle_class;
8134 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8138 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8140 return lookup_dynamic (image, token, valid_token, handle_class, context);
8143 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8146 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8148 get_cached_class_info = func;
8152 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8154 if (!get_cached_class_info)
8157 return get_cached_class_info (klass, res);
8161 mono_install_get_class_from_name (MonoGetClassFromName func)
8163 get_class_from_name = func;
8167 mono_class_get_image (MonoClass *klass)
8169 return klass->image;
8173 * mono_class_get_element_class:
8174 * @klass: the MonoClass to act on
8176 * Returns: the element class of an array or an enumeration.
8179 mono_class_get_element_class (MonoClass *klass)
8181 return klass->element_class;
8185 * mono_class_is_valuetype:
8186 * @klass: the MonoClass to act on
8188 * Returns: true if the MonoClass represents a ValueType.
8191 mono_class_is_valuetype (MonoClass *klass)
8193 return klass->valuetype;
8197 * mono_class_is_enum:
8198 * @klass: the MonoClass to act on
8200 * Returns: true if the MonoClass represents an enumeration.
8203 mono_class_is_enum (MonoClass *klass)
8205 return klass->enumtype;
8209 * mono_class_enum_basetype:
8210 * @klass: the MonoClass to act on
8212 * Returns: the underlying type representation for an enumeration.
8215 mono_class_enum_basetype (MonoClass *klass)
8217 if (klass->element_class == klass)
8218 /* SRE or broken types */
8221 return &klass->element_class->byval_arg;
8225 * mono_class_get_parent
8226 * @klass: the MonoClass to act on
8228 * Returns: the parent class for this class.
8231 mono_class_get_parent (MonoClass *klass)
8233 return klass->parent;
8237 * mono_class_get_nesting_type;
8238 * @klass: the MonoClass to act on
8240 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8243 mono_class_get_nesting_type (MonoClass *klass)
8245 return klass->nested_in;
8249 * mono_class_get_rank:
8250 * @klass: the MonoClass to act on
8252 * Returns: the rank for the array (the number of dimensions).
8255 mono_class_get_rank (MonoClass *klass)
8261 * mono_class_get_flags:
8262 * @klass: the MonoClass to act on
8264 * The type flags from the TypeDef table from the metadata.
8265 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8268 * Returns: the flags from the TypeDef table.
8271 mono_class_get_flags (MonoClass *klass)
8273 return klass->flags;
8277 * mono_class_get_name
8278 * @klass: the MonoClass to act on
8280 * Returns: the name of the class.
8283 mono_class_get_name (MonoClass *klass)
8289 * mono_class_get_namespace:
8290 * @klass: the MonoClass to act on
8292 * Returns: the namespace of the class.
8295 mono_class_get_namespace (MonoClass *klass)
8297 return klass->name_space;
8301 * mono_class_get_type:
8302 * @klass: the MonoClass to act on
8304 * This method returns the internal Type representation for the class.
8306 * Returns: the MonoType from the class.
8309 mono_class_get_type (MonoClass *klass)
8311 return &klass->byval_arg;
8315 * mono_class_get_type_token
8316 * @klass: the MonoClass to act on
8318 * This method returns type token for the class.
8320 * Returns: the type token for the class.
8323 mono_class_get_type_token (MonoClass *klass)
8325 return klass->type_token;
8329 * mono_class_get_byref_type:
8330 * @klass: the MonoClass to act on
8335 mono_class_get_byref_type (MonoClass *klass)
8337 return &klass->this_arg;
8341 * mono_class_num_fields:
8342 * @klass: the MonoClass to act on
8344 * Returns: the number of static and instance fields in the class.
8347 mono_class_num_fields (MonoClass *klass)
8349 return klass->field.count;
8353 * mono_class_num_methods:
8354 * @klass: the MonoClass to act on
8356 * Returns: the number of methods in the class.
8359 mono_class_num_methods (MonoClass *klass)
8361 return klass->method.count;
8365 * mono_class_num_properties
8366 * @klass: the MonoClass to act on
8368 * Returns: the number of properties in the class.
8371 mono_class_num_properties (MonoClass *klass)
8373 mono_class_setup_properties (klass);
8375 return klass->ext->property.count;
8379 * mono_class_num_events:
8380 * @klass: the MonoClass to act on
8382 * Returns: the number of events in the class.
8385 mono_class_num_events (MonoClass *klass)
8387 mono_class_setup_events (klass);
8389 return klass->ext->event.count;
8393 * mono_class_get_fields:
8394 * @klass: the MonoClass to act on
8396 * This routine is an iterator routine for retrieving the fields in a class.
8398 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8399 * iterate over all of the elements. When no more values are
8400 * available, the return value is NULL.
8402 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8405 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8407 MonoClassField* field;
8411 mono_class_setup_fields_locking (klass);
8412 if (klass->exception_type)
8414 /* start from the first */
8415 if (klass->field.count) {
8416 return *iter = &klass->fields [0];
8424 if (field < &klass->fields [klass->field.count]) {
8425 return *iter = field;
8431 * mono_class_get_methods
8432 * @klass: the MonoClass to act on
8434 * This routine is an iterator routine for retrieving the fields in a class.
8436 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8437 * iterate over all of the elements. When no more values are
8438 * available, the return value is NULL.
8440 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8443 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8445 MonoMethod** method;
8449 mono_class_setup_methods (klass);
8452 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8453 * FIXME we should better report this error to the caller
8455 if (!klass->methods)
8457 /* start from the first */
8458 if (klass->method.count) {
8459 *iter = &klass->methods [0];
8460 return klass->methods [0];
8468 if (method < &klass->methods [klass->method.count]) {
8476 * mono_class_get_virtual_methods:
8478 * Iterate over the virtual methods of KLASS.
8480 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8483 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8485 MonoMethod** method;
8488 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8490 mono_class_setup_methods (klass);
8492 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8493 * FIXME we should better report this error to the caller
8495 if (!klass->methods)
8497 /* start from the first */
8498 method = &klass->methods [0];
8503 while (method < &klass->methods [klass->method.count]) {
8504 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8508 if (method < &klass->methods [klass->method.count]) {
8515 /* Search directly in metadata to avoid calling setup_methods () */
8516 MonoMethod *res = NULL;
8522 start_index = GPOINTER_TO_UINT (*iter);
8525 for (i = start_index; i < klass->method.count; ++i) {
8528 /* class->method.first points into the methodptr table */
8529 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8531 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8535 if (i < klass->method.count) {
8536 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8537 /* Add 1 here so the if (*iter) check fails */
8538 *iter = GUINT_TO_POINTER (i + 1);
8547 * mono_class_get_properties:
8548 * @klass: the MonoClass to act on
8550 * This routine is an iterator routine for retrieving the properties in a class.
8552 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8553 * iterate over all of the elements. When no more values are
8554 * available, the return value is NULL.
8556 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8559 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8561 MonoProperty* property;
8565 mono_class_setup_properties (klass);
8566 /* start from the first */
8567 if (klass->ext->property.count) {
8568 return *iter = &klass->ext->properties [0];
8576 if (property < &klass->ext->properties [klass->ext->property.count]) {
8577 return *iter = property;
8583 * mono_class_get_events:
8584 * @klass: the MonoClass to act on
8586 * This routine is an iterator routine for retrieving the properties in a class.
8588 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8589 * iterate over all of the elements. When no more values are
8590 * available, the return value is NULL.
8592 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8595 mono_class_get_events (MonoClass* klass, gpointer *iter)
8601 mono_class_setup_events (klass);
8602 /* start from the first */
8603 if (klass->ext->event.count) {
8604 return *iter = &klass->ext->events [0];
8612 if (event < &klass->ext->events [klass->ext->event.count]) {
8613 return *iter = event;
8619 * mono_class_get_interfaces
8620 * @klass: the MonoClass to act on
8622 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8624 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8625 * iterate over all of the elements. When no more values are
8626 * available, the return value is NULL.
8628 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8631 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8639 mono_class_init (klass);
8640 if (!klass->interfaces_inited) {
8641 mono_class_setup_interfaces (klass, &error);
8642 if (!mono_error_ok (&error)) {
8643 mono_error_cleanup (&error);
8647 /* start from the first */
8648 if (klass->interface_count) {
8649 *iter = &klass->interfaces [0];
8650 return klass->interfaces [0];
8658 if (iface < &klass->interfaces [klass->interface_count]) {
8666 * mono_class_get_nested_types
8667 * @klass: the MonoClass to act on
8669 * This routine is an iterator routine for retrieving the nested types of a class.
8670 * This works only if @klass is non-generic, or a generic type definition.
8672 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8673 * iterate over all of the elements. When no more values are
8674 * available, the return value is NULL.
8676 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8679 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8686 if (!klass->nested_classes_inited) {
8687 if (!klass->type_token)
8688 klass->nested_classes_inited = TRUE;
8689 mono_loader_lock ();
8690 if (!klass->nested_classes_inited) {
8691 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8694 guint32 cols [MONO_NESTED_CLASS_SIZE];
8695 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8696 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
8698 mono_loader_clear_error ();
8699 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8702 mono_class_alloc_ext (klass);
8703 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8705 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8708 mono_memory_barrier ();
8709 klass->nested_classes_inited = TRUE;
8710 mono_loader_unlock ();
8714 /* start from the first */
8715 if (klass->ext && klass->ext->nested_classes) {
8716 *iter = klass->ext->nested_classes;
8717 return klass->ext->nested_classes->data;
8719 /* no nested types */
8733 * mono_field_get_name:
8734 * @field: the MonoClassField to act on
8736 * Returns: the name of the field.
8739 mono_field_get_name (MonoClassField *field)
8745 * mono_field_get_type:
8746 * @field: the MonoClassField to act on
8748 * Returns: MonoType of the field.
8751 mono_field_get_type (MonoClassField *field)
8754 MonoType *type = mono_field_get_type_checked (field, &error);
8755 if (!mono_error_ok (&error)) {
8756 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8757 mono_error_cleanup (&error);
8764 * mono_field_get_type_checked:
8765 * @field: the MonoClassField to act on
8766 * @error: used to return any erro found while retrieving @field type
8768 * Returns: MonoType of the field.
8771 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8773 mono_error_init (error);
8775 mono_field_resolve_type (field, error);
8780 * mono_field_get_parent:
8781 * @field: the MonoClassField to act on
8783 * Returns: MonoClass where the field was defined.
8786 mono_field_get_parent (MonoClassField *field)
8788 return field->parent;
8792 * mono_field_get_flags;
8793 * @field: the MonoClassField to act on
8795 * The metadata flags for a field are encoded using the
8796 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8798 * Returns: the flags for the field.
8801 mono_field_get_flags (MonoClassField *field)
8804 return mono_field_resolve_flags (field);
8805 return field->type->attrs;
8809 * mono_field_get_offset;
8810 * @field: the MonoClassField to act on
8812 * Returns: the field offset.
8815 mono_field_get_offset (MonoClassField *field)
8817 return field->offset;
8821 mono_field_get_rva (MonoClassField *field)
8825 MonoClass *klass = field->parent;
8827 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
8829 if (!klass->ext || !klass->ext->field_def_values) {
8830 mono_loader_lock ();
8831 mono_class_alloc_ext (klass);
8832 if (!klass->ext->field_def_values)
8833 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
8834 mono_loader_unlock ();
8837 field_index = mono_field_get_index (field);
8839 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
8840 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
8842 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
8843 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
8846 return klass->ext->field_def_values [field_index].data;
8850 * mono_field_get_data;
8851 * @field: the MonoClassField to act on
8853 * Returns: pointer to the metadata constant value or to the field
8854 * data if it has an RVA flag.
8857 mono_field_get_data (MonoClassField *field)
8859 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
8860 MonoTypeEnum def_type;
8862 return mono_class_get_field_default_value (field, &def_type);
8863 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
8864 return mono_field_get_rva (field);
8871 * mono_property_get_name:
8872 * @prop: the MonoProperty to act on
8874 * Returns: the name of the property
8877 mono_property_get_name (MonoProperty *prop)
8883 * mono_property_get_set_method
8884 * @prop: the MonoProperty to act on.
8886 * Returns: the setter method of the property (A MonoMethod)
8889 mono_property_get_set_method (MonoProperty *prop)
8895 * mono_property_get_get_method
8896 * @prop: the MonoProperty to act on.
8898 * Returns: the setter method of the property (A MonoMethod)
8901 mono_property_get_get_method (MonoProperty *prop)
8907 * mono_property_get_parent:
8908 * @prop: the MonoProperty to act on.
8910 * Returns: the MonoClass where the property was defined.
8913 mono_property_get_parent (MonoProperty *prop)
8915 return prop->parent;
8919 * mono_property_get_flags:
8920 * @prop: the MonoProperty to act on.
8922 * The metadata flags for a property are encoded using the
8923 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8925 * Returns: the flags for the property.
8928 mono_property_get_flags (MonoProperty *prop)
8934 * mono_event_get_name:
8935 * @event: the MonoEvent to act on
8937 * Returns: the name of the event.
8940 mono_event_get_name (MonoEvent *event)
8946 * mono_event_get_add_method:
8947 * @event: The MonoEvent to act on.
8949 * Returns: the @add' method for the event (a MonoMethod).
8952 mono_event_get_add_method (MonoEvent *event)
8958 * mono_event_get_remove_method:
8959 * @event: The MonoEvent to act on.
8961 * Returns: the @remove method for the event (a MonoMethod).
8964 mono_event_get_remove_method (MonoEvent *event)
8966 return event->remove;
8970 * mono_event_get_raise_method:
8971 * @event: The MonoEvent to act on.
8973 * Returns: the @raise method for the event (a MonoMethod).
8976 mono_event_get_raise_method (MonoEvent *event)
8978 return event->raise;
8982 * mono_event_get_parent:
8983 * @event: the MonoEvent to act on.
8985 * Returns: the MonoClass where the event is defined.
8988 mono_event_get_parent (MonoEvent *event)
8990 return event->parent;
8994 * mono_event_get_flags
8995 * @event: the MonoEvent to act on.
8997 * The metadata flags for an event are encoded using the
8998 * EVENT_* constants. See the tabledefs.h file for details.
9000 * Returns: the flags for the event.
9003 mono_event_get_flags (MonoEvent *event)
9005 return event->attrs;
9009 * mono_class_get_method_from_name:
9010 * @klass: where to look for the method
9011 * @name_space: name of the method
9012 * @param_count: number of parameters. -1 for any number.
9014 * Obtains a MonoMethod with a given name and number of parameters.
9015 * It only works if there are no multiple signatures for any given method name.
9018 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9020 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9024 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9026 MonoMethod *res = NULL;
9029 /* Search directly in the metadata to avoid calling setup_methods () */
9030 for (i = 0; i < klass->method.count; ++i) {
9031 guint32 cols [MONO_METHOD_SIZE];
9033 MonoMethodSignature *sig;
9035 /* class->method.first points into the methodptr table */
9036 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9038 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9039 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9040 if (param_count == -1) {
9044 sig = mono_method_signature (method);
9045 if (sig && sig->param_count == param_count) {
9056 * mono_class_get_method_from_name_flags:
9057 * @klass: where to look for the method
9058 * @name_space: name of the method
9059 * @param_count: number of parameters. -1 for any number.
9060 * @flags: flags which must be set in the method
9062 * Obtains a MonoMethod with a given name and number of parameters.
9063 * It only works if there are no multiple signatures for any given method name.
9066 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9068 MonoMethod *res = NULL;
9071 mono_class_init (klass);
9073 if (klass->generic_class && !klass->methods) {
9074 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9076 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9080 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9081 mono_class_setup_methods (klass);
9083 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9084 See mono/tests/array_load_exception.il
9085 FIXME we should better report this error to the caller
9087 if (!klass->methods)
9089 for (i = 0; i < klass->method.count; ++i) {
9090 MonoMethod *method = klass->methods [i];
9092 if (method->name[0] == name [0] &&
9093 !strcmp (name, method->name) &&
9094 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9095 ((method->flags & flags) == flags)) {
9102 res = find_method_in_metadata (klass, name, param_count, flags);
9109 * mono_class_set_failure:
9110 * @klass: class in which the failure was detected
9111 * @ex_type: the kind of exception/error to be thrown (later)
9112 * @ex_data: exception data (specific to each type of exception/error)
9114 * Keep a detected failure informations in the class for later processing.
9115 * Note that only the first failure is kept.
9117 * LOCKING: Acquires the loader lock.
9120 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9122 if (klass->exception_type)
9125 mono_loader_lock ();
9126 klass->exception_type = ex_type;
9128 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9129 mono_loader_unlock ();
9135 * mono_class_get_exception_data:
9137 * Return the exception_data property of KLASS.
9139 * LOCKING: Acquires the loader lock.
9142 mono_class_get_exception_data (MonoClass *klass)
9144 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9148 * mono_classes_init:
9150 * Initialize the resources used by this module.
9153 mono_classes_init (void)
9155 mono_counters_register ("Inflated methods size",
9156 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9157 mono_counters_register ("Inflated classes",
9158 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9159 mono_counters_register ("Inflated classes size",
9160 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9161 mono_counters_register ("MonoClass size",
9162 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9163 mono_counters_register ("MonoClassExt size",
9164 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9168 * mono_classes_cleanup:
9170 * Free the resources used by this module.
9173 mono_classes_cleanup (void)
9175 if (global_interface_bitset)
9176 mono_bitset_free (global_interface_bitset);
9177 global_interface_bitset = NULL;
9181 * mono_class_get_exception_for_failure:
9182 * @klass: class in which the failure was detected
9184 * Return a constructed MonoException than the caller can then throw
9185 * using mono_raise_exception - or NULL if no failure is present (or
9186 * doesn't result in an exception).
9189 mono_class_get_exception_for_failure (MonoClass *klass)
9191 gpointer exception_data = mono_class_get_exception_data (klass);
9193 switch (klass->exception_type) {
9194 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9195 MonoDomain *domain = mono_domain_get ();
9196 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9197 MonoMethod *method = exception_data;
9198 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9199 MonoObject *exc = NULL;
9203 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9204 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9205 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9207 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9208 return (MonoException*) exc;
9210 case MONO_EXCEPTION_TYPE_LOAD: {
9213 char *str = mono_type_get_full_name (klass);
9214 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9215 name = mono_string_new (mono_domain_get (), str);
9217 ex = mono_get_exception_type_load (name, astr);
9221 case MONO_EXCEPTION_MISSING_METHOD: {
9222 char *class_name = exception_data;
9223 char *assembly_name = class_name + strlen (class_name) + 1;
9225 return mono_get_exception_missing_method (class_name, assembly_name);
9227 case MONO_EXCEPTION_MISSING_FIELD: {
9228 char *class_name = exception_data;
9229 char *member_name = class_name + strlen (class_name) + 1;
9231 return mono_get_exception_missing_field (class_name, member_name);
9233 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9234 char *msg_format = exception_data;
9235 char *assembly_name = msg_format + strlen (msg_format) + 1;
9236 char *msg = g_strdup_printf (msg_format, assembly_name);
9239 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9245 case MONO_EXCEPTION_BAD_IMAGE: {
9246 return mono_get_exception_bad_image_format (exception_data);
9249 MonoLoaderError *error;
9252 error = mono_loader_get_last_error ();
9254 ex = mono_loader_error_prepare_exception (error);
9258 /* TODO - handle other class related failures */
9265 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9267 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9268 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9270 if (outer_klass == inner_klass)
9272 inner_klass = inner_klass->nested_in;
9273 } while (inner_klass);
9278 mono_class_get_generic_type_definition (MonoClass *klass)
9280 return klass->generic_class ? klass->generic_class->container_class : klass;
9284 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9286 * Generic instantiations are ignored for all super types of @klass.
9288 * Visibility checks ignoring generic instantiations.
9291 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9294 klass = mono_class_get_generic_type_definition (klass);
9295 parent = mono_class_get_generic_type_definition (parent);
9296 mono_class_setup_supertypes (klass);
9298 for (i = 0; i < klass->idepth; ++i) {
9299 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9305 * Subtype can only access parent members with family protection if the site object
9306 * is subclass of Subtype. For example:
9307 * class A { protected int x; }
9309 * void valid_access () {
9313 * void invalid_access () {
9320 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9322 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9325 if (context_klass == NULL)
9327 /*if access_klass is not member_klass context_klass must be type compat*/
9328 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9334 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9337 if (accessing == accessed)
9339 if (!accessed || !accessing)
9342 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9343 * anywhere so untrusted friends are not safe to access platform's code internals */
9344 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
9345 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9349 mono_assembly_load_friends (accessed);
9350 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9351 MonoAssemblyName *friend = tmp->data;
9352 /* Be conservative with checks */
9355 if (strcmp (accessing->aname.name, friend->name))
9357 if (friend->public_key_token [0]) {
9358 if (!accessing->aname.public_key_token [0])
9360 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9369 * If klass is a generic type or if it is derived from a generic type, return the
9370 * MonoClass of the generic definition
9371 * Returns NULL if not found
9374 get_generic_definition_class (MonoClass *klass)
9377 if (klass->generic_class && klass->generic_class->container_class)
9378 return klass->generic_class->container_class;
9379 klass = klass->parent;
9385 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9388 for (i = 0; i < ginst->type_argc; ++i) {
9389 MonoType *type = ginst->type_argv[i];
9390 switch (type->type) {
9391 case MONO_TYPE_SZARRAY:
9392 if (!can_access_type (access_klass, type->data.klass))
9395 case MONO_TYPE_ARRAY:
9396 if (!can_access_type (access_klass, type->data.array->eklass))
9400 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9403 case MONO_TYPE_CLASS:
9404 case MONO_TYPE_VALUETYPE:
9405 case MONO_TYPE_GENERICINST:
9406 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9414 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9418 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9421 if (access_klass->element_class && !access_klass->enumtype)
9422 access_klass = access_klass->element_class;
9424 if (member_klass->element_class && !member_klass->enumtype)
9425 member_klass = member_klass->element_class;
9427 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9429 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9432 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9435 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9438 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9441 /*Non nested type with nested visibility. We just fail it.*/
9442 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9445 switch (access_level) {
9446 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9447 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9449 case TYPE_ATTRIBUTE_PUBLIC:
9452 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9455 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9456 return is_nesting_type (member_klass, access_klass);
9458 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9459 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9461 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9462 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9464 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9465 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9466 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9468 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9469 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9470 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9475 /* FIXME: check visibility of type, too */
9477 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9479 MonoClass *member_generic_def;
9480 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9483 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9484 access_klass->generic_container) &&
9485 (member_generic_def = get_generic_definition_class (member_klass))) {
9486 MonoClass *access_container;
9488 if (access_klass->generic_container)
9489 access_container = access_klass;
9491 access_container = access_klass->generic_class->container_class;
9493 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9497 /* Partition I 8.5.3.2 */
9498 /* the access level values are the same for fields and methods */
9499 switch (access_level) {
9500 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9501 /* same compilation unit */
9502 return access_klass->image == member_klass->image;
9503 case FIELD_ATTRIBUTE_PRIVATE:
9504 return access_klass == member_klass;
9505 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9506 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9507 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9510 case FIELD_ATTRIBUTE_ASSEMBLY:
9511 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9512 case FIELD_ATTRIBUTE_FAMILY:
9513 if (is_valid_family_access (access_klass, member_klass, context_klass))
9516 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9517 if (is_valid_family_access (access_klass, member_klass, context_klass))
9519 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9520 case FIELD_ATTRIBUTE_PUBLIC:
9527 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9529 /* FIXME: check all overlapping fields */
9530 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9532 MonoClass *nested = method->klass->nested_in;
9534 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9537 nested = nested->nested_in;
9544 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9546 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9548 MonoClass *nested = method->klass->nested_in;
9550 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9553 nested = nested->nested_in;
9558 * with generics calls to explicit interface implementations can be expressed
9559 * directly: the method is private, but we must allow it. This may be opening
9560 * a hole or the generics code should handle this differently.
9561 * Maybe just ensure the interface type is public.
9563 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9569 * mono_method_can_access_method_full:
9570 * @method: The caller method
9571 * @called: The called method
9572 * @context_klass: The static type on stack of the owner @called object used
9574 * This function must be used with instance calls, as they have more strict family accessibility.
9575 * It can be used with static methods, but context_klass should be NULL.
9577 * Returns: TRUE if caller have proper visibility and acessibility to @called
9580 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9582 MonoClass *access_class = method->klass;
9583 MonoClass *member_class = called->klass;
9584 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9586 MonoClass *nested = access_class->nested_in;
9588 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9591 nested = nested->nested_in;
9598 can = can_access_type (access_class, member_class);
9600 MonoClass *nested = access_class->nested_in;
9602 can = can_access_type (nested, member_class);
9605 nested = nested->nested_in;
9612 if (called->is_inflated) {
9613 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9614 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9623 * mono_method_can_access_field_full:
9624 * @method: The caller method
9625 * @field: The accessed field
9626 * @context_klass: The static type on stack of the owner @field object used
9628 * This function must be used with instance fields, as they have more strict family accessibility.
9629 * It can be used with static fields, but context_klass should be NULL.
9631 * Returns: TRUE if caller have proper visibility and acessibility to @field
9634 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9636 MonoClass *access_class = method->klass;
9637 MonoClass *member_class = field->parent;
9638 /* FIXME: check all overlapping fields */
9639 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9641 MonoClass *nested = access_class->nested_in;
9643 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9646 nested = nested->nested_in;
9653 can = can_access_type (access_class, member_class);
9655 MonoClass *nested = access_class->nested_in;
9657 can = can_access_type (nested, member_class);
9660 nested = nested->nested_in;
9670 * mono_type_is_valid_enum_basetype:
9671 * @type: The MonoType to check
9673 * Returns: TRUE if the type can be used as the basetype of an enum
9675 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9676 switch (type->type) {
9679 case MONO_TYPE_BOOLEAN:
9682 case MONO_TYPE_CHAR:
9695 * mono_class_is_valid_enum:
9696 * @klass: An enum class to be validated
9698 * This method verify the required properties an enum should have.
9700 * Returns: TRUE if the informed enum class is valid
9702 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9703 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9704 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9706 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9707 MonoClassField * field;
9708 gpointer iter = NULL;
9709 gboolean found_base_field = FALSE;
9711 g_assert (klass->enumtype);
9712 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9713 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9717 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9720 while ((field = mono_class_get_fields (klass, &iter))) {
9721 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9722 if (found_base_field)
9724 found_base_field = TRUE;
9725 if (!mono_type_is_valid_enum_basetype (field->type))
9730 if (!found_base_field)
9733 if (klass->method.count > 0)
9740 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9742 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9746 * mono_class_setup_interface_id:
9748 * Initializes MonoClass::interface_id if required.
9750 * LOCKING: Acquires the loader lock.
9753 mono_class_setup_interface_id (MonoClass *class)
9755 mono_loader_lock ();
9756 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9757 class->interface_id = mono_get_unique_iid (class);
9758 mono_loader_unlock ();
9762 * mono_class_alloc_ext:
9764 * Allocate klass->ext if not already done.
9765 * LOCKING: Assumes the loader lock is held.
9768 mono_class_alloc_ext (MonoClass *klass)
9771 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9772 class_ext_size += sizeof (MonoClassExt);
9777 * mono_class_setup_interfaces:
9779 * Initialize class->interfaces/interfaces_count.
9780 * LOCKING: Acquires the loader lock.
9781 * This function can fail the type.
9784 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9788 mono_error_init (error);
9790 if (klass->interfaces_inited)
9793 mono_loader_lock ();
9795 if (klass->interfaces_inited) {
9796 mono_loader_unlock ();
9800 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY && mono_defaults.generic_ilist_class) {
9803 /* generic IList, ICollection, IEnumerable */
9804 klass->interface_count = 1;
9805 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9807 args [0] = &klass->element_class->byval_arg;
9808 klass->interfaces [0] = mono_class_bind_generic_parameters (
9809 mono_defaults.generic_ilist_class, 1, args, FALSE);
9810 } else if (klass->generic_class) {
9811 MonoClass *gklass = klass->generic_class->container_class;
9813 klass->interface_count = gklass->interface_count;
9814 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
9815 for (i = 0; i < klass->interface_count; i++) {
9816 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
9817 if (!mono_error_ok (error)) {
9818 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
9819 klass->interfaces = NULL;
9825 mono_memory_barrier ();
9827 klass->interfaces_inited = TRUE;
9829 mono_loader_unlock ();
9833 mono_field_resolve_type (MonoClassField *field, MonoError *error)
9835 MonoClass *class = field->parent;
9836 MonoImage *image = class->image;
9837 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
9838 int field_idx = field - class->fields;
9840 mono_error_init (error);
9843 MonoClassField *gfield = >d->fields [field_idx];
9844 MonoType *gtype = mono_field_get_type_checked (gfield, error);
9845 if (!mono_error_ok (error)) {
9846 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9847 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9851 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
9852 if (!mono_error_ok (error)) {
9853 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
9854 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
9859 guint32 cols [MONO_FIELD_SIZE];
9860 MonoGenericContainer *container = NULL;
9861 int idx = class->field.first + field_idx;
9863 /*FIXME, in theory we do not lazy load SRE fields*/
9864 g_assert (!image->dynamic);
9866 if (class->generic_container) {
9867 container = class->generic_container;
9869 container = gtd->generic_container;
9870 g_assert (container);
9873 /* class->field.first and idx points into the fieldptr table */
9874 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
9876 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
9877 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
9878 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
9882 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
9884 mono_metadata_decode_value (sig, &sig);
9885 /* FIELD signature == 0x06 */
9886 g_assert (*sig == 0x06);
9887 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
9889 mono_error_set_type_load_class (error, class, "Could not load field %s type", field->name);
9890 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
9891 mono_loader_clear_error ();
9897 mono_field_resolve_flags (MonoClassField *field)
9899 MonoClass *class = field->parent;
9900 MonoImage *image = class->image;
9901 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
9902 int field_idx = field - class->fields;
9906 MonoClassField *gfield = >d->fields [field_idx];
9907 return mono_field_get_flags (gfield);
9909 int idx = class->field.first + field_idx;
9911 /*FIXME, in theory we do not lazy load SRE fields*/
9912 g_assert (!image->dynamic);
9914 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
9919 * mono_class_setup_basic_field_info:
9920 * @class: The class to initialize
9922 * Initializes the class->fields array of fields.
9923 * Aquires the loader lock.
9926 mono_class_setup_basic_field_info_locking (MonoClass *class)
9928 mono_loader_lock ();
9929 mono_class_setup_basic_field_info (class);
9930 mono_loader_unlock ();
9934 * mono_class_get_fields_lazy:
9935 * @klass: the MonoClass to act on
9937 * This routine is an iterator routine for retrieving the fields in a class.
9938 * Only minimal information about fields are loaded. Accessors must be used
9939 * for all MonoClassField returned.
9941 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9942 * iterate over all of the elements. When no more values are
9943 * available, the return value is NULL.
9945 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9948 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
9950 MonoClassField* field;
9954 mono_class_setup_basic_field_info_locking (klass);
9957 /* start from the first */
9958 if (klass->field.count) {
9959 return *iter = &klass->fields [0];
9967 if (field < &klass->fields [klass->field.count]) {
9968 return *iter = field;