2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9 * Copyright 2012 Xamarin Inc (http://www.xamarin.com)
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/assembly.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/metadata-internals.h>
23 #include <mono/metadata/profiler-private.h>
24 #include <mono/metadata/tabledefs.h>
25 #include <mono/metadata/tokentype.h>
26 #include <mono/metadata/class-internals.h>
27 #include <mono/metadata/object.h>
28 #include <mono/metadata/appdomain.h>
29 #include <mono/metadata/mono-endian.h>
30 #include <mono/metadata/debug-helpers.h>
31 #include <mono/metadata/reflection.h>
32 #include <mono/metadata/exception.h>
33 #include <mono/metadata/security-manager.h>
34 #include <mono/metadata/security-core-clr.h>
35 #include <mono/metadata/attrdefs.h>
36 #include <mono/metadata/gc-internal.h>
37 #include <mono/metadata/verify-internals.h>
38 #include <mono/metadata/mono-debug.h>
39 #include <mono/utils/mono-counters.h>
40 #include <mono/utils/mono-string.h>
41 #include <mono/utils/mono-error-internals.h>
42 #include <mono/utils/mono-logger-internal.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
49 gboolean mono_print_vtable = FALSE;
52 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
53 guint32 classes_size, class_ext_size;
55 /* 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, MonoError *error);
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 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
224 if (!mono_error_ok (&error)) {
225 mono_loader_set_error_from_mono_error (&error);
226 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
232 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
235 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
238 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
242 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
243 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
247 if (!image->references || !image->references [idx - 1])
248 mono_assembly_load_reference (image, idx - 1);
249 g_assert (image->references [idx - 1]);
251 /* If the assembly did not load, register this as a type load exception */
252 if (image->references [idx - 1] == REFERENCE_MISSING){
253 MonoAssemblyName aname;
256 mono_assembly_get_assemblyref (image, idx - 1, &aname);
257 human_name = mono_stringify_assembly_name (&aname);
258 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
264 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
269 mono_image_memdup (MonoImage *image, void *data, guint size)
271 void *res = mono_image_alloc (image, size);
272 memcpy (res, data, size);
276 /* Copy everything mono_metadata_free_array free. */
278 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
281 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
283 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
285 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
287 a = g_memdup (a, sizeof (MonoArrayType));
289 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
291 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
296 /* Copy everything mono_metadata_free_method_signature free. */
298 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
302 sig = mono_metadata_signature_dup_full (image, sig);
304 sig->ret = mono_metadata_type_dup (image, sig->ret);
305 for (i = 0; i < sig->param_count; ++i)
306 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
312 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
314 MonoAssembly *ta = klass->image->assembly;
317 name = mono_stringify_assembly_name (&ta->aname);
318 g_string_append_printf (str, ", %s", name);
323 mono_type_name_check_byref (MonoType *type, GString *str)
326 g_string_append_c (str, '&');
330 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
331 MonoTypeNameFormat format)
335 switch (type->type) {
336 case MONO_TYPE_ARRAY: {
337 int i, rank = type->data.array->rank;
338 MonoTypeNameFormat nested_format;
340 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
341 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
343 mono_type_get_name_recurse (
344 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
345 g_string_append_c (str, '[');
347 g_string_append_c (str, '*');
348 for (i = 1; i < rank; i++)
349 g_string_append_c (str, ',');
350 g_string_append_c (str, ']');
352 mono_type_name_check_byref (type, str);
354 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
355 _mono_type_get_assembly_name (type->data.array->eklass, str);
358 case MONO_TYPE_SZARRAY: {
359 MonoTypeNameFormat nested_format;
361 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
362 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
364 mono_type_get_name_recurse (
365 &type->data.klass->byval_arg, str, FALSE, nested_format);
366 g_string_append (str, "[]");
368 mono_type_name_check_byref (type, str);
370 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
371 _mono_type_get_assembly_name (type->data.klass, str);
374 case MONO_TYPE_PTR: {
375 MonoTypeNameFormat nested_format;
377 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
378 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
380 mono_type_get_name_recurse (
381 type->data.type, str, FALSE, nested_format);
382 g_string_append_c (str, '*');
384 mono_type_name_check_byref (type, str);
386 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
387 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
392 if (!mono_generic_param_info (type->data.generic_param))
393 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
395 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
397 mono_type_name_check_byref (type, str);
401 klass = mono_class_from_mono_type (type);
402 if (klass->nested_in) {
403 mono_type_get_name_recurse (
404 &klass->nested_in->byval_arg, str, TRUE, format);
405 if (format == MONO_TYPE_NAME_FORMAT_IL)
406 g_string_append_c (str, '.');
408 g_string_append_c (str, '+');
409 } else if (*klass->name_space) {
410 g_string_append (str, klass->name_space);
411 g_string_append_c (str, '.');
413 if (format == MONO_TYPE_NAME_FORMAT_IL) {
414 char *s = strchr (klass->name, '`');
415 int len = s ? s - klass->name : strlen (klass->name);
417 g_string_append_len (str, klass->name, len);
419 g_string_append (str, klass->name);
422 if (klass->generic_class) {
423 MonoGenericClass *gclass = klass->generic_class;
424 MonoGenericInst *inst = gclass->context.class_inst;
425 MonoTypeNameFormat nested_format;
428 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
429 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
431 if (format == MONO_TYPE_NAME_FORMAT_IL)
432 g_string_append_c (str, '<');
434 g_string_append_c (str, '[');
435 for (i = 0; i < inst->type_argc; i++) {
436 MonoType *t = inst->type_argv [i];
439 g_string_append_c (str, ',');
440 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
441 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
442 g_string_append_c (str, '[');
443 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
444 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
445 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
446 g_string_append_c (str, ']');
448 if (format == MONO_TYPE_NAME_FORMAT_IL)
449 g_string_append_c (str, '>');
451 g_string_append_c (str, ']');
452 } else if (klass->generic_container &&
453 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
454 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
457 if (format == MONO_TYPE_NAME_FORMAT_IL)
458 g_string_append_c (str, '<');
460 g_string_append_c (str, '[');
461 for (i = 0; i < klass->generic_container->type_argc; i++) {
463 g_string_append_c (str, ',');
464 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
466 if (format == MONO_TYPE_NAME_FORMAT_IL)
467 g_string_append_c (str, '>');
469 g_string_append_c (str, ']');
472 mono_type_name_check_byref (type, str);
474 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
475 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
476 _mono_type_get_assembly_name (klass, str);
482 * mono_type_get_name_full:
484 * @format: the format for the return string.
487 * Returns: the string representation in a number of formats:
489 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
490 * returned in the formatrequired by System.Reflection, this is the
491 * inverse of mono_reflection_parse_type ().
493 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
494 * be used by the IL assembler.
496 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
498 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
501 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
505 result = g_string_new ("");
507 mono_type_get_name_recurse (type, result, FALSE, format);
509 return g_string_free (result, FALSE);
513 * mono_type_get_full_name:
516 * Returns: the string representation for type as required by System.Reflection.
517 * The inverse of mono_reflection_parse_type ().
520 mono_type_get_full_name (MonoClass *class)
522 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
526 * mono_type_get_name:
529 * Returns: the string representation for type as it would be represented in IL code.
532 mono_type_get_name (MonoType *type)
534 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
538 * mono_type_get_underlying_type:
541 * Returns: the MonoType for the underlying integer type if @type
542 * is an enum and byref is false, otherwise the type itself.
545 mono_type_get_underlying_type (MonoType *type)
547 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
548 return mono_class_enum_basetype (type->data.klass);
549 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
550 return mono_class_enum_basetype (type->data.generic_class->container_class);
555 * mono_class_is_open_constructed_type:
558 * Returns TRUE if type represents a generics open constructed type.
559 * IOW, not all type parameters required for the instantiation have
560 * been provided or it's a generic type definition.
562 * An open constructed type means it's a non realizable type. Not to
563 * be mixed up with an abstract type - we can't cast or dispatch to
564 * an open type, for example.
567 mono_class_is_open_constructed_type (MonoType *t)
573 case MONO_TYPE_SZARRAY:
574 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
575 case MONO_TYPE_ARRAY:
576 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
578 return mono_class_is_open_constructed_type (t->data.type);
579 case MONO_TYPE_GENERICINST:
580 return t->data.generic_class->context.class_inst->is_open;
581 case MONO_TYPE_CLASS:
582 case MONO_TYPE_VALUETYPE:
583 return t->data.klass->generic_container != NULL;
590 This is a simple function to catch the most common bad instances of generic types.
591 Specially those that might lead to further failures in the runtime.
594 is_valid_generic_argument (MonoType *type)
596 switch (type->type) {
598 //case MONO_TYPE_TYPEDBYREF:
605 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
607 mono_error_init (error);
609 switch (type->type) {
610 case MONO_TYPE_MVAR: {
612 int num = mono_type_get_generic_param_num (type);
613 MonoGenericInst *inst = context->method_inst;
614 if (!inst || !inst->type_argv)
616 if (num >= inst->type_argc) {
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 in this context with %d instantiations",
619 num, info ? info->name : "", inst->type_argc);
623 if (!is_valid_generic_argument (inst->type_argv [num])) {
624 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
625 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
626 num, info ? info->name : "", inst->type_argv [num]->type);
630 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
631 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
632 * ->byref and ->attrs from @type are propagated to the returned type.
634 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
635 nt->byref = type->byref;
636 nt->attrs = type->attrs;
639 case MONO_TYPE_VAR: {
641 int num = mono_type_get_generic_param_num (type);
642 MonoGenericInst *inst = context->class_inst;
645 if (num >= inst->type_argc) {
646 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
647 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
648 num, info ? info->name : "", inst->type_argc);
651 if (!is_valid_generic_argument (inst->type_argv [num])) {
652 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
653 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
654 num, info ? info->name : "", inst->type_argv [num]->type);
657 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
658 nt->byref = type->byref;
659 nt->attrs = type->attrs;
662 case MONO_TYPE_SZARRAY: {
663 MonoClass *eclass = type->data.klass;
664 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
665 if (!inflated || !mono_error_ok (error))
667 nt = mono_metadata_type_dup (image, type);
668 nt->data.klass = mono_class_from_mono_type (inflated);
669 mono_metadata_free_type (inflated);
672 case MONO_TYPE_ARRAY: {
673 MonoClass *eclass = type->data.array->eklass;
674 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
675 if (!inflated || !mono_error_ok (error))
677 nt = mono_metadata_type_dup (image, type);
678 nt->data.array->eklass = mono_class_from_mono_type (inflated);
679 mono_metadata_free_type (inflated);
682 case MONO_TYPE_GENERICINST: {
683 MonoGenericClass *gclass = type->data.generic_class;
684 MonoGenericInst *inst;
686 if (!gclass->context.class_inst->is_open)
689 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
690 if (!mono_error_ok (error))
692 if (inst != gclass->context.class_inst)
693 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
695 if (gclass == type->data.generic_class)
698 nt = mono_metadata_type_dup (image, type);
699 nt->data.generic_class = gclass;
702 case MONO_TYPE_CLASS:
703 case MONO_TYPE_VALUETYPE: {
704 MonoClass *klass = type->data.klass;
705 MonoGenericContainer *container = klass->generic_container;
706 MonoGenericInst *inst;
707 MonoGenericClass *gclass = NULL;
713 /* We can't use context->class_inst directly, since it can have more elements */
714 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
715 if (!mono_error_ok (error))
717 if (inst == container->context.class_inst)
720 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
722 nt = mono_metadata_type_dup (image, type);
723 nt->type = MONO_TYPE_GENERICINST;
724 nt->data.generic_class = gclass;
734 mono_generic_class_get_context (MonoGenericClass *gclass)
736 return &gclass->context;
740 mono_class_get_context (MonoClass *class)
742 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
746 * mono_class_get_generic_container:
748 * Return the generic container of KLASS which should be a generic type definition.
750 MonoGenericContainer*
751 mono_class_get_generic_container (MonoClass *klass)
753 g_assert (klass->is_generic);
755 return klass->generic_container;
759 * mono_class_get_generic_class:
761 * Return the MonoGenericClass of KLASS, which should be a generic instance.
764 mono_class_get_generic_class (MonoClass *klass)
766 g_assert (klass->is_inflated);
768 return klass->generic_class;
772 * mono_class_inflate_generic_type_with_mempool:
773 * @mempool: a mempool
775 * @context: a generics context
776 * @error: error context
778 * The same as mono_class_inflate_generic_type, but allocates the MonoType
779 * from mempool if it is non-NULL. If it is NULL, the MonoType is
780 * allocated on the heap and is owned by the caller.
781 * The returned type can potentially be the same as TYPE, so it should not be
782 * modified by the caller, and it should be freed using mono_metadata_free_type ().
785 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
787 MonoType *inflated = NULL;
788 mono_error_init (error);
791 inflated = inflate_generic_type (image, type, context, error);
792 if (!mono_error_ok (error))
796 MonoType *shared = mono_metadata_get_shared_type (type);
801 return mono_metadata_type_dup (image, type);
805 mono_stats.inflated_type_count++;
810 * mono_class_inflate_generic_type:
812 * @context: a generics context
814 * If @type is a generic type and @context is not NULL, instantiate it using the
815 * generics context @context.
817 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
818 * on the heap and is owned by the caller. Returns NULL on error.
820 * @deprecated Please use mono_class_inflate_generic_type_checked instead
823 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
827 result = mono_class_inflate_generic_type_checked (type, context, &error);
829 if (!mono_error_ok (&error)) {
830 mono_error_cleanup (&error);
837 * mono_class_inflate_generic_type:
839 * @context: a generics context
840 * @error: error context to use
842 * If @type is a generic type and @context is not NULL, instantiate it using the
843 * generics context @context.
845 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
846 * on the heap and is owned by the caller.
849 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
851 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
855 * mono_class_inflate_generic_type_no_copy:
857 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
861 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
863 MonoType *inflated = NULL;
865 mono_error_init (error);
867 inflated = inflate_generic_type (image, type, context, error);
868 if (!mono_error_ok (error))
875 mono_stats.inflated_type_count++;
880 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
885 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
886 if (!mono_error_ok (error))
889 res = mono_class_from_mono_type (inflated);
890 mono_metadata_free_type (inflated);
895 * mono_class_inflate_generic_class:
897 * Inflate the class GKLASS with CONTEXT.
900 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
905 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
906 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
913 static MonoGenericContext
914 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
916 MonoGenericInst *class_inst = NULL;
917 MonoGenericInst *method_inst = NULL;
918 MonoGenericContext res = { NULL, NULL };
920 mono_error_init (error);
922 if (context->class_inst) {
923 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
924 if (!mono_error_ok (error))
928 if (context->method_inst) {
929 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
930 if (!mono_error_ok (error))
934 res.class_inst = class_inst;
935 res.method_inst = method_inst;
941 * mono_class_inflate_generic_method:
942 * @method: a generic method
943 * @context: a generics context
945 * Instantiate the generic method @method using the generics context @context.
947 * Returns: the new instantiated method
950 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
952 return mono_class_inflate_generic_method_full (method, NULL, context);
956 * mono_class_inflate_generic_method_full:
958 * Instantiate method @method with the generic context @context.
959 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
960 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
963 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
966 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
967 if (!mono_error_ok (&error))
968 /*FIXME do proper error handling - on this case, kill this function. */
969 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
975 * mono_class_inflate_generic_method_full_checked:
976 * Same as mono_class_inflate_generic_method_full but return failure using @error.
979 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
982 MonoMethodInflated *iresult, *cached;
983 MonoMethodSignature *sig;
984 MonoGenericContext tmp_context;
985 gboolean is_mb_open = FALSE;
987 mono_error_init (error);
989 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
990 while (method->is_inflated) {
991 MonoGenericContext *method_context = mono_method_get_context (method);
992 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
994 tmp_context = inflate_generic_context (method_context, context, error);
995 if (!mono_error_ok (error))
997 context = &tmp_context;
999 if (mono_metadata_generic_context_equal (method_context, context))
1002 method = imethod->declaring;
1006 * A method only needs to be inflated if the context has argument for which it is
1009 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1010 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1013 if (!((method->is_generic && context->method_inst) ||
1014 (method->klass->generic_container && context->class_inst)))
1018 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1019 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1020 * This is opposite to the way non-SRE MethodInfos behave.
1022 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1024 * void Example<T> () {
1028 * In Example, the method token must be encoded as: "void Example<!!0>()"
1030 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1031 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1033 * On the other hand, inflating a non-SRE generic method with its own arguments should
1034 * return itself. For example:
1036 * MethodInfo m = ... //m is a generic method definition
1037 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1040 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1041 * what happens with regular methods.
1043 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1044 * everything should behave like a regular type or method.
1047 is_mb_open = method->is_generic &&
1048 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1049 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1051 iresult = g_new0 (MonoMethodInflated, 1);
1052 iresult->context = *context;
1053 iresult->declaring = method;
1054 iresult->method.method.is_mb_open = is_mb_open;
1056 if (!context->method_inst && method->is_generic)
1057 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1059 if (!context->class_inst) {
1060 g_assert (!iresult->declaring->klass->generic_class);
1061 if (iresult->declaring->klass->generic_container)
1062 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1063 else if (iresult->declaring->klass->generic_class)
1064 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1067 mono_loader_lock ();
1068 cached = mono_method_inflated_lookup (iresult, FALSE);
1070 mono_loader_unlock ();
1072 return (MonoMethod*)cached;
1075 mono_stats.inflated_method_count++;
1077 inflated_methods_size += sizeof (MonoMethodInflated);
1079 sig = mono_method_signature (method);
1081 char *name = mono_type_get_full_name (method->klass);
1082 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1088 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1090 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1093 result = (MonoMethod *) iresult;
1094 result->is_inflated = TRUE;
1095 result->is_generic = FALSE;
1096 result->sre_method = FALSE;
1097 result->signature = NULL;
1098 result->is_mb_open = is_mb_open;
1100 if (!context->method_inst) {
1101 /* Set the generic_container of the result to the generic_container of method */
1102 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1104 if (generic_container) {
1105 result->is_generic = 1;
1106 mono_method_set_generic_container (result, generic_container);
1110 if (!klass_hint || !klass_hint->generic_class ||
1111 klass_hint->generic_class->container_class != method->klass ||
1112 klass_hint->generic_class->context.class_inst != context->class_inst)
1115 if (method->klass->generic_container)
1116 result->klass = klass_hint;
1118 if (!result->klass) {
1119 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1120 if (!mono_error_ok (error))
1123 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1125 mono_metadata_free_type (inflated);
1129 * FIXME: This should hold, but it doesn't:
1131 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1132 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1133 * g_assert (result->is_generic);
1136 * Fixing this here causes other things to break, hence a very
1137 * ugly hack in mini-trampolines.c - see
1138 * is_generic_method_definition().
1141 mono_method_inflated_lookup (iresult, TRUE);
1142 mono_loader_unlock ();
1146 mono_loader_unlock ();
1152 * mono_get_inflated_method:
1154 * Obsolete. We keep it around since it's mentioned in the public API.
1157 mono_get_inflated_method (MonoMethod *method)
1163 * mono_method_get_context_general:
1165 * @uninflated: handle uninflated methods?
1167 * Returns the generic context of a method or NULL if it doesn't have
1168 * one. For an inflated method that's the context stored in the
1169 * method. Otherwise it's in the method's generic container or in the
1170 * generic container of the method's class.
1173 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1175 if (method->is_inflated) {
1176 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1177 return &imethod->context;
1181 if (method->is_generic)
1182 return &(mono_method_get_generic_container (method)->context);
1183 if (method->klass->generic_container)
1184 return &method->klass->generic_container->context;
1189 * mono_method_get_context:
1192 * Returns the generic context for method if it's inflated, otherwise
1196 mono_method_get_context (MonoMethod *method)
1198 return mono_method_get_context_general (method, FALSE);
1202 * mono_method_get_generic_container:
1204 * Returns the generic container of METHOD, which should be a generic method definition.
1205 * Returns NULL if METHOD is not a generic method definition.
1206 * LOCKING: Acquires the loader lock.
1208 MonoGenericContainer*
1209 mono_method_get_generic_container (MonoMethod *method)
1211 MonoGenericContainer *container;
1213 if (!method->is_generic)
1216 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1217 g_assert (container);
1223 * mono_method_set_generic_container:
1225 * Sets the generic container of METHOD to CONTAINER.
1226 * LOCKING: Acquires the loader lock.
1229 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1231 g_assert (method->is_generic);
1233 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1237 * mono_class_find_enum_basetype:
1238 * @class: The enum class
1240 * Determine the basetype of an enum by iterating through its fields. We do this
1241 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1244 mono_class_find_enum_basetype (MonoClass *class)
1246 MonoGenericContainer *container = NULL;
1247 MonoImage *m = class->image;
1248 const int top = class->field.count;
1251 g_assert (class->enumtype);
1253 if (class->generic_container)
1254 container = class->generic_container;
1255 else if (class->generic_class) {
1256 MonoClass *gklass = class->generic_class->container_class;
1258 container = gklass->generic_container;
1259 g_assert (container);
1263 * Fetch all the field information.
1265 for (i = 0; i < top; i++){
1267 guint32 cols [MONO_FIELD_SIZE];
1268 int idx = class->field.first + i;
1271 /* class->field.first and idx points into the fieldptr table */
1272 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1274 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1277 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1280 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1281 mono_metadata_decode_value (sig, &sig);
1282 /* FIELD signature == 0x06 */
1286 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1289 if (class->generic_class) {
1290 //FIXME do we leak here?
1291 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1292 ftype->attrs = cols [MONO_FIELD_FLAGS];
1302 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1305 mono_type_has_exceptions (MonoType *type)
1307 switch (type->type) {
1308 case MONO_TYPE_CLASS:
1309 case MONO_TYPE_VALUETYPE:
1310 case MONO_TYPE_SZARRAY:
1311 return type->data.klass->exception_type;
1312 case MONO_TYPE_ARRAY:
1313 return type->data.array->eklass->exception_type;
1314 case MONO_TYPE_GENERICINST:
1315 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1323 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1327 mono_class_alloc (MonoClass *class, int size)
1329 if (class->generic_class)
1330 return mono_image_set_alloc (class->generic_class->owner, size);
1332 return mono_image_alloc (class->image, size);
1336 mono_class_alloc0 (MonoClass *class, int size)
1340 res = mono_class_alloc (class, size);
1341 memset (res, 0, size);
1345 #define mono_class_new0(class,struct_type, n_structs) \
1346 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1349 * mono_class_setup_basic_field_info:
1350 * @class: The class to initialize
1352 * Initializes the class->fields.
1353 * LOCKING: Assumes the loader lock is held.
1356 mono_class_setup_basic_field_info (MonoClass *class)
1358 MonoClassField *field;
1366 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1367 image = class->image;
1368 top = class->field.count;
1370 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1372 * This happens when a generic instance of an unfinished generic typebuilder
1373 * is used as an element type for creating an array type. We can't initialize
1374 * the fields of this class using the fields of gklass, since gklass is not
1375 * finished yet, fields could be added to it later.
1381 mono_class_setup_basic_field_info (gtd);
1383 top = gtd->field.count;
1384 class->field.first = gtd->field.first;
1385 class->field.count = gtd->field.count;
1388 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1391 * Fetch all the field information.
1393 for (i = 0; i < top; i++){
1394 field = &class->fields [i];
1395 field->parent = class;
1398 field->name = mono_field_get_name (>d->fields [i]);
1400 int idx = class->field.first + i;
1401 /* class->field.first and idx points into the fieldptr table */
1402 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1403 /* The name is needed for fieldrefs */
1404 field->name = mono_metadata_string_heap (image, name_idx);
1410 * mono_class_setup_fields:
1411 * @class: The class to initialize
1413 * Initializes the class->fields.
1414 * LOCKING: Assumes the loader lock is held.
1417 mono_class_setup_fields (MonoClass *class)
1420 MonoImage *m = class->image;
1422 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1423 int i, blittable = TRUE;
1424 guint32 real_size = 0;
1425 guint32 packing_size = 0;
1426 gboolean explicit_size;
1427 MonoClassField *field;
1428 MonoGenericContainer *container = NULL;
1429 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1432 * FIXME: We have a race condition here. It's possible that this function returns
1433 * to its caller with `instance_size` set to `0` instead of the actual size. This
1434 * is not a problem when the function is called recursively on the same class,
1435 * because the size will be initialized by the outer invocation. What follows is a
1436 * description of how it can occur in other cases, too. There it is a problem,
1437 * because it can lead to the GC being asked to allocate an object of size `0`,
1438 * which SGen chokes on. The race condition is triggered infrequently by
1439 * `tests/sgen-suspend.cs`.
1441 * This function is called for a class whenever one of its subclasses is inited.
1442 * For example, it's called for every subclass of Object. What it does is this:
1444 * if (class->setup_fields_called)
1447 * class->instance_size = 0;
1449 * class->setup_fields_called = 1;
1450 * ... critical point
1451 * class->instance_size = actual_instance_size;
1453 * The last two steps are sometimes reversed, but that only changes the way in which
1454 * the race condition works.
1456 * Assume thread A goes through this function and makes it to the critical point.
1457 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1458 * immediately, but `instance_size` is incorrect.
1460 * The other case looks like this:
1462 * if (class->setup_fields_called)
1464 * ... critical point X
1465 * class->instance_size = 0;
1466 * ... critical point Y
1467 * class->instance_size = actual_instance_size;
1469 * class->setup_fields_called = 1;
1471 * Assume thread A goes through the function and makes it to critical point X. Now
1472 * thread B runs through the whole of the function, returning, assuming
1473 * `instance_size` is set. At that point thread A gets to run and makes it to
1474 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1477 if (class->setup_fields_called)
1480 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1482 * This happens when a generic instance of an unfinished generic typebuilder
1483 * is used as an element type for creating an array type. We can't initialize
1484 * the fields of this class using the fields of gklass, since gklass is not
1485 * finished yet, fields could be added to it later.
1490 mono_class_setup_basic_field_info (class);
1491 top = class->field.count;
1494 mono_class_setup_fields (gtd);
1495 if (gtd->exception_type) {
1496 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1501 class->instance_size = 0;
1503 class->sizes.class_size = 0;
1505 if (class->parent) {
1506 /* For generic instances, class->parent might not have been initialized */
1507 mono_class_init (class->parent);
1508 if (!class->parent->size_inited) {
1509 mono_class_setup_fields (class->parent);
1510 if (class->parent->exception_type) {
1511 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1515 class->instance_size += class->parent->instance_size;
1516 class->min_align = class->parent->min_align;
1517 /* we use |= since it may have been set already */
1518 class->has_references |= class->parent->has_references;
1519 blittable = class->parent->blittable;
1521 class->instance_size = sizeof (MonoObject);
1522 class->min_align = 1;
1525 /* We can't really enable 16 bytes alignment until the GC supports it.
1526 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1527 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1528 Bug #506144 is an example of this issue.
1530 if (class->simd_type)
1531 class->min_align = 16;
1533 /* Get the real size */
1534 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1536 if (explicit_size) {
1537 if ((packing_size & 0xfffffff0) != 0) {
1538 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1539 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1542 class->packing_size = packing_size;
1543 real_size += class->instance_size;
1547 if (explicit_size && real_size) {
1548 class->instance_size = MAX (real_size, class->instance_size);
1550 class->blittable = blittable;
1551 mono_memory_barrier ();
1552 class->size_inited = 1;
1553 class->fields_inited = 1;
1554 class->setup_fields_called = 1;
1558 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1561 /* Prevent infinite loops if the class references itself */
1562 class->setup_fields_called = 1;
1564 if (class->generic_container) {
1565 container = class->generic_container;
1567 container = gtd->generic_container;
1568 g_assert (container);
1572 * Fetch all the field information.
1574 for (i = 0; i < top; i++){
1575 int idx = class->field.first + i;
1576 field = &class->fields [i];
1578 field->parent = class;
1581 mono_field_resolve_type (field, &error);
1582 if (!mono_error_ok (&error)) {
1583 /*mono_field_resolve_type already failed class*/
1584 mono_error_cleanup (&error);
1588 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1589 g_assert (field->type);
1592 if (mono_field_is_deleted (field))
1595 MonoClassField *gfield = >d->fields [i];
1596 field->offset = gfield->offset;
1598 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1600 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1601 field->offset = offset;
1603 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1604 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1607 if (field->offset < -1) { /*-1 is used to encode special static fields */
1608 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1614 /* Only do these checks if we still think this type is blittable */
1615 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1616 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1619 MonoClass *field_class = mono_class_from_mono_type (field->type);
1621 mono_class_setup_fields (field_class);
1622 if (field_class->exception_type) {
1623 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1627 if (!field_class || !field_class->blittable)
1632 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1633 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1634 blittable = class->element_class->blittable;
1637 if (mono_type_has_exceptions (field->type)) {
1638 char *class_name = mono_type_get_full_name (class);
1639 char *type_name = mono_type_full_name (field->type);
1641 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1642 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1643 g_free (class_name);
1647 /* The def_value of fields is compute lazily during vtable creation */
1650 if (class == mono_defaults.string_class)
1653 class->blittable = blittable;
1655 if (class->enumtype && !mono_class_enum_basetype (class)) {
1656 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1659 if (explicit_size && real_size) {
1660 class->instance_size = MAX (real_size, class->instance_size);
1663 if (class->exception_type)
1665 mono_class_layout_fields (class);
1667 /*valuetypes can't be neither bigger than 1Mb or empty. */
1668 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1669 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1671 mono_memory_barrier ();
1672 class->fields_inited = 1;
1676 * mono_class_setup_fields_locking:
1677 * @class: The class to initialize
1679 * Initializes the class->fields array of fields.
1680 * Aquires the loader lock.
1683 mono_class_setup_fields_locking (MonoClass *class)
1685 /* This can be checked without locks */
1686 if (class->fields_inited)
1688 mono_loader_lock ();
1689 mono_class_setup_fields (class);
1690 mono_loader_unlock ();
1694 * mono_class_has_references:
1696 * Returns whenever @klass->has_references is set, initializing it if needed.
1697 * Aquires the loader lock.
1700 mono_class_has_references (MonoClass *klass)
1702 if (klass->init_pending) {
1703 /* Be conservative */
1706 mono_class_init (klass);
1708 return klass->has_references;
1713 * mono_type_get_basic_type_from_generic:
1716 * Returns a closed type corresponding to the possibly open type
1720 mono_type_get_basic_type_from_generic (MonoType *type)
1722 /* When we do generic sharing we let type variables stand for reference types. */
1723 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1724 return &mono_defaults.object_class->byval_arg;
1729 * mono_class_layout_fields:
1732 * Compute the placement of fields inside an object or struct, according to
1733 * the layout rules and set the following fields in @class:
1734 * - has_references (if the class contains instance references firled or structs that contain references)
1735 * - has_static_refs (same, but for static fields)
1736 * - instance_size (size of the object in memory)
1737 * - class_size (size needed for the static fields)
1738 * - size_inited (flag set when the instance_size is set)
1740 * LOCKING: this is supposed to be called with the loader lock held.
1743 mono_class_layout_fields (MonoClass *class)
1746 const int top = class->field.count;
1747 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1748 guint32 pass, passes, real_size;
1749 gboolean gc_aware_layout = FALSE;
1750 MonoClassField *field;
1753 * When we do generic sharing we need to have layout
1754 * information for open generic classes (either with a generic
1755 * context containing type variables or with a generic
1756 * container), so we don't return in that case anymore.
1760 * Enable GC aware auto layout: in this mode, reference
1761 * fields are grouped together inside objects, increasing collector
1763 * Requires that all classes whose layout is known to native code be annotated
1764 * with [StructLayout (LayoutKind.Sequential)]
1765 * Value types have gc_aware_layout disabled by default, as per
1766 * what the default is for other runtimes.
1768 /* corlib is missing [StructLayout] directives in many places */
1769 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1770 if (!class->valuetype)
1771 gc_aware_layout = TRUE;
1774 /* Compute klass->has_references */
1776 * Process non-static fields first, since static fields might recursively
1777 * refer to the class itself.
1779 for (i = 0; i < top; i++) {
1782 field = &class->fields [i];
1784 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1785 ftype = mono_type_get_underlying_type (field->type);
1786 ftype = mono_type_get_basic_type_from_generic (ftype);
1787 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1788 class->has_references = TRUE;
1792 for (i = 0; i < top; i++) {
1795 field = &class->fields [i];
1797 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1798 ftype = mono_type_get_underlying_type (field->type);
1799 ftype = mono_type_get_basic_type_from_generic (ftype);
1800 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1801 class->has_static_refs = TRUE;
1805 for (i = 0; i < top; i++) {
1808 field = &class->fields [i];
1810 ftype = mono_type_get_underlying_type (field->type);
1811 ftype = mono_type_get_basic_type_from_generic (ftype);
1812 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1813 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1814 class->has_static_refs = TRUE;
1816 class->has_references = TRUE;
1821 * Compute field layout and total size (not considering static fields)
1825 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1826 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1828 if (gc_aware_layout)
1833 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1836 if (class->parent) {
1837 mono_class_setup_fields (class->parent);
1838 if (class->parent->exception_type) {
1839 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1842 real_size = class->parent->instance_size;
1844 real_size = sizeof (MonoObject);
1847 for (pass = 0; pass < passes; ++pass) {
1848 for (i = 0; i < top; i++){
1853 field = &class->fields [i];
1855 if (mono_field_is_deleted (field))
1857 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1860 ftype = mono_type_get_underlying_type (field->type);
1861 ftype = mono_type_get_basic_type_from_generic (ftype);
1862 if (gc_aware_layout) {
1863 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1872 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1873 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1874 /* This field is a hack inserted by MCS to empty structures */
1878 size = mono_type_size (field->type, &align);
1880 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1881 align = class->packing_size ? MIN (class->packing_size, align): align;
1882 /* if the field has managed references, we need to force-align it
1885 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1886 align = MAX (align, sizeof (gpointer));
1888 class->min_align = MAX (align, class->min_align);
1889 field->offset = real_size;
1891 field->offset += align - 1;
1892 field->offset &= ~(align - 1);
1894 /*TypeBuilders produce all sort of weird things*/
1895 g_assert (class->image->dynamic || field->offset > 0);
1896 real_size = field->offset + size;
1899 class->instance_size = MAX (real_size, class->instance_size);
1901 if (class->instance_size & (class->min_align - 1)) {
1902 class->instance_size += class->min_align - 1;
1903 class->instance_size &= ~(class->min_align - 1);
1907 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1909 for (i = 0; i < top; i++) {
1914 field = &class->fields [i];
1917 * There must be info about all the fields in a type if it
1918 * uses explicit layout.
1921 if (mono_field_is_deleted (field))
1923 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1926 size = mono_type_size (field->type, &align);
1927 align = class->packing_size ? MIN (class->packing_size, align): align;
1928 class->min_align = MAX (align, class->min_align);
1931 * When we get here, field->offset is already set by the
1932 * loader (for either runtime fields or fields loaded from metadata).
1933 * The offset is from the start of the object: this works for both
1934 * classes and valuetypes.
1936 field->offset += sizeof (MonoObject);
1937 ftype = mono_type_get_underlying_type (field->type);
1938 ftype = mono_type_get_basic_type_from_generic (ftype);
1939 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1940 if (field->offset % sizeof (gpointer)) {
1941 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1948 real_size = MAX (real_size, size + field->offset);
1950 class->instance_size = MAX (real_size, class->instance_size);
1951 if (class->instance_size & (class->min_align - 1)) {
1952 class->instance_size += class->min_align - 1;
1953 class->instance_size &= ~(class->min_align - 1);
1958 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1960 * For small structs, set min_align to at least the struct size to improve
1961 * performance, and since the JIT memset/memcpy code assumes this and generates
1962 * unaligned accesses otherwise. See #78990 for a testcase.
1964 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1965 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1968 mono_memory_barrier ();
1969 class->size_inited = 1;
1972 * Compute static field layout and size
1974 for (i = 0; i < top; i++){
1978 field = &class->fields [i];
1980 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1982 if (mono_field_is_deleted (field))
1985 if (mono_type_has_exceptions (field->type)) {
1986 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1990 size = mono_type_size (field->type, &align);
1991 field->offset = class->sizes.class_size;
1992 /*align is always non-zero here*/
1993 field->offset += align - 1;
1994 field->offset &= ~(align - 1);
1995 class->sizes.class_size = field->offset + size;
2000 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2004 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2005 method->klass = class;
2006 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2007 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2008 method->signature = sig;
2009 method->name = name;
2012 if (name [0] == '.') {
2013 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2015 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2021 * mono_class_setup_methods:
2024 * Initializes the 'methods' array in the klass.
2025 * Calling this method should be avoided if possible since it allocates a lot
2026 * of long-living MonoMethod structures.
2027 * Methods belonging to an interface are assigned a sequential slot starting
2030 * On failure this function sets class->exception_type
2033 mono_class_setup_methods (MonoClass *class)
2036 MonoMethod **methods;
2041 mono_loader_lock ();
2043 if (class->methods) {
2044 mono_loader_unlock ();
2048 if (class->generic_class) {
2050 MonoClass *gklass = class->generic_class->container_class;
2052 mono_class_init (gklass);
2053 if (!gklass->exception_type)
2054 mono_class_setup_methods (gklass);
2055 if (gklass->exception_type) {
2056 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2057 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2058 mono_loader_unlock ();
2062 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2063 class->method.count = gklass->method.count;
2064 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2066 for (i = 0; i < class->method.count; i++) {
2067 methods [i] = mono_class_inflate_generic_method_full_checked (
2068 gklass->methods [i], class, mono_class_get_context (class), &error);
2069 if (!mono_error_ok (&error)) {
2070 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2071 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)));
2074 mono_error_cleanup (&error);
2075 mono_loader_unlock ();
2079 } else if (class->rank) {
2081 MonoMethod *amethod;
2082 MonoMethodSignature *sig;
2083 int count_generic = 0, first_generic = 0;
2086 class->method.count = 3 + (class->rank > 1? 2: 1);
2088 mono_class_setup_interfaces (class, &error);
2089 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2091 if (class->interface_count) {
2092 count_generic = generic_array_methods (class);
2093 first_generic = class->method.count;
2094 class->method.count += class->interface_count * count_generic;
2097 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2099 sig = mono_metadata_signature_alloc (class->image, class->rank);
2100 sig->ret = &mono_defaults.void_class->byval_arg;
2101 sig->pinvoke = TRUE;
2102 sig->hasthis = TRUE;
2103 for (i = 0; i < class->rank; ++i)
2104 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2106 amethod = create_array_method (class, ".ctor", sig);
2107 methods [method_num++] = amethod;
2108 if (class->rank > 1) {
2109 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2110 sig->ret = &mono_defaults.void_class->byval_arg;
2111 sig->pinvoke = TRUE;
2112 sig->hasthis = TRUE;
2113 for (i = 0; i < class->rank * 2; ++i)
2114 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2116 amethod = create_array_method (class, ".ctor", sig);
2117 methods [method_num++] = amethod;
2119 /* element Get (idx11, [idx2, ...]) */
2120 sig = mono_metadata_signature_alloc (class->image, class->rank);
2121 sig->ret = &class->element_class->byval_arg;
2122 sig->pinvoke = TRUE;
2123 sig->hasthis = TRUE;
2124 for (i = 0; i < class->rank; ++i)
2125 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2126 amethod = create_array_method (class, "Get", sig);
2127 methods [method_num++] = amethod;
2128 /* element& Address (idx11, [idx2, ...]) */
2129 sig = mono_metadata_signature_alloc (class->image, class->rank);
2130 sig->ret = &class->element_class->this_arg;
2131 sig->pinvoke = TRUE;
2132 sig->hasthis = TRUE;
2133 for (i = 0; i < class->rank; ++i)
2134 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2135 amethod = create_array_method (class, "Address", sig);
2136 methods [method_num++] = amethod;
2137 /* void Set (idx11, [idx2, ...], element) */
2138 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2139 sig->ret = &mono_defaults.void_class->byval_arg;
2140 sig->pinvoke = TRUE;
2141 sig->hasthis = TRUE;
2142 for (i = 0; i < class->rank; ++i)
2143 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2144 sig->params [i] = &class->element_class->byval_arg;
2145 amethod = create_array_method (class, "Set", sig);
2146 methods [method_num++] = amethod;
2148 for (i = 0; i < class->interface_count; i++)
2149 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2151 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2152 for (i = 0; i < class->method.count; ++i) {
2153 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2154 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2158 if (MONO_CLASS_IS_INTERFACE (class)) {
2160 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2161 for (i = 0; i < class->method.count; ++i) {
2162 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2163 methods [i]->slot = slot++;
2167 /* Needed because of the double-checking locking pattern */
2168 mono_memory_barrier ();
2170 class->methods = methods;
2172 if (mono_debugger_class_loaded_methods_func)
2173 mono_debugger_class_loaded_methods_func (class);
2175 mono_loader_unlock ();
2179 * mono_class_get_method_by_index:
2181 * Returns class->methods [index], initializing class->methods if neccesary.
2183 * LOCKING: Acquires the loader lock.
2186 mono_class_get_method_by_index (MonoClass *class, int index)
2188 /* Avoid calling setup_methods () if possible */
2189 if (class->generic_class && !class->methods) {
2190 MonoClass *gklass = class->generic_class->container_class;
2193 m = mono_class_inflate_generic_method_full (
2194 gklass->methods [index], class, mono_class_get_context (class));
2196 * If setup_methods () is called later for this class, no duplicates are created,
2197 * since inflate_generic_method guarantees that only one instance of a method
2198 * is created for each context.
2201 mono_class_setup_methods (class);
2202 g_assert (m == class->methods [index]);
2206 mono_class_setup_methods (class);
2207 if (class->exception_type) /*FIXME do proper error handling*/
2209 g_assert (index >= 0 && index < class->method.count);
2210 return class->methods [index];
2215 * mono_class_get_inflated_method:
2217 * Given an inflated class CLASS and a method METHOD which should be a method of
2218 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2221 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2223 MonoClass *gklass = class->generic_class->container_class;
2226 g_assert (method->klass == gklass);
2228 mono_class_setup_methods (gklass);
2229 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2231 for (i = 0; i < gklass->method.count; ++i) {
2232 if (gklass->methods [i] == method) {
2234 return class->methods [i];
2236 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2244 * mono_class_get_vtable_entry:
2246 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2247 * LOCKING: Acquires the loader lock.
2250 mono_class_get_vtable_entry (MonoClass *class, int offset)
2254 if (class->rank == 1) {
2256 * szarrays do not overwrite any methods of Array, so we can avoid
2257 * initializing their vtables in some cases.
2259 mono_class_setup_vtable (class->parent);
2260 if (offset < class->parent->vtable_size)
2261 return class->parent->vtable [offset];
2264 if (class->generic_class) {
2265 MonoClass *gklass = class->generic_class->container_class;
2266 mono_class_setup_vtable (gklass);
2267 m = gklass->vtable [offset];
2269 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2271 mono_class_setup_vtable (class);
2272 if (class->exception_type)
2274 m = class->vtable [offset];
2281 * mono_class_get_vtable_size:
2283 * Return the vtable size for KLASS.
2286 mono_class_get_vtable_size (MonoClass *klass)
2288 mono_class_setup_vtable (klass);
2290 return klass->vtable_size;
2293 /*This method can fail the class.*/
2295 mono_class_setup_properties (MonoClass *class)
2297 guint startm, endm, i, j;
2298 guint32 cols [MONO_PROPERTY_SIZE];
2299 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2300 MonoProperty *properties;
2303 if (class->ext && class->ext->properties)
2306 mono_loader_lock ();
2308 if (class->ext && class->ext->properties) {
2309 mono_loader_unlock ();
2313 mono_class_alloc_ext (class);
2315 if (class->generic_class) {
2316 MonoClass *gklass = class->generic_class->container_class;
2318 mono_class_init (gklass);
2319 mono_class_setup_properties (gklass);
2320 if (gklass->exception_type) {
2321 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2322 mono_loader_unlock ();
2326 class->ext->property = gklass->ext->property;
2328 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2330 for (i = 0; i < class->ext->property.count; i++) {
2331 MonoProperty *prop = &properties [i];
2333 *prop = gklass->ext->properties [i];
2336 prop->get = mono_class_inflate_generic_method_full (
2337 prop->get, class, mono_class_get_context (class));
2339 prop->set = mono_class_inflate_generic_method_full (
2340 prop->set, class, mono_class_get_context (class));
2342 prop->parent = class;
2345 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2346 int count = last - first;
2349 mono_class_setup_methods (class);
2350 if (class->exception_type) {
2351 mono_loader_unlock ();
2356 class->ext->property.first = first;
2357 class->ext->property.count = count;
2358 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2359 for (i = first; i < last; ++i) {
2360 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2361 properties [i - first].parent = class;
2362 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2363 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2365 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2366 for (j = startm; j < endm; ++j) {
2369 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2371 if (class->image->uncompressed_metadata)
2372 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2373 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2375 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2377 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2378 case METHOD_SEMANTIC_SETTER:
2379 properties [i - first].set = method;
2381 case METHOD_SEMANTIC_GETTER:
2382 properties [i - first].get = method;
2390 /*Flush any pending writes as we do double checked locking on class->properties */
2391 mono_memory_barrier ();
2393 /* Leave this assignment as the last op in the function */
2394 class->ext->properties = properties;
2396 mono_loader_unlock ();
2400 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2402 MonoMethod **om, **retval;
2405 for (om = methods, count = 0; *om; ++om, ++count)
2408 retval = g_new0 (MonoMethod*, count + 1);
2410 for (om = methods, count = 0; *om; ++om, ++count)
2411 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2416 /*This method can fail the class.*/
2418 mono_class_setup_events (MonoClass *class)
2421 guint startm, endm, i, j;
2422 guint32 cols [MONO_EVENT_SIZE];
2423 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2427 if (class->ext && class->ext->events)
2430 mono_loader_lock ();
2432 if (class->ext && class->ext->events) {
2433 mono_loader_unlock ();
2437 mono_class_alloc_ext (class);
2439 if (class->generic_class) {
2440 MonoClass *gklass = class->generic_class->container_class;
2441 MonoGenericContext *context;
2443 mono_class_setup_events (gklass);
2444 if (gklass->exception_type) {
2445 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2446 mono_loader_unlock ();
2450 class->ext->event = gklass->ext->event;
2451 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2453 if (class->ext->event.count)
2454 context = mono_class_get_context (class);
2456 for (i = 0; i < class->ext->event.count; i++) {
2457 MonoEvent *event = &class->ext->events [i];
2458 MonoEvent *gevent = &gklass->ext->events [i];
2460 event->parent = class;
2461 event->name = gevent->name;
2462 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2463 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2464 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2465 #ifndef MONO_SMALL_CONFIG
2466 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2468 event->attrs = gevent->attrs;
2471 mono_loader_unlock ();
2475 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2476 count = last - first;
2479 mono_class_setup_methods (class);
2480 if (class->exception_type) {
2481 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2482 mono_loader_unlock ();
2486 class->ext->event.first = first;
2487 class->ext->event.count = count;
2488 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2489 for (i = first; i < last; ++i) {
2490 MonoEvent *event = &events [i - first];
2492 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2493 event->parent = class;
2494 event->attrs = cols [MONO_EVENT_FLAGS];
2495 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2497 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2498 for (j = startm; j < endm; ++j) {
2501 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2503 if (class->image->uncompressed_metadata)
2504 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2505 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2507 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2509 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2510 case METHOD_SEMANTIC_ADD_ON:
2511 event->add = method;
2513 case METHOD_SEMANTIC_REMOVE_ON:
2514 event->remove = method;
2516 case METHOD_SEMANTIC_FIRE:
2517 event->raise = method;
2519 case METHOD_SEMANTIC_OTHER: {
2520 #ifndef MONO_SMALL_CONFIG
2523 if (event->other == NULL) {
2524 event->other = g_new0 (MonoMethod*, 2);
2526 while (event->other [n])
2528 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2530 event->other [n] = method;
2531 /* NULL terminated */
2532 event->other [n + 1] = NULL;
2541 /*Flush any pending writes as we do double checked locking on class->properties */
2542 mono_memory_barrier ();
2544 /* Leave this assignment as the last op in the function */
2545 class->ext->events = events;
2547 mono_loader_unlock ();
2551 * Global pool of interface IDs, represented as a bitset.
2552 * LOCKING: this is supposed to be accessed with the loader lock held.
2554 static MonoBitSet *global_interface_bitset = NULL;
2557 * mono_unload_interface_ids:
2558 * @bitset: bit set of interface IDs
2560 * When an image is unloaded, the interface IDs associated with
2561 * the image are put back in the global pool of IDs so the numbers
2565 mono_unload_interface_ids (MonoBitSet *bitset)
2567 mono_loader_lock ();
2568 mono_bitset_sub (global_interface_bitset, bitset);
2569 mono_loader_unlock ();
2573 mono_unload_interface_id (MonoClass *class)
2575 if (global_interface_bitset && class->interface_id) {
2576 mono_loader_lock ();
2577 mono_bitset_clear (global_interface_bitset, class->interface_id);
2578 mono_loader_unlock ();
2583 * mono_get_unique_iid:
2586 * Assign a unique integer ID to the interface represented by @class.
2587 * The ID will positive and as small as possible.
2588 * LOCKING: this is supposed to be called with the loader lock held.
2589 * Returns: the new ID.
2592 mono_get_unique_iid (MonoClass *class)
2596 g_assert (MONO_CLASS_IS_INTERFACE (class));
2598 if (!global_interface_bitset) {
2599 global_interface_bitset = mono_bitset_new (128, 0);
2602 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2604 int old_size = mono_bitset_size (global_interface_bitset);
2605 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2606 mono_bitset_free (global_interface_bitset);
2607 global_interface_bitset = new_set;
2610 mono_bitset_set (global_interface_bitset, iid);
2611 /* set the bit also in the per-image set */
2612 if (!class->generic_class) {
2613 if (class->image->interface_bitset) {
2614 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2615 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2616 mono_bitset_free (class->image->interface_bitset);
2617 class->image->interface_bitset = new_set;
2620 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2622 mono_bitset_set (class->image->interface_bitset, iid);
2625 #ifndef MONO_SMALL_CONFIG
2626 if (mono_print_vtable) {
2628 char *type_name = mono_type_full_name (&class->byval_arg);
2629 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2630 generic_id = class->generic_class->context.class_inst->id;
2631 g_assert (generic_id != 0);
2635 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2640 g_assert (iid <= 65535);
2645 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2650 mono_class_setup_interfaces (klass, error);
2651 if (!mono_error_ok (error))
2654 for (i = 0; i < klass->interface_count; i++) {
2655 ic = klass->interfaces [i];
2658 *res = g_ptr_array_new ();
2659 g_ptr_array_add (*res, ic);
2660 mono_class_init (ic);
2661 if (ic->exception_type) {
2662 mono_error_set_type_load_class (error, ic, "Error Loading class");
2666 collect_implemented_interfaces_aux (ic, res, error);
2667 if (!mono_error_ok (error))
2673 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2675 GPtrArray *res = NULL;
2677 collect_implemented_interfaces_aux (klass, &res, error);
2678 if (!mono_error_ok (error)) {
2680 g_ptr_array_free (res, TRUE);
2687 compare_interface_ids (const void *p_key, const void *p_element) {
2688 const MonoClass *key = p_key;
2689 const MonoClass *element = *(MonoClass**) p_element;
2691 return (key->interface_id - element->interface_id);
2694 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2696 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2697 MonoClass **result = mono_binary_search (
2699 klass->interfaces_packed,
2700 klass->interface_offsets_count,
2701 sizeof (MonoClass *),
2702 compare_interface_ids);
2704 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2711 * mono_class_interface_offset_with_variance:
2713 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2714 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2716 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2718 * FIXME figure out MS disambiguation rules and fix this function.
2721 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2722 int i = mono_class_interface_offset (klass, itf);
2723 *non_exact_match = FALSE;
2727 if (!mono_class_has_variant_generic_params (itf))
2730 for (i = 0; i < klass->interface_offsets_count; i++) {
2731 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2732 *non_exact_match = TRUE;
2733 return klass->interface_offsets_packed [i];
2741 print_implemented_interfaces (MonoClass *klass) {
2744 GPtrArray *ifaces = NULL;
2746 int ancestor_level = 0;
2748 name = mono_type_get_full_name (klass);
2749 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2752 for (i = 0; i < klass->interface_offsets_count; i++)
2753 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2754 klass->interfaces_packed [i]->interface_id,
2755 klass->interface_offsets_packed [i],
2756 klass->interfaces_packed [i]->method.count,
2757 klass->interfaces_packed [i]->name_space,
2758 klass->interfaces_packed [i]->name );
2759 printf ("Interface flags: ");
2760 for (i = 0; i <= klass->max_interface_id; i++)
2761 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2762 printf ("(%d,T)", i);
2764 printf ("(%d,F)", i);
2766 printf ("Dump interface flags:");
2767 #ifdef COMPRESSED_INTERFACE_BITMAP
2769 const uint8_t* p = klass->interface_bitmap;
2770 i = klass->max_interface_id;
2772 printf (" %d x 00 %02X", p [0], p [1]);
2778 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2779 printf (" %02X", klass->interface_bitmap [i]);
2782 while (klass != NULL) {
2783 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2784 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2785 if (!mono_error_ok (&error)) {
2786 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2787 mono_error_cleanup (&error);
2788 } else if (ifaces) {
2789 for (i = 0; i < ifaces->len; i++) {
2790 MonoClass *ic = g_ptr_array_index (ifaces, i);
2791 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2792 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2794 mono_class_interface_offset (klass, ic),
2799 g_ptr_array_free (ifaces, TRUE);
2802 klass = klass->parent;
2807 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2810 args [0] = &arg0->byval_arg;
2812 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2816 array_class_get_if_rank (MonoClass *class, guint rank)
2818 return rank ? mono_array_class_get (class, rank) : class;
2822 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2824 valuetype_types [0] = eclass;
2825 if (eclass == mono_defaults.int16_class)
2826 valuetype_types [1] = mono_defaults.uint16_class;
2827 else if (eclass == mono_defaults.uint16_class)
2828 valuetype_types [1] = mono_defaults.int16_class;
2829 else if (eclass == mono_defaults.int32_class)
2830 valuetype_types [1] = mono_defaults.uint32_class;
2831 else if (eclass == mono_defaults.uint32_class)
2832 valuetype_types [1] = mono_defaults.int32_class;
2833 else if (eclass == mono_defaults.int64_class)
2834 valuetype_types [1] = mono_defaults.uint64_class;
2835 else if (eclass == mono_defaults.uint64_class)
2836 valuetype_types [1] = mono_defaults.int64_class;
2837 else if (eclass == mono_defaults.byte_class)
2838 valuetype_types [1] = mono_defaults.sbyte_class;
2839 else if (eclass == mono_defaults.sbyte_class)
2840 valuetype_types [1] = mono_defaults.byte_class;
2841 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2842 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2845 /* this won't be needed once bug #325495 is completely fixed
2846 * though we'll need something similar to know which interfaces to allow
2847 * in arrays when they'll be lazyly created
2849 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2850 * MS returns diferrent types based on which instance is called. For example:
2851 * object obj = new byte[10][];
2852 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2853 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2856 * Fixing this should kill quite some code, save some bits and improve compatibility.
2859 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2861 MonoClass *eclass = class->element_class;
2862 static MonoClass* generic_icollection_class = NULL;
2863 static MonoClass* generic_ienumerable_class = NULL;
2864 static MonoClass* generic_ienumerator_class = NULL;
2865 static MonoClass* generic_ireadonlylist_class = NULL;
2866 static MonoClass* generic_ireadonlycollection_class = NULL;
2867 MonoClass *valuetype_types[2] = { NULL, NULL };
2868 MonoClass **interfaces = NULL;
2869 int i, nifaces, interface_count, real_count, original_rank;
2871 gboolean internal_enumerator;
2872 gboolean eclass_is_valuetype;
2874 if (!mono_defaults.generic_ilist_class) {
2878 internal_enumerator = FALSE;
2879 eclass_is_valuetype = FALSE;
2880 original_rank = eclass->rank;
2881 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2882 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2884 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2886 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2887 original_rank = eclass->rank;
2889 eclass = eclass->element_class;
2890 internal_enumerator = TRUE;
2891 *is_enumerator = TRUE;
2899 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2900 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2902 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2904 if (!generic_icollection_class) {
2905 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2906 "System.Collections.Generic", "ICollection`1");
2907 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2908 "System.Collections.Generic", "IEnumerable`1");
2909 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2910 "System.Collections.Generic", "IEnumerator`1");
2911 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2912 "System.Collections.Generic", "IReadOnlyList`1");
2913 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2914 "System.Collections.Generic", "IReadOnlyCollection`1");
2917 mono_class_init (eclass);
2920 * Arrays in 2.0 need to implement a number of generic interfaces
2921 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2922 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2923 * We collect the types needed to build the
2924 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2925 * the generic interfaces needed to implement.
2927 nifaces = generic_ireadonlylist_class ? 5 : 3;
2928 if (eclass->valuetype) {
2929 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2931 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2932 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2933 if (internal_enumerator) {
2935 if (valuetype_types [1])
2939 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2940 interfaces [0] = valuetype_types [0];
2941 if (valuetype_types [1])
2942 interfaces [nifaces] = valuetype_types [1];
2944 eclass_is_valuetype = TRUE;
2947 int idepth = eclass->idepth;
2948 if (!internal_enumerator)
2951 // FIXME: This doesn't seem to work/required for generic params
2952 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (eclass->image->dynamic && !eclass->wastypebuilder)))
2953 mono_class_setup_interface_offsets (eclass);
2955 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
2956 /* we add object for interfaces and the supertypes for the other
2957 * types. The last of the supertypes is the element class itself which we
2958 * already created the explicit interfaces for (so we include it for IEnumerator
2959 * and exclude it for arrays).
2961 if (MONO_CLASS_IS_INTERFACE (eclass))
2964 interface_count += idepth;
2965 if (eclass->rank && eclass->element_class->valuetype) {
2966 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
2967 if (valuetype_types [1])
2970 /* IList, ICollection, IEnumerable, IReadOnlyList */
2971 interface_count *= nifaces;
2972 real_count = interface_count;
2973 if (internal_enumerator) {
2974 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
2975 if (valuetype_types [1])
2978 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2979 if (MONO_CLASS_IS_INTERFACE (eclass)) {
2980 interfaces [0] = mono_defaults.object_class;
2984 for (i = 0; i < idepth; i++) {
2985 mono_class_init (eclass->supertypes [i]);
2986 interfaces [j] = eclass->supertypes [i];
2990 if (all_interfaces) {
2991 for (i = 0; i < eclass->interface_offsets_count; i++) {
2992 interfaces [j] = eclass->interfaces_packed [i];
2996 for (i = 0; i < eclass->interface_count; i++) {
2997 interfaces [j] = eclass->interfaces [i];
3001 if (valuetype_types [1]) {
3002 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3007 /* instantiate the generic interfaces */
3008 for (i = 0; i < interface_count; i += nifaces) {
3009 MonoClass *iface = interfaces [i];
3011 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3012 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3013 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3014 if (generic_ireadonlylist_class) {
3015 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3016 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3019 if (internal_enumerator) {
3021 /* instantiate IEnumerator<iface> */
3022 for (i = 0; i < interface_count; i++) {
3023 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3025 j = interface_count;
3026 if (!eclass_is_valuetype) {
3027 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3028 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3031 for (i = 0; i < eclass->idepth; i++) {
3032 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3036 for (i = 0; i < eclass->interface_offsets_count; i++) {
3037 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3041 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3043 if (valuetype_types [1])
3044 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3048 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3049 for (i = 0; i < real_count; ++i) {
3050 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3051 g_print ("%s implements %s\n", type_name, name);
3062 find_array_interface (MonoClass *klass, const char *name)
3065 for (i = 0; i < klass->interface_count; ++i) {
3066 if (strcmp (klass->interfaces [i]->name, name) == 0)
3073 * Return the number of virtual methods.
3074 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3075 * Return -1 on failure.
3076 * FIXME It would be nice if this information could be cached somewhere.
3079 count_virtual_methods (MonoClass *class)
3083 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3085 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3086 mono_class_setup_methods (class);
3087 if (class->exception_type)
3090 for (i = 0; i < class->method.count; ++i) {
3091 flags = class->methods [i]->flags;
3092 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3096 for (i = 0; i < class->method.count; ++i) {
3097 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3099 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3107 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3115 m = (l + num_ifaces) / 2;
3116 if (interfaces_full [m] == ic)
3118 if (l == num_ifaces)
3120 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3129 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3131 int i = find_interface (num_ifaces, interfaces_full, ic);
3133 return interface_offsets_full [i];
3138 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3140 int i = find_interface (num_ifaces, interfaces_full, ic);
3144 interface_offsets_full [i] = offset;
3147 for (i = 0; i < num_ifaces; ++i) {
3148 if (interfaces_full [i]) {
3150 if (interfaces_full [i]->interface_id < ic->interface_id)
3153 while (end < num_ifaces && interfaces_full [end]) end++;
3154 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3155 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3157 interfaces_full [i] = ic;
3158 interface_offsets_full [i] = offset;
3164 #ifdef COMPRESSED_INTERFACE_BITMAP
3167 * Compressed interface bitmap design.
3169 * Interface bitmaps take a large amount of memory, because their size is
3170 * linear with the maximum interface id assigned in the process (each interface
3171 * is assigned a unique id as it is loaded). The number of interface classes
3172 * is high because of the many implicit interfaces implemented by arrays (we'll
3173 * need to lazy-load them in the future).
3174 * Most classes implement a very small number of interfaces, so the bitmap is
3175 * sparse. This bitmap needs to be checked by interface casts, so access to the
3176 * needed bit must be fast and doable with few jit instructions.
3178 * The current compression format is as follows:
3179 * *) it is a sequence of one or more two-byte elements
3180 * *) the first byte in the element is the count of empty bitmap bytes
3181 * at the current bitmap position
3182 * *) the second byte in the element is an actual bitmap byte at the current
3185 * As an example, the following compressed bitmap bytes:
3186 * 0x07 0x01 0x00 0x7
3187 * correspond to the following bitmap:
3188 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3190 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3191 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3192 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3196 * mono_compress_bitmap:
3197 * @dest: destination buffer
3198 * @bitmap: bitmap buffer
3199 * @size: size of @bitmap in bytes
3201 * This is a mono internal function.
3202 * The @bitmap data is compressed into a format that is small but
3203 * still searchable in few instructions by the JIT and runtime.
3204 * The compressed data is stored in the buffer pointed to by the
3205 * @dest array. Passing a #NULL value for @dest allows to just compute
3206 * the size of the buffer.
3207 * This compression algorithm assumes the bits set in the bitmap are
3208 * few and far between, like in interface bitmaps.
3209 * Returns: the size of the compressed bitmap in bytes.
3212 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3216 const uint8_t *end = bitmap + size;
3217 while (bitmap < end) {
3218 if (*bitmap || numz == 255) {
3242 * mono_class_interface_match:
3243 * @bitmap: a compressed bitmap buffer
3244 * @id: the index to check in the bitmap
3246 * This is a mono internal function.
3247 * Checks if a bit is set in a compressed interface bitmap. @id must
3248 * be already checked for being smaller than the maximum id encoded in the
3251 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3255 mono_class_interface_match (const uint8_t *bitmap, int id)
3258 id -= bitmap [0] * 8;
3262 return bitmap [1] & (1 << id);
3271 * LOCKING: this is supposed to be called with the loader lock held.
3272 * Return -1 on failure and set exception_type
3275 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3279 int i, j, max_iid, num_ifaces;
3280 MonoClass **interfaces_full = NULL;
3281 int *interface_offsets_full = NULL;
3283 GPtrArray **ifaces_array = NULL;
3284 int interface_offsets_count;
3285 MonoClass **array_interfaces = NULL;
3286 int num_array_interfaces;
3287 int is_enumerator = FALSE;
3289 mono_class_setup_supertypes (class);
3291 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3292 * implicit interfaces have the property that they are assigned the same slot in the
3293 * vtables for compatible interfaces
3295 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3297 /* compute maximum number of slots and maximum interface id */
3299 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3300 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3301 for (j = 0; j < class->idepth; j++) {
3302 k = class->supertypes [j];
3303 num_ifaces += k->interface_count;
3304 for (i = 0; i < k->interface_count; i++) {
3305 ic = k->interfaces [i];
3308 mono_class_init (ic);
3310 if (max_iid < ic->interface_id)
3311 max_iid = ic->interface_id;
3313 ifaces = mono_class_get_implemented_interfaces (k, &error);
3314 if (!mono_error_ok (&error)) {
3315 char *name = mono_type_get_full_name (k);
3316 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)));
3318 mono_error_cleanup (&error);
3323 num_ifaces += ifaces->len;
3324 for (i = 0; i < ifaces->len; ++i) {
3325 ic = g_ptr_array_index (ifaces, i);
3326 if (max_iid < ic->interface_id)
3327 max_iid = ic->interface_id;
3329 ifaces_array [j] = ifaces;
3333 for (i = 0; i < num_array_interfaces; ++i) {
3334 ic = array_interfaces [i];
3335 mono_class_init (ic);
3336 if (max_iid < ic->interface_id)
3337 max_iid = ic->interface_id;
3340 if (MONO_CLASS_IS_INTERFACE (class)) {
3342 if (max_iid < class->interface_id)
3343 max_iid = class->interface_id;
3345 class->max_interface_id = max_iid;
3346 /* compute vtable offset for interfaces */
3347 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3348 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3350 for (i = 0; i < num_ifaces; i++) {
3351 interface_offsets_full [i] = -1;
3354 /* skip the current class */
3355 for (j = 0; j < class->idepth - 1; j++) {
3356 k = class->supertypes [j];
3357 ifaces = ifaces_array [j];
3360 for (i = 0; i < ifaces->len; ++i) {
3362 ic = g_ptr_array_index (ifaces, i);
3364 /*Force the sharing of interface offsets between parent and subtypes.*/
3365 io = mono_class_interface_offset (k, ic);
3367 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3372 g_assert (class == class->supertypes [class->idepth - 1]);
3373 ifaces = ifaces_array [class->idepth - 1];
3375 for (i = 0; i < ifaces->len; ++i) {
3377 ic = g_ptr_array_index (ifaces, i);
3378 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3380 count = count_virtual_methods (ic);
3382 char *name = mono_type_get_full_name (ic);
3383 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3392 if (MONO_CLASS_IS_INTERFACE (class))
3393 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3395 if (num_array_interfaces) {
3396 if (is_enumerator) {
3397 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3398 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3399 g_assert (ienumerator_offset >= 0);
3400 for (i = 0; i < num_array_interfaces; ++i) {
3401 ic = array_interfaces [i];
3402 if (strcmp (ic->name, "IEnumerator`1") == 0)
3403 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3405 g_assert_not_reached ();
3406 /*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);*/
3409 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3410 int ilist_iface_idx = find_array_interface (class, "IList`1");
3411 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3412 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3413 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3414 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3415 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3416 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3417 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3418 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3419 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3420 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3421 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3422 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3423 for (i = 0; i < num_array_interfaces; ++i) {
3425 ic = array_interfaces [i];
3426 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3427 offset = ilist_offset;
3428 else if (strcmp (ic->name, "ICollection`1") == 0)
3429 offset = icollection_offset;
3430 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3431 offset = ienumerable_offset;
3432 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3433 offset = ireadonlylist_offset;
3434 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3435 offset = ireadonlycollection_offset;
3437 g_assert_not_reached ();
3438 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3439 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3444 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3445 if (interface_offsets_full [i] != -1) {
3446 interface_offsets_count ++;
3451 * We might get called multiple times:
3452 * - mono_class_init ()
3453 * - mono_class_setup_vtable ().
3454 * - mono_class_setup_interface_offsets ().
3455 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3456 * means we have to overwrite those when called from other places (#4440).
3458 if (class->interfaces_packed && !overwrite) {
3459 g_assert (class->interface_offsets_count == interface_offsets_count);
3463 class->interface_offsets_count = interface_offsets_count;
3464 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3465 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3466 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3467 #ifdef COMPRESSED_INTERFACE_BITMAP
3468 bitmap = g_malloc0 (bsize);
3470 bitmap = mono_class_alloc0 (class, bsize);
3472 for (i = 0; i < interface_offsets_count; i++) {
3473 int id = interfaces_full [i]->interface_id;
3474 bitmap [id >> 3] |= (1 << (id & 7));
3475 class->interfaces_packed [i] = interfaces_full [i];
3476 class->interface_offsets_packed [i] = interface_offsets_full [i];
3477 /*if (num_array_interfaces)
3478 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]);*/
3480 #ifdef COMPRESSED_INTERFACE_BITMAP
3481 i = mono_compress_bitmap (NULL, bitmap, bsize);
3482 class->interface_bitmap = mono_class_alloc0 (class, i);
3483 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3486 class->interface_bitmap = bitmap;
3491 g_free (interfaces_full);
3492 g_free (interface_offsets_full);
3493 g_free (array_interfaces);
3494 for (i = 0; i < class->idepth; i++) {
3495 ifaces = ifaces_array [i];
3497 g_ptr_array_free (ifaces, TRUE);
3499 g_free (ifaces_array);
3501 //printf ("JUST DONE: ");
3502 //print_implemented_interfaces (class);
3508 * Setup interface offsets for interfaces.
3510 * - class->max_interface_id
3511 * - class->interface_offsets_count
3512 * - class->interfaces_packed
3513 * - class->interface_offsets_packed
3514 * - class->interface_bitmap
3516 * This function can fail @class.
3519 mono_class_setup_interface_offsets (MonoClass *class)
3521 mono_loader_lock ();
3523 setup_interface_offsets (class, 0, FALSE);
3525 mono_loader_unlock ();
3528 /*Checks if @klass has @parent as one of it's parents type gtd
3532 * Bar<T> : Foo<Bar<Bar<T>>>
3536 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3538 klass = mono_class_get_generic_type_definition (klass);
3539 parent = mono_class_get_generic_type_definition (parent);
3540 mono_class_setup_supertypes (klass);
3541 mono_class_setup_supertypes (parent);
3543 return klass->idepth >= parent->idepth &&
3544 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3548 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3550 MonoGenericInst *ginst;
3552 if (!class->generic_class) {
3553 mono_class_setup_vtable_full (class, in_setup);
3554 return class->exception_type == 0;
3557 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3558 if (class->generic_class->container_class->exception_type) {
3559 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3563 ginst = class->generic_class->context.class_inst;
3564 for (i = 0; i < ginst->type_argc; ++i) {
3566 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3568 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3569 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3570 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3572 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3573 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3581 * mono_class_setup_vtable:
3583 * Creates the generic vtable of CLASS.
3584 * Initializes the following fields in MonoClass:
3587 * Plus all the fields initialized by setup_interface_offsets ().
3588 * If there is an error during vtable construction, class->exception_type is set.
3590 * LOCKING: Acquires the loader lock.
3593 mono_class_setup_vtable (MonoClass *class)
3595 mono_class_setup_vtable_full (class, NULL);
3599 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3601 MonoMethod **overrides;
3602 MonoGenericContext *context;
3610 if (mono_debug_using_mono_debugger ())
3611 /* The debugger currently depends on this */
3612 mono_class_setup_methods (class);
3614 if (MONO_CLASS_IS_INTERFACE (class)) {
3615 /* This sets method->slot for all methods if this is an interface */
3616 mono_class_setup_methods (class);
3620 if (class->exception_type)
3623 if (g_list_find (in_setup, class))
3626 mono_loader_lock ();
3628 if (class->vtable) {
3629 mono_loader_unlock ();
3633 mono_stats.generic_vtable_count ++;
3634 in_setup = g_list_prepend (in_setup, class);
3636 if (class->generic_class) {
3637 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3638 mono_loader_unlock ();
3639 g_list_remove (in_setup, class);
3643 context = mono_class_get_context (class);
3644 type_token = class->generic_class->container_class->type_token;
3646 context = (MonoGenericContext *) class->generic_container;
3647 type_token = class->type_token;
3650 if (class->image->dynamic) {
3651 /* Generic instances can have zero method overrides without causing any harm.
3652 * This is true since we don't do layout all over again for them, we simply inflate
3653 * the layout of the parent.
3655 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3657 /* The following call fails if there are missing methods in the type */
3658 /* FIXME it's probably a good idea to avoid this for generic instances. */
3659 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3663 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3665 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3669 mono_loader_unlock ();
3670 g_list_remove (in_setup, class);
3675 #define DEBUG_INTERFACE_VTABLE_CODE 0
3676 #define TRACE_INTERFACE_VTABLE_CODE 0
3677 #define VERIFY_INTERFACE_VTABLE_CODE 0
3678 #define VTABLE_SELECTOR (1)
3680 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3681 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3682 if (!(VTABLE_SELECTOR)) break; \
3686 #define DEBUG_INTERFACE_VTABLE(stmt)
3689 #if TRACE_INTERFACE_VTABLE_CODE
3690 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3691 if (!(VTABLE_SELECTOR)) break; \
3695 #define TRACE_INTERFACE_VTABLE(stmt)
3698 #if VERIFY_INTERFACE_VTABLE_CODE
3699 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3700 if (!(VTABLE_SELECTOR)) break; \
3704 #define VERIFY_INTERFACE_VTABLE(stmt)
3708 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3710 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3714 GString *res = g_string_new ("");
3716 g_string_append_c (res, '(');
3717 for (i = 0; i < sig->param_count; ++i) {
3719 g_string_append_c (res, ',');
3720 mono_type_get_desc (res, sig->params [i], include_namespace);
3722 g_string_append (res, ")=>");
3723 if (sig->ret != NULL) {
3724 mono_type_get_desc (res, sig->ret, include_namespace);
3726 g_string_append (res, "NULL");
3729 g_string_free (res, FALSE);
3733 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3734 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3735 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3736 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3744 is_wcf_hack_disabled (void)
3746 static gboolean disabled;
3747 static gboolean inited = FALSE;
3749 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3756 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) {
3757 MonoMethodSignature *cmsig, *imsig;
3758 if (strcmp (im->name, cm->name) == 0) {
3759 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3760 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3763 if (! slot_is_empty) {
3764 if (require_newslot) {
3765 if (! interface_is_explicitly_implemented_by_class) {
3766 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3769 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3770 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3774 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3777 cmsig = mono_method_signature (cm);
3778 imsig = mono_method_signature (im);
3779 if (!cmsig || !imsig) {
3780 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3784 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3785 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3786 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3787 TRACE_INTERFACE_VTABLE (printf ("]"));
3790 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3791 /* CAS - SecurityAction.InheritanceDemand on interface */
3792 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3793 mono_secman_inheritancedemand_method (cm, im);
3796 if (mono_security_core_clr_enabled ())
3797 mono_security_core_clr_check_override (class, cm, im);
3799 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3800 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3801 char *body_name = mono_method_full_name (cm, TRUE);
3802 char *decl_name = mono_method_full_name (im, TRUE);
3803 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));
3811 MonoClass *ic = im->klass;
3812 const char *ic_name_space = ic->name_space;
3813 const char *ic_name = ic->name;
3816 if (! require_newslot) {
3817 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3820 if (cm->klass->rank == 0) {
3821 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3824 cmsig = mono_method_signature (cm);
3825 imsig = mono_method_signature (im);
3826 if (!cmsig || !imsig) {
3827 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3831 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3832 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3833 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3834 TRACE_INTERFACE_VTABLE (printf ("]"));
3837 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3838 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3841 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3842 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3845 if ((ic_name == NULL) || ((strcmp (ic_name, "IEnumerable`1") != 0) && (strcmp (ic_name, "ICollection`1") != 0) && (strcmp (ic_name, "IList`1") != 0) && (strcmp (ic_name, "IReadOnlyList`1") != 0) && (strcmp (ic_name, "IReadOnlyCollection`1") != 0))) {
3846 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3850 subname = strstr (cm->name, ic_name_space);
3851 if (subname != cm->name) {
3852 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3855 subname += strlen (ic_name_space);
3856 if (subname [0] != '.') {
3857 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3861 if (strstr (subname, ic_name) != subname) {
3862 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3865 subname += strlen (ic_name);
3866 if (subname [0] != '.') {
3867 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3871 if (strcmp (subname, im->name) != 0) {
3872 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3876 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3877 /* CAS - SecurityAction.InheritanceDemand on interface */
3878 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3879 mono_secman_inheritancedemand_method (cm, im);
3882 if (mono_security_core_clr_enabled ())
3883 mono_security_core_clr_check_override (class, cm, im);
3885 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3886 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3887 char *body_name = mono_method_full_name (cm, TRUE);
3888 char *decl_name = mono_method_full_name (im, TRUE);
3889 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));
3899 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3901 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3902 MonoMethod *method = key;
3903 MonoMethod *override = value;
3904 MonoClass *method_class = mono_method_get_class (method);
3905 MonoClass *override_class = mono_method_get_class (override);
3907 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3908 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3909 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3912 print_overrides (GHashTable *override_map, const char *message) {
3914 printf ("Override map \"%s\" START:\n", message);
3915 g_hash_table_foreach (override_map, foreach_override, NULL);
3916 printf ("Override map \"%s\" END.\n", message);
3918 printf ("Override map \"%s\" EMPTY.\n", message);
3922 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3923 char *full_name = mono_type_full_name (&class->byval_arg);
3927 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3929 if (print_interfaces) {
3930 print_implemented_interfaces (class);
3931 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3934 if (class->parent) {
3935 parent_size = class->parent->vtable_size;
3939 for (i = 0; i < size; ++i) {
3940 MonoMethod *cm = vtable [i];
3941 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3942 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3944 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3952 #if VERIFY_INTERFACE_VTABLE_CODE
3954 mono_method_try_get_vtable_index (MonoMethod *method)
3956 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3957 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3958 if (imethod->declaring->is_generic)
3959 return imethod->declaring->slot;
3961 return method->slot;
3965 mono_class_verify_vtable (MonoClass *class)
3968 char *full_name = mono_type_full_name (&class->byval_arg);
3970 printf ("*** Verifying VTable of class '%s' \n", full_name);
3974 if (!class->methods)
3977 for (i = 0; i < class->method.count; ++i) {
3978 MonoMethod *cm = class->methods [i];
3981 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3985 full_name = mono_method_full_name (cm, TRUE);
3987 slot = mono_method_try_get_vtable_index (cm);
3989 if (slot >= class->vtable_size) {
3990 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3994 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3995 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3996 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3997 g_free (other_name);
4000 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4007 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4009 char *method_signature;
4012 for (index = 0; index < onum; ++index) {
4013 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4014 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4016 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4017 type_name = mono_type_full_name (&class->byval_arg);
4018 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4019 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4020 g_free (method_signature);
4022 mono_class_setup_methods (class);
4023 if (class->exception_type) {
4024 char *name = mono_type_get_full_name (class);
4025 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4029 for (index = 0; index < class->method.count; ++index) {
4030 MonoMethod *cm = class->methods [index];
4031 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4033 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4034 g_free (method_signature);
4039 mono_method_get_method_definition (MonoMethod *method)
4041 while (method->is_inflated)
4042 method = ((MonoMethodInflated*)method)->declaring;
4047 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4051 for (i = 0; i < onum; ++i) {
4052 MonoMethod *decl = overrides [i * 2];
4053 MonoMethod *body = overrides [i * 2 + 1];
4055 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4056 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4060 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4061 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4062 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4064 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4068 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4069 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4070 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4072 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4076 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4077 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4081 body = mono_method_get_method_definition (body);
4082 decl = mono_method_get_method_definition (decl);
4084 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4085 char *body_name = mono_method_full_name (body, TRUE);
4086 char *decl_name = mono_method_full_name (decl, TRUE);
4087 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));
4097 mono_class_need_stelemref_method (MonoClass *class)
4099 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4103 * LOCKING: this is supposed to be called with the loader lock held.
4106 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4110 MonoMethod **vtable;
4111 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4112 GPtrArray *ifaces = NULL;
4113 GHashTable *override_map = NULL;
4114 gboolean security_enabled = mono_security_enabled ();
4116 gpointer class_iter;
4117 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4118 int first_non_interface_slot;
4120 GSList *virt_methods = NULL, *l;
4121 int stelemref_slot = 0;
4126 if (overrides && !verify_class_overrides (class, overrides, onum))
4129 ifaces = mono_class_get_implemented_interfaces (class, &error);
4130 if (!mono_error_ok (&error)) {
4131 char *name = mono_type_get_full_name (class);
4132 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)));
4134 mono_error_cleanup (&error);
4136 } else if (ifaces) {
4137 for (i = 0; i < ifaces->len; i++) {
4138 MonoClass *ic = g_ptr_array_index (ifaces, i);
4139 max_vtsize += ic->method.count;
4141 g_ptr_array_free (ifaces, TRUE);
4145 if (class->parent) {
4146 mono_class_init (class->parent);
4147 mono_class_setup_vtable_full (class->parent, in_setup);
4149 if (class->parent->exception_type) {
4150 char *name = mono_type_get_full_name (class->parent);
4151 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4156 max_vtsize += class->parent->vtable_size;
4157 cur_slot = class->parent->vtable_size;
4160 max_vtsize += class->method.count;
4162 /*Array have a slot for stelemref*/
4163 if (mono_class_need_stelemref_method (class)) {
4164 stelemref_slot = cur_slot;
4169 vtable = alloca (sizeof (gpointer) * max_vtsize);
4170 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4172 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4174 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4175 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4178 max_iid = class->max_interface_id;
4179 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4181 /* Optimized version for generic instances */
4182 if (class->generic_class) {
4184 MonoClass *gklass = class->generic_class->container_class;
4187 mono_class_setup_vtable_full (gklass, in_setup);
4188 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4189 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4193 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4194 class->vtable_size = gklass->vtable_size;
4195 for (i = 0; i < gklass->vtable_size; ++i)
4196 if (gklass->vtable [i]) {
4197 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4198 if (!mono_error_ok (&error)) {
4199 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4200 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4202 mono_error_cleanup (&error);
4206 tmp [i]->slot = gklass->vtable [i]->slot;
4208 mono_memory_barrier ();
4209 class->vtable = tmp;
4211 /* Have to set method->slot for abstract virtual methods */
4212 if (class->methods && gklass->methods) {
4213 for (i = 0; i < class->method.count; ++i)
4214 if (class->methods [i]->slot == -1)
4215 class->methods [i]->slot = gklass->methods [i]->slot;
4221 if (class->parent && class->parent->vtable_size) {
4222 MonoClass *parent = class->parent;
4225 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4227 // Also inherit parent interface vtables, just as a starting point.
4228 // This is needed otherwise bug-77127.exe fails when the property methods
4229 // have different names in the iterface and the class, because for child
4230 // classes the ".override" information is not used anymore.
4231 for (i = 0; i < parent->interface_offsets_count; i++) {
4232 MonoClass *parent_interface = parent->interfaces_packed [i];
4233 int interface_offset = mono_class_interface_offset (class, parent_interface);
4234 /*FIXME this is now dead code as this condition will never hold true.
4235 Since interface offsets are inherited then the offset of an interface implemented
4236 by a parent will never be the out of it's vtable boundary.
4238 if (interface_offset >= parent->vtable_size) {
4239 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4242 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4243 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4244 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4245 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4246 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4247 parent_interface_offset + j, parent_interface_offset, j,
4248 interface_offset + j, interface_offset, j));
4255 /*Array have a slot for stelemref*/
4256 if (mono_class_need_stelemref_method (class)) {
4257 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4259 method->slot = stelemref_slot;
4261 g_assert (method->slot == stelemref_slot);
4263 vtable [stelemref_slot] = method;
4266 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4267 /* override interface methods */
4268 for (i = 0; i < onum; i++) {
4269 MonoMethod *decl = overrides [i*2];
4270 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4272 dslot = mono_method_get_vtable_slot (decl);
4274 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4278 dslot += mono_class_interface_offset (class, decl->klass);
4279 vtable [dslot] = overrides [i*2 + 1];
4280 vtable [dslot]->slot = dslot;
4282 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4284 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4286 if (mono_security_core_clr_enabled ())
4287 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4290 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4291 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4294 * Create a list of virtual methods to avoid calling
4295 * mono_class_get_virtual_methods () which is slow because of the metadata
4299 gpointer iter = NULL;
4302 virt_methods = NULL;
4303 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4304 virt_methods = g_slist_prepend (virt_methods, cm);
4306 if (class->exception_type)
4310 // Loop on all implemented interfaces...
4311 for (i = 0; i < class->interface_offsets_count; i++) {
4312 MonoClass *parent = class->parent;
4314 gboolean interface_is_explicitly_implemented_by_class;
4317 ic = class->interfaces_packed [i];
4318 ic_offset = mono_class_interface_offset (class, ic);
4320 mono_class_setup_methods (ic);
4321 if (ic->exception_type)
4324 // Check if this interface is explicitly implemented (instead of just inherited)
4325 if (parent != NULL) {
4326 int implemented_interfaces_index;
4327 interface_is_explicitly_implemented_by_class = FALSE;
4328 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4329 if (ic == class->interfaces [implemented_interfaces_index]) {
4330 interface_is_explicitly_implemented_by_class = TRUE;
4335 interface_is_explicitly_implemented_by_class = TRUE;
4338 // Loop on all interface methods...
4339 for (im_index = 0; im_index < ic->method.count; im_index++) {
4340 MonoMethod *im = ic->methods [im_index];
4341 int im_slot = ic_offset + im->slot;
4342 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4344 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4347 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4349 // If there is an explicit implementation, just use it right away,
4350 // otherwise look for a matching method
4351 if (override_im == NULL) {
4356 // First look for a suitable method among the class methods
4358 for (l = virt_methods; l; l = l->next) {
4360 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)));
4361 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4362 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4363 vtable [im_slot] = cm;
4364 /* Why do we need this? */
4369 TRACE_INTERFACE_VTABLE (printf ("\n"));
4370 if (class->exception_type) /*Might be set by check_interface_method_override*/
4374 // If the slot is still empty, look in all the inherited virtual methods...
4375 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4376 MonoClass *parent = class->parent;
4377 // Reverse order, so that last added methods are preferred
4378 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4379 MonoMethod *cm = parent->vtable [cm_index];
4381 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));
4382 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4383 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4384 vtable [im_slot] = cm;
4385 /* Why do we need this? */
4391 if (class->exception_type) /*Might be set by check_interface_method_override*/
4393 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4397 g_assert (vtable [im_slot] == override_im);
4402 // If the class is not abstract, check that all its interface slots are full.
4403 // The check is done here and not directly at the end of the loop above because
4404 // it can happen (for injected generic array interfaces) that the same slot is
4405 // processed multiple times (those interfaces have overlapping slots), and it
4406 // will not always be the first pass the one that fills the slot.
4407 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4408 for (i = 0; i < class->interface_offsets_count; i++) {
4412 ic = class->interfaces_packed [i];
4413 ic_offset = mono_class_interface_offset (class, ic);
4415 for (im_index = 0; im_index < ic->method.count; im_index++) {
4416 MonoMethod *im = ic->methods [im_index];
4417 int im_slot = ic_offset + im->slot;
4419 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4422 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4423 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4424 if (vtable [im_slot] == NULL) {
4425 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4432 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4434 for (l = virt_methods; l; l = l->next) {
4437 * If the method is REUSE_SLOT, we must check in the
4438 * base class for a method to override.
4440 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4442 for (k = class->parent; k ; k = k->parent) {
4447 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4448 MonoMethodSignature *cmsig, *m1sig;
4450 cmsig = mono_method_signature (cm);
4451 m1sig = mono_method_signature (m1);
4453 if (!cmsig || !m1sig) {
4454 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4458 if (!strcmp(cm->name, m1->name) &&
4459 mono_metadata_signature_equal (cmsig, m1sig)) {
4461 /* CAS - SecurityAction.InheritanceDemand */
4462 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4463 mono_secman_inheritancedemand_method (cm, m1);
4466 if (mono_security_core_clr_enabled ())
4467 mono_security_core_clr_check_override (class, cm, m1);
4469 slot = mono_method_get_vtable_slot (m1);
4473 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4474 char *body_name = mono_method_full_name (cm, TRUE);
4475 char *decl_name = mono_method_full_name (m1, TRUE);
4476 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));
4482 g_assert (cm->slot < max_vtsize);
4484 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4485 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4486 mono_method_full_name (m1, 1), m1,
4487 mono_method_full_name (cm, 1), cm));
4488 g_hash_table_insert (override_map, m1, cm);
4492 if (k->exception_type)
4502 /*Non final newslot methods must be given a non-interface vtable slot*/
4503 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4507 cm->slot = cur_slot++;
4509 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4510 vtable [cm->slot] = cm;
4513 /* override non interface methods */
4514 for (i = 0; i < onum; i++) {
4515 MonoMethod *decl = overrides [i*2];
4516 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4517 g_assert (decl->slot != -1);
4518 vtable [decl->slot] = overrides [i*2 + 1];
4519 overrides [i * 2 + 1]->slot = decl->slot;
4521 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4522 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4523 mono_method_full_name (decl, 1), decl,
4524 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4525 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4527 if (mono_security_core_clr_enabled ())
4528 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4533 * If a method occupies more than one place in the vtable, and it is
4534 * overriden, then change the other occurances too.
4539 for (i = 0; i < max_vtsize; ++i)
4541 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4543 cm = g_hash_table_lookup (override_map, vtable [i]);
4548 g_hash_table_destroy (override_map);
4549 override_map = NULL;
4552 g_slist_free (virt_methods);
4553 virt_methods = NULL;
4555 /* Ensure that all vtable slots are filled with concrete instance methods */
4556 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4557 for (i = 0; i < cur_slot; ++i) {
4558 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4559 char *type_name = mono_type_get_full_name (class);
4560 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4561 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));
4563 g_free (method_name);
4569 if (class->generic_class) {
4570 MonoClass *gklass = class->generic_class->container_class;
4572 mono_class_init (gklass);
4574 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4576 /* Check that the vtable_size value computed in mono_class_init () is correct */
4577 if (class->vtable_size)
4578 g_assert (cur_slot == class->vtable_size);
4579 class->vtable_size = cur_slot;
4582 /* Try to share the vtable with our parent. */
4583 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4584 mono_memory_barrier ();
4585 class->vtable = class->parent->vtable;
4587 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4588 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4589 mono_memory_barrier ();
4590 class->vtable = tmp;
4593 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4594 if (mono_print_vtable) {
4597 print_implemented_interfaces (class);
4599 for (i = 0; i <= max_iid; i++)
4600 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4603 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4604 class->vtable_size, icount);
4606 for (i = 0; i < cur_slot; ++i) {
4611 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4612 mono_method_full_name (cm, TRUE));
4618 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4619 class->name, max_iid);
4621 for (i = 0; i < class->interface_count; i++) {
4622 ic = class->interfaces [i];
4623 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4624 mono_class_interface_offset (class, ic),
4625 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4628 for (k = class->parent; k ; k = k->parent) {
4629 for (i = 0; i < k->interface_count; i++) {
4630 ic = k->interfaces [i];
4631 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4632 mono_class_interface_offset (class, ic),
4633 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4639 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4644 char *name = mono_type_get_full_name (class);
4645 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4648 g_hash_table_destroy (override_map);
4650 g_slist_free (virt_methods);
4655 * mono_method_get_vtable_slot:
4657 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4658 * LOCKING: Acquires the loader lock.
4660 * FIXME Use proper MonoError machinery here.
4663 mono_method_get_vtable_slot (MonoMethod *method)
4665 if (method->slot == -1) {
4666 mono_class_setup_vtable (method->klass);
4667 if (method->klass->exception_type)
4669 if (method->slot == -1) {
4673 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4674 g_assert (method->klass->generic_class);
4675 gklass = method->klass->generic_class->container_class;
4676 mono_class_setup_methods (method->klass);
4677 g_assert (method->klass->methods);
4678 for (i = 0; i < method->klass->method.count; ++i) {
4679 if (method->klass->methods [i] == method)
4682 g_assert (i < method->klass->method.count);
4683 g_assert (gklass->methods);
4684 method->slot = gklass->methods [i]->slot;
4686 g_assert (method->slot != -1);
4688 return method->slot;
4692 * mono_method_get_vtable_index:
4695 * Returns the index into the runtime vtable to access the method or,
4696 * in the case of a virtual generic method, the virtual generic method
4697 * thunk. Returns -1 on failure.
4699 * FIXME Use proper MonoError machinery here.
4702 mono_method_get_vtable_index (MonoMethod *method)
4704 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4705 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4706 if (imethod->declaring->is_generic)
4707 return mono_method_get_vtable_slot (imethod->declaring);
4709 return mono_method_get_vtable_slot (method);
4712 static MonoMethod *default_ghc = NULL;
4713 static MonoMethod *default_finalize = NULL;
4714 static int finalize_slot = -1;
4715 static int ghc_slot = -1;
4718 initialize_object_slots (MonoClass *class)
4723 if (class == mono_defaults.object_class) {
4724 mono_class_setup_vtable (class);
4725 for (i = 0; i < class->vtable_size; ++i) {
4726 MonoMethod *cm = class->vtable [i];
4728 if (!strcmp (cm->name, "GetHashCode"))
4730 else if (!strcmp (cm->name, "Finalize"))
4734 g_assert (ghc_slot > 0);
4735 default_ghc = class->vtable [ghc_slot];
4737 g_assert (finalize_slot > 0);
4738 default_finalize = class->vtable [finalize_slot];
4743 MonoMethod *array_method;
4745 } GenericArrayMethodInfo;
4747 static int generic_array_method_num = 0;
4748 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4751 generic_array_methods (MonoClass *class)
4753 int i, count_generic = 0;
4754 GList *list = NULL, *tmp;
4755 if (generic_array_method_num)
4756 return generic_array_method_num;
4757 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4758 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4759 for (i = 0; i < class->parent->method.count; i++) {
4760 MonoMethod *m = class->parent->methods [i];
4761 if (!strncmp (m->name, "InternalArray__", 15)) {
4763 list = g_list_prepend (list, m);
4766 list = g_list_reverse (list);
4767 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4769 for (tmp = list; tmp; tmp = tmp->next) {
4770 const char *mname, *iname;
4772 MonoMethod *m = tmp->data;
4773 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4774 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4776 generic_array_method_info [i].array_method = m;
4777 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4778 iname = "System.Collections.Generic.ICollection`1.";
4779 mname = m->name + 27;
4780 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4781 iname = "System.Collections.Generic.IEnumerable`1.";
4782 mname = m->name + 27;
4783 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4784 iname = "System.Collections.Generic.IReadOnlyList`1.";
4785 mname = m->name + strlen (ireadonlylist_prefix);
4786 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4787 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4788 mname = m->name + strlen (ireadonlycollection_prefix);
4789 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4790 iname = "System.Collections.Generic.IList`1.";
4791 mname = m->name + 15;
4793 g_assert_not_reached ();
4796 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4797 strcpy (name, iname);
4798 strcpy (name + strlen (iname), mname);
4799 generic_array_method_info [i].name = name;
4802 /*g_print ("array generic methods: %d\n", count_generic);*/
4804 generic_array_method_num = count_generic;
4806 return generic_array_method_num;
4810 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4812 MonoGenericContext tmp_context;
4815 tmp_context.class_inst = NULL;
4816 tmp_context.method_inst = iface->generic_class->context.class_inst;
4817 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4819 for (i = 0; i < generic_array_method_num; i++) {
4820 MonoMethod *m = generic_array_method_info [i].array_method;
4821 MonoMethod *inflated;
4823 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4824 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4829 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4831 int null_length = strlen ("(null)");
4832 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4833 char *s = mono_image_alloc (image, len);
4836 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4837 g_assert (result == len - 1);
4843 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4845 gpointer exception_data = NULL;
4847 switch (error->exception_type) {
4848 case MONO_EXCEPTION_TYPE_LOAD:
4849 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4852 case MONO_EXCEPTION_MISSING_METHOD:
4853 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4856 case MONO_EXCEPTION_MISSING_FIELD: {
4857 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4858 const char *class_name;
4861 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4863 class_name = error->klass->name;
4865 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4868 g_free ((void*)class_name);
4872 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4875 if (error->ref_only)
4876 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.";
4878 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4880 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4884 case MONO_EXCEPTION_BAD_IMAGE:
4885 exception_data = error->msg;
4889 g_assert_not_reached ();
4892 mono_class_set_failure (class, error->exception_type, exception_data);
4897 * @class: the class to initialize
4899 * Compute the instance_size, class_size and other infos that cannot be
4900 * computed at mono_class_get() time. Also compute vtable_size if possible.
4901 * Returns TRUE on success or FALSE if there was a problem in loading
4902 * the type (incorrect assemblies, missing assemblies, methods, etc).
4904 * LOCKING: Acquires the loader lock.
4907 mono_class_init (MonoClass *class)
4910 MonoCachedClassInfo cached_info;
4911 gboolean has_cached_info;
4915 /* Double-checking locking pattern */
4916 if (class->inited || class->exception_type)
4917 return class->exception_type == MONO_EXCEPTION_NONE;
4919 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4921 /* We do everything inside the lock to prevent races */
4922 mono_loader_lock ();
4924 if (class->inited || class->exception_type) {
4925 mono_loader_unlock ();
4926 /* Somebody might have gotten in before us */
4927 return class->exception_type == MONO_EXCEPTION_NONE;
4930 if (class->init_pending) {
4931 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4935 class->init_pending = 1;
4937 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4938 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4943 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4944 MonoClass *element_class = class->element_class;
4945 if (!element_class->inited)
4946 mono_class_init (element_class);
4947 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4948 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4953 /* CAS - SecurityAction.InheritanceDemand */
4954 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4955 mono_secman_inheritancedemand_class (class, class->parent);
4958 mono_stats.initialized_class_count++;
4960 if (class->generic_class && !class->generic_class->is_dynamic) {
4961 MonoClass *gklass = class->generic_class->container_class;
4963 mono_stats.generic_class_count++;
4965 class->method = gklass->method;
4966 class->field = gklass->field;
4968 mono_class_init (gklass);
4969 // FIXME: Why is this needed ?
4970 if (!gklass->exception_type)
4971 mono_class_setup_methods (gklass);
4972 if (gklass->exception_type) {
4973 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4977 if (MONO_CLASS_IS_INTERFACE (class))
4978 class->interface_id = mono_get_unique_iid (class);
4981 if (class->parent && !class->parent->inited)
4982 mono_class_init (class->parent);
4984 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4986 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4987 class->nested_classes_inited = TRUE;
4990 * Computes the size used by the fields, and their locations
4992 if (has_cached_info) {
4993 class->instance_size = cached_info.instance_size;
4994 class->sizes.class_size = cached_info.class_size;
4995 class->packing_size = cached_info.packing_size;
4996 class->min_align = cached_info.min_align;
4997 class->blittable = cached_info.blittable;
4998 class->has_references = cached_info.has_references;
4999 class->has_static_refs = cached_info.has_static_refs;
5000 class->no_special_static_fields = cached_info.no_special_static_fields;
5003 if (!class->size_inited){
5004 mono_class_setup_fields (class);
5005 if (class->exception_type || mono_loader_get_last_error ())
5009 /* Initialize arrays */
5011 class->method.count = 3 + (class->rank > 1? 2: 1);
5013 if (class->interface_count) {
5014 int count_generic = generic_array_methods (class);
5015 class->method.count += class->interface_count * count_generic;
5019 mono_class_setup_supertypes (class);
5022 initialize_object_slots (class);
5025 * Initialize the rest of the data without creating a generic vtable if possible.
5026 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5027 * also avoid computing a generic vtable.
5029 if (has_cached_info) {
5031 class->vtable_size = cached_info.vtable_size;
5032 class->has_finalize = cached_info.has_finalize;
5033 class->has_finalize_inited = TRUE;
5034 class->ghcimpl = cached_info.ghcimpl;
5035 class->has_cctor = cached_info.has_cctor;
5036 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5037 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5038 * The first slot if for array with.
5040 static int szarray_vtable_size[2] = { 0 };
5042 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5045 if (!szarray_vtable_size [slot]) {
5046 mono_class_setup_vtable (class);
5047 szarray_vtable_size [slot] = class->vtable_size;
5049 class->vtable_size = szarray_vtable_size[slot];
5051 class->has_finalize_inited = TRUE;
5052 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5053 MonoClass *gklass = class->generic_class->container_class;
5055 /* Generic instance case */
5056 class->ghcimpl = gklass->ghcimpl;
5057 class->has_finalize = mono_class_has_finalizer (gklass);
5058 class->has_finalize_inited = TRUE;
5059 class->has_cctor = gklass->has_cctor;
5061 mono_class_setup_vtable (gklass);
5062 if (gklass->exception_type) {
5063 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5067 class->vtable_size = gklass->vtable_size;
5071 /* ghcimpl is not currently used
5073 if (class->parent) {
5074 MonoMethod *cmethod = class->vtable [ghc_slot];
5075 if (cmethod->is_inflated)
5076 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5077 if (cmethod == default_ghc) {
5083 /* C# doesn't allow interfaces to have cctors */
5084 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5085 MonoMethod *cmethod = NULL;
5087 if (class->type_token) {
5088 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5089 /* The find_method function ignores the 'flags' argument */
5090 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5091 class->has_cctor = 1;
5093 mono_class_setup_methods (class);
5094 if (class->exception_type)
5097 for (i = 0; i < class->method.count; ++i) {
5098 MonoMethod *method = class->methods [i];
5099 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5100 (strcmp (".cctor", method->name) == 0)) {
5101 class->has_cctor = 1;
5109 if (class->parent) {
5110 int first_iface_slot;
5111 /* This will compute class->parent->vtable_size for some classes */
5112 mono_class_init (class->parent);
5113 if (class->parent->exception_type) {
5114 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5117 if (mono_loader_get_last_error ())
5119 if (!class->parent->vtable_size) {
5120 /* FIXME: Get rid of this somehow */
5121 mono_class_setup_vtable (class->parent);
5122 if (class->parent->exception_type) {
5123 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5126 if (mono_loader_get_last_error ())
5129 first_iface_slot = class->parent->vtable_size;
5130 if (mono_class_need_stelemref_method (class))
5132 setup_interface_offsets (class, first_iface_slot, TRUE);
5134 setup_interface_offsets (class, 0, TRUE);
5137 if (mono_security_core_clr_enabled ())
5138 mono_security_core_clr_check_inheritance (class);
5140 if (mono_loader_get_last_error ()) {
5141 if (class->exception_type == MONO_EXCEPTION_NONE) {
5142 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5144 mono_loader_clear_error ();
5147 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5148 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5153 /* Because of the double-checking locking pattern */
5154 mono_memory_barrier ();
5156 class->init_pending = 0;
5158 mono_loader_unlock ();
5160 if (mono_debugger_class_init_func)
5161 mono_debugger_class_init_func (class);
5163 return class->exception_type == MONO_EXCEPTION_NONE;
5167 * mono_class_has_finalizer:
5169 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5173 mono_class_has_finalizer (MonoClass *klass)
5175 if (!klass->has_finalize_inited) {
5176 MonoClass *class = klass;
5178 mono_loader_lock ();
5180 /* Interfaces and valuetypes are not supposed to have finalizers */
5181 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5182 MonoMethod *cmethod = NULL;
5184 if (class->parent && class->parent->has_finalize) {
5185 class->has_finalize = 1;
5187 if (class->parent) {
5189 * Can't search in metadata for a method named Finalize, because that
5190 * ignores overrides.
5192 mono_class_setup_vtable (class);
5193 if (class->exception_type || mono_loader_get_last_error ())
5195 cmethod = class->vtable [finalize_slot];
5199 g_assert (class->vtable_size > finalize_slot);
5201 class->has_finalize = 0;
5202 if (class->parent) {
5203 if (cmethod->is_inflated)
5204 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5205 if (cmethod != default_finalize) {
5206 class->has_finalize = 1;
5213 mono_memory_barrier ();
5214 klass->has_finalize_inited = TRUE;
5216 mono_loader_unlock ();
5219 return klass->has_finalize;
5222 mono_loader_unlock ();
5227 mono_is_corlib_image (MonoImage *image)
5229 /* FIXME: allow the dynamic case for our compilers and with full trust */
5231 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5233 return image == mono_defaults.corlib;
5237 * LOCKING: this assumes the loader lock is held
5240 mono_class_setup_mono_type (MonoClass *class)
5242 const char *name = class->name;
5243 const char *nspace = class->name_space;
5244 gboolean is_corlib = mono_is_corlib_image (class->image);
5246 class->this_arg.byref = 1;
5247 class->this_arg.data.klass = class;
5248 class->this_arg.type = MONO_TYPE_CLASS;
5249 class->byval_arg.data.klass = class;
5250 class->byval_arg.type = MONO_TYPE_CLASS;
5252 if (is_corlib && !strcmp (nspace, "System")) {
5253 if (!strcmp (name, "ValueType")) {
5255 * do not set the valuetype bit for System.ValueType.
5256 * class->valuetype = 1;
5258 class->blittable = TRUE;
5259 } else if (!strcmp (name, "Enum")) {
5261 * do not set the valuetype bit for System.Enum.
5262 * class->valuetype = 1;
5264 class->valuetype = 0;
5265 class->enumtype = 0;
5266 } else if (!strcmp (name, "Object")) {
5267 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5268 } else if (!strcmp (name, "String")) {
5269 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5270 } else if (!strcmp (name, "TypedReference")) {
5271 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5275 if (class->valuetype) {
5276 int t = MONO_TYPE_VALUETYPE;
5278 if (is_corlib && !strcmp (nspace, "System")) {
5281 if (!strcmp (name, "Boolean")) {
5282 t = MONO_TYPE_BOOLEAN;
5283 } else if (!strcmp(name, "Byte")) {
5285 class->blittable = TRUE;
5289 if (!strcmp (name, "Char")) {
5294 if (!strcmp (name, "Double")) {
5296 class->blittable = TRUE;
5300 if (!strcmp (name, "Int32")) {
5302 class->blittable = TRUE;
5303 } else if (!strcmp(name, "Int16")) {
5305 class->blittable = TRUE;
5306 } else if (!strcmp(name, "Int64")) {
5308 class->blittable = TRUE;
5309 } else if (!strcmp(name, "IntPtr")) {
5311 class->blittable = TRUE;
5315 if (!strcmp (name, "Single")) {
5317 class->blittable = TRUE;
5318 } else if (!strcmp(name, "SByte")) {
5320 class->blittable = TRUE;
5324 if (!strcmp (name, "UInt32")) {
5326 class->blittable = TRUE;
5327 } else if (!strcmp(name, "UInt16")) {
5329 class->blittable = TRUE;
5330 } else if (!strcmp(name, "UInt64")) {
5332 class->blittable = TRUE;
5333 } else if (!strcmp(name, "UIntPtr")) {
5335 class->blittable = TRUE;
5339 if (!strcmp (name, "TypedReference")) {
5340 t = MONO_TYPE_TYPEDBYREF;
5341 class->blittable = TRUE;
5345 if (!strcmp (name, "Void")) {
5353 class->this_arg.type = class->byval_arg.type = t;
5356 if (MONO_CLASS_IS_INTERFACE (class))
5357 class->interface_id = mono_get_unique_iid (class);
5363 * COM initialization is delayed until needed.
5364 * However when a [ComImport] attribute is present on a type it will trigger
5365 * the initialization. This is not a problem unless the BCL being executed
5366 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5369 init_com_from_comimport (MonoClass *class)
5371 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5372 if (mono_security_core_clr_enabled ()) {
5373 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5374 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5375 /* but it can not be made available for application (i.e. user code) since all COM calls
5376 * are considered native calls. In this case we fail with a TypeLoadException (just like
5377 * Silverlight 2 does */
5378 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5383 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5385 #endif /*DISABLE_COM*/
5388 * LOCKING: this assumes the loader lock is held
5391 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5393 gboolean system_namespace;
5394 gboolean is_corlib = mono_is_corlib_image (class->image);
5396 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5398 /* if root of the hierarchy */
5399 if (system_namespace && !strcmp (class->name, "Object")) {
5400 class->parent = NULL;
5401 class->instance_size = sizeof (MonoObject);
5404 if (!strcmp (class->name, "<Module>")) {
5405 class->parent = NULL;
5406 class->instance_size = 0;
5410 if (!MONO_CLASS_IS_INTERFACE (class)) {
5411 /* Imported COM Objects always derive from __ComObject. */
5413 if (MONO_CLASS_IS_IMPORT (class)) {
5414 init_com_from_comimport (class);
5415 if (parent == mono_defaults.object_class)
5416 parent = mono_class_get_com_object_class ();
5420 /* set the parent to something useful and safe, but mark the type as broken */
5421 parent = mono_defaults.object_class;
5422 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5425 class->parent = parent;
5427 if (parent->generic_class && !parent->name) {
5429 * If the parent is a generic instance, we may get
5430 * called before it is fully initialized, especially
5431 * before it has its name.
5436 #ifndef DISABLE_REMOTING
5437 class->marshalbyref = parent->marshalbyref;
5438 class->contextbound = parent->contextbound;
5441 class->delegate = parent->delegate;
5443 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5444 mono_class_set_is_com_object (class);
5446 if (system_namespace) {
5447 #ifndef DISABLE_REMOTING
5448 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5449 class->marshalbyref = 1;
5451 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5452 class->contextbound = 1;
5454 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5455 class->delegate = 1;
5458 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5459 (strcmp (class->parent->name_space, "System") == 0)))
5460 class->valuetype = 1;
5461 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5462 class->valuetype = class->enumtype = 1;
5464 /*class->enumtype = class->parent->enumtype; */
5466 /* initialize com types if COM interfaces are present */
5468 if (MONO_CLASS_IS_IMPORT (class))
5469 init_com_from_comimport (class);
5471 class->parent = NULL;
5477 * mono_class_setup_supertypes:
5480 * Build the data structure needed to make fast type checks work.
5481 * This currently sets two fields in @class:
5482 * - idepth: distance between @class and System.Object in the type
5484 * - supertypes: array of classes: each element has a class in the hierarchy
5485 * starting from @class up to System.Object
5487 * LOCKING: this assumes the loader lock is held
5490 mono_class_setup_supertypes (MonoClass *class)
5493 MonoClass **supertypes;
5495 if (class->supertypes)
5498 if (class->parent && !class->parent->supertypes)
5499 mono_class_setup_supertypes (class->parent);
5501 class->idepth = class->parent->idepth + 1;
5505 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5506 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5508 if (class->parent) {
5509 supertypes [class->idepth - 1] = class;
5510 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5512 supertypes [0] = class;
5515 mono_atomic_store_release (&class->supertypes, supertypes);
5519 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5521 MonoClass *gtd = (MonoClass*)user_data;
5522 /* Only try to fix generic instances of @gtd */
5523 if (gclass->generic_class->container_class != gtd)
5526 /* Check if the generic instance has no parent. */
5527 if (gtd->parent && !gclass->parent)
5528 mono_generic_class_setup_parent (gclass, gtd);
5534 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5536 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5537 mono_error_set_type_load_class (error, class, msg);
5541 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5543 MonoLoaderError *lerror = mono_loader_get_last_error ();
5546 set_failure_from_loader_error (class, lerror);
5547 mono_error_set_from_loader_error (error);
5551 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5552 mono_error_set_type_load_class (error, class, msg);
5557 * mono_class_create_from_typedef:
5558 * @image: image where the token is valid
5559 * @type_token: typedef token
5560 * @error: used to return any error found while creating the type
5562 * Create the MonoClass* representing the specified type token.
5563 * @type_token must be a TypeDef token.
5565 * FIXME: don't return NULL on failure, just the the caller figure it out.
5568 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5570 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5571 MonoClass *class, *parent = NULL;
5572 guint32 cols [MONO_TYPEDEF_SIZE];
5573 guint32 cols_next [MONO_TYPEDEF_SIZE];
5574 guint tidx = mono_metadata_token_index (type_token);
5575 MonoGenericContext *context = NULL;
5576 const char *name, *nspace;
5578 MonoClass **interfaces;
5579 guint32 field_last, method_last;
5580 guint32 nesting_tokeen;
5582 mono_error_init (error);
5584 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5585 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5586 g_assert (!mono_loader_get_last_error ());
5590 mono_loader_lock ();
5592 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5593 mono_loader_unlock ();
5594 g_assert (!mono_loader_get_last_error ());
5598 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5600 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5601 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5603 class = mono_image_alloc0 (image, sizeof (MonoClass));
5606 class->name_space = nspace;
5608 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5610 class->image = image;
5611 class->type_token = type_token;
5612 class->flags = cols [MONO_TYPEDEF_FLAGS];
5614 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5616 classes_size += sizeof (MonoClass);
5619 * Check whether we're a generic type definition.
5621 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5622 if (class->generic_container) {
5623 class->is_generic = 1;
5624 class->generic_container->owner.klass = class;
5625 context = &class->generic_container->context;
5628 if (class->generic_container)
5629 enable_gclass_recording ();
5631 if (cols [MONO_TYPEDEF_EXTENDS]) {
5633 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5635 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5636 /*WARNING: this must satisfy mono_metadata_type_hash*/
5637 class->this_arg.byref = 1;
5638 class->this_arg.data.klass = class;
5639 class->this_arg.type = MONO_TYPE_CLASS;
5640 class->byval_arg.data.klass = class;
5641 class->byval_arg.type = MONO_TYPE_CLASS;
5643 parent = mono_class_get_full (image, parent_token, context);
5645 if (parent == NULL) {
5646 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5647 goto parent_failure;
5650 for (tmp = parent; tmp; tmp = tmp->parent) {
5652 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5653 goto parent_failure;
5655 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5656 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5657 goto parent_failure;
5662 mono_class_setup_parent (class, parent);
5664 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5665 mono_class_setup_mono_type (class);
5667 if (class->generic_container)
5668 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5671 * This might access class->byval_arg for recursion generated by generic constraints,
5672 * so it has to come after setup_mono_type ().
5674 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5675 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5676 if (!mono_error_ok (error)) {
5677 /*FIXME implement a mono_class_set_failure_from_mono_error */
5678 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5679 mono_loader_unlock ();
5680 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5681 g_assert (!mono_loader_get_last_error ());
5686 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5690 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5694 class->cast_class = class->element_class = class;
5696 if (!class->enumtype) {
5697 if (!mono_metadata_interfaces_from_typedef_full (
5698 image, type_token, &interfaces, &icount, FALSE, context)){
5699 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5700 mono_loader_unlock ();
5701 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5705 class->interfaces = interfaces;
5706 class->interface_count = icount;
5707 class->interfaces_inited = 1;
5710 /*g_print ("Load class %s\n", name);*/
5713 * Compute the field and method lists
5715 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5716 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5718 if (tt->rows > tidx){
5719 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5720 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5721 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5723 field_last = image->tables [MONO_TABLE_FIELD].rows;
5724 method_last = image->tables [MONO_TABLE_METHOD].rows;
5727 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5728 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5729 class->field.count = field_last - class->field.first;
5731 class->field.count = 0;
5733 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5734 class->method.count = method_last - class->method.first;
5736 class->method.count = 0;
5738 /* reserve space to store vector pointer in arrays */
5739 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5740 class->instance_size += 2 * sizeof (gpointer);
5741 g_assert (class->field.count == 0);
5744 if (class->enumtype) {
5745 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5746 if (!enum_basetype) {
5747 /*set it to a default value as the whole runtime can't handle this to be null*/
5748 class->cast_class = class->element_class = mono_defaults.int32_class;
5749 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5750 mono_loader_unlock ();
5751 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5752 g_assert (!mono_loader_get_last_error ());
5755 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5759 * If we're a generic type definition, load the constraints.
5760 * We must do this after the class has been constructed to make certain recursive scenarios
5763 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5764 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5765 mono_loader_unlock ();
5766 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5767 g_assert (!mono_loader_get_last_error ());
5771 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5772 if (!strncmp (name, "Vector", 6))
5773 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");
5776 mono_loader_unlock ();
5778 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5779 g_assert (!mono_loader_get_last_error ());
5784 mono_class_setup_mono_type (class);
5785 mono_loader_unlock ();
5786 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5787 g_assert (!mono_loader_get_last_error ());
5791 /** is klass Nullable<T>? */
5793 mono_class_is_nullable (MonoClass *klass)
5795 return klass->generic_class != NULL &&
5796 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5800 /** if klass is T? return T */
5802 mono_class_get_nullable_param (MonoClass *klass)
5804 g_assert (mono_class_is_nullable (klass));
5805 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5809 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5813 MonoGenericClass *gclass = klass->generic_class;
5815 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5816 if (!mono_error_ok (&error)) {
5817 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5818 klass->parent = mono_defaults.object_class;
5819 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5820 mono_error_cleanup (&error);
5824 mono_class_setup_parent (klass, klass->parent);
5826 if (klass->enumtype) {
5827 klass->cast_class = gtd->cast_class;
5828 klass->element_class = gtd->element_class;
5834 * Create the `MonoClass' for an instantiation of a generic type.
5835 * We only do this if we actually need it.
5838 mono_generic_class_get_class (MonoGenericClass *gclass)
5840 MonoClass *klass, *gklass;
5842 if (gclass->cached_class)
5843 return gclass->cached_class;
5845 mono_loader_lock ();
5846 if (gclass->cached_class) {
5847 mono_loader_unlock ();
5848 return gclass->cached_class;
5851 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5853 gklass = gclass->container_class;
5855 if (record_gclass_instantiation > 0)
5856 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5858 if (gklass->nested_in) {
5859 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5860 klass->nested_in = gklass->nested_in;
5863 klass->name = gklass->name;
5864 klass->name_space = gklass->name_space;
5866 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5868 klass->image = gklass->image;
5869 klass->flags = gklass->flags;
5870 klass->type_token = gklass->type_token;
5871 klass->field.count = gklass->field.count;
5873 klass->is_inflated = 1;
5874 klass->generic_class = gclass;
5876 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5877 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5878 klass->this_arg.byref = TRUE;
5879 klass->enumtype = gklass->enumtype;
5880 klass->valuetype = gklass->valuetype;
5882 klass->cast_class = klass->element_class = klass;
5884 if (mono_class_is_nullable (klass))
5885 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5888 * We're not interested in the nested classes of a generic instance.
5889 * We use the generic type definition to look for nested classes.
5892 mono_generic_class_setup_parent (klass, gklass);
5894 if (gclass->is_dynamic) {
5897 mono_class_setup_supertypes (klass);
5899 if (klass->enumtype) {
5901 * For enums, gklass->fields might not been set, but instance_size etc. is
5902 * already set in mono_reflection_create_internal_class (). For non-enums,
5903 * these will be computed normally in mono_class_layout_fields ().
5905 klass->instance_size = gklass->instance_size;
5906 klass->sizes.class_size = gklass->sizes.class_size;
5907 mono_memory_barrier ();
5908 klass->size_inited = 1;
5912 mono_memory_barrier ();
5913 gclass->cached_class = klass;
5915 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5917 inflated_classes ++;
5918 inflated_classes_size += sizeof (MonoClass);
5920 mono_loader_unlock ();
5926 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5928 MonoClass *klass, **ptr;
5930 MonoGenericContainer *container = mono_generic_param_owner (param);
5934 image = mono_defaults.corlib;
5936 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5937 classes_size += sizeof (MonoClass);
5940 klass->name = pinfo->name;
5942 int n = mono_generic_param_num (param);
5943 klass->name = mono_image_alloc0 (image, 16);
5944 sprintf ((char*)klass->name, "%d", n);
5949 MonoMethod *omethod = container->owner.method;
5950 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5952 MonoClass *oklass = container->owner.klass;
5953 klass->name_space = oklass ? oklass->name_space : "";
5956 klass->name_space = "";
5959 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5963 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5967 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5968 klass->parent = pinfo->constraints [0];
5970 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5971 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5973 klass->parent = mono_defaults.object_class;
5976 if (count - pos > 0) {
5977 klass->interface_count = count - pos;
5978 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5979 klass->interfaces_inited = TRUE;
5980 for (i = pos; i < count; i++)
5981 klass->interfaces [i - pos] = pinfo->constraints [i];
5984 klass->image = image;
5986 klass->inited = TRUE;
5987 klass->cast_class = klass->element_class = klass;
5988 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5990 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5991 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5992 klass->this_arg.byref = TRUE;
5994 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5995 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
5997 /*Init these fields to sane values*/
5998 klass->min_align = 1;
5999 klass->instance_size = sizeof (gpointer);
6000 mono_memory_barrier ();
6001 klass->size_inited = 1;
6003 mono_class_setup_supertypes (klass);
6005 if (count - pos > 0) {
6006 mono_class_setup_vtable (klass->parent);
6007 if (klass->parent->exception_type)
6008 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6010 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6016 #define FAST_CACHE_SIZE 16
6019 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6021 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6022 MonoImage *image = param->image;
6027 if (n < FAST_CACHE_SIZE) {
6029 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6031 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6033 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6034 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6039 * LOCKING: Acquires the loader lock.
6042 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6044 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6045 MonoImage *image = param->image;
6050 if (n < FAST_CACHE_SIZE) {
6052 /* No locking needed */
6053 if (!image->mvar_cache_fast)
6054 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6055 image->mvar_cache_fast [n] = klass;
6057 if (!image->var_cache_fast)
6058 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6059 image->var_cache_fast [n] = klass;
6063 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6065 mono_loader_lock ();
6066 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6068 ht = g_hash_table_new (NULL, NULL);
6069 mono_memory_barrier ();
6071 image->mvar_cache_slow = ht;
6073 image->var_cache_slow = ht;
6075 mono_loader_unlock ();
6078 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6082 * LOCKING: Acquires the loader lock.
6085 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6087 MonoGenericContainer *container = mono_generic_param_owner (param);
6088 MonoGenericParamInfo *pinfo;
6091 mono_loader_lock ();
6094 pinfo = mono_generic_param_info (param);
6095 if (pinfo->pklass) {
6096 mono_loader_unlock ();
6097 return pinfo->pklass;
6103 klass = get_anon_gparam_class (param, is_mvar);
6105 mono_loader_unlock ();
6110 if (!image && container) {
6112 MonoMethod *method = container->owner.method;
6113 image = (method && method->klass) ? method->klass->image : NULL;
6115 MonoClass *klass = container->owner.klass;
6116 // FIXME: 'klass' should not be null
6117 // But, monodis creates GenericContainers without associating a owner to it
6118 image = klass ? klass->image : NULL;
6122 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6124 mono_memory_barrier ();
6127 pinfo->pklass = klass;
6129 set_anon_gparam_class (param, is_mvar, klass);
6131 mono_loader_unlock ();
6133 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6134 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6140 mono_ptr_class_get (MonoType *type)
6143 MonoClass *el_class;
6147 el_class = mono_class_from_mono_type (type);
6148 image = el_class->image;
6150 mono_loader_lock ();
6152 if (!image->ptr_cache)
6153 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6155 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6156 mono_loader_unlock ();
6159 result = mono_image_alloc0 (image, sizeof (MonoClass));
6161 classes_size += sizeof (MonoClass);
6163 result->parent = NULL; /* no parent for PTR types */
6164 result->name_space = el_class->name_space;
6165 name = g_strdup_printf ("%s*", el_class->name);
6166 result->name = mono_image_strdup (image, name);
6169 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6171 result->image = el_class->image;
6172 result->inited = TRUE;
6173 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6174 /* Can pointers get boxed? */
6175 result->instance_size = sizeof (gpointer);
6176 result->cast_class = result->element_class = el_class;
6177 result->blittable = TRUE;
6179 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6180 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6181 result->this_arg.byref = TRUE;
6183 mono_class_setup_supertypes (result);
6185 g_hash_table_insert (image->ptr_cache, el_class, result);
6187 mono_loader_unlock ();
6189 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6195 mono_fnptr_class_get (MonoMethodSignature *sig)
6198 static GHashTable *ptr_hash = NULL;
6200 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6202 mono_loader_lock ();
6205 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6207 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6208 mono_loader_unlock ();
6211 result = g_new0 (MonoClass, 1);
6213 result->parent = NULL; /* no parent for PTR types */
6214 result->name_space = "System";
6215 result->name = "MonoFNPtrFakeClass";
6217 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6219 result->image = mono_defaults.corlib; /* need to fix... */
6220 result->inited = TRUE;
6221 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6222 /* Can pointers get boxed? */
6223 result->instance_size = sizeof (gpointer);
6224 result->cast_class = result->element_class = result;
6225 result->blittable = TRUE;
6227 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6228 result->this_arg.data.method = result->byval_arg.data.method = sig;
6229 result->this_arg.byref = TRUE;
6230 result->blittable = TRUE;
6232 mono_class_setup_supertypes (result);
6234 g_hash_table_insert (ptr_hash, sig, result);
6236 mono_loader_unlock ();
6238 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6244 mono_class_from_mono_type (MonoType *type)
6246 switch (type->type) {
6247 case MONO_TYPE_OBJECT:
6248 return type->data.klass? type->data.klass: mono_defaults.object_class;
6249 case MONO_TYPE_VOID:
6250 return type->data.klass? type->data.klass: mono_defaults.void_class;
6251 case MONO_TYPE_BOOLEAN:
6252 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6253 case MONO_TYPE_CHAR:
6254 return type->data.klass? type->data.klass: mono_defaults.char_class;
6256 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6258 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6260 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6262 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6264 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6266 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6268 return type->data.klass? type->data.klass: mono_defaults.int_class;
6270 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6272 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6274 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6276 return type->data.klass? type->data.klass: mono_defaults.single_class;
6278 return type->data.klass? type->data.klass: mono_defaults.double_class;
6279 case MONO_TYPE_STRING:
6280 return type->data.klass? type->data.klass: mono_defaults.string_class;
6281 case MONO_TYPE_TYPEDBYREF:
6282 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6283 case MONO_TYPE_ARRAY:
6284 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6286 return mono_ptr_class_get (type->data.type);
6287 case MONO_TYPE_FNPTR:
6288 return mono_fnptr_class_get (type->data.method);
6289 case MONO_TYPE_SZARRAY:
6290 return mono_array_class_get (type->data.klass, 1);
6291 case MONO_TYPE_CLASS:
6292 case MONO_TYPE_VALUETYPE:
6293 return type->data.klass;
6294 case MONO_TYPE_GENERICINST:
6295 return mono_generic_class_get_class (type->data.generic_class);
6297 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6298 case MONO_TYPE_MVAR:
6299 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6301 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6302 g_assert_not_reached ();
6309 * mono_type_retrieve_from_typespec
6310 * @image: context where the image is created
6311 * @type_spec: typespec token
6312 * @context: the generic context used to evaluate generic instantiations in
6315 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6317 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6319 mono_error_init (error);
6320 *did_inflate = FALSE;
6323 char *name = mono_class_name_from_token (image, type_spec);
6324 char *assembly = mono_assembly_name_from_token (image, type_spec);
6325 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6329 if (context && (context->class_inst || context->method_inst)) {
6330 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6332 if (!mono_error_ok (error))
6337 *did_inflate = TRUE;
6344 * mono_class_create_from_typespec
6345 * @image: context where the image is created
6346 * @type_spec: typespec token
6347 * @context: the generic context used to evaluate generic instantiations in
6350 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6353 gboolean inflated = FALSE;
6354 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6355 if (!mono_error_ok (error))
6357 ret = mono_class_from_mono_type (t);
6359 mono_metadata_free_type (t);
6364 * mono_bounded_array_class_get:
6365 * @element_class: element class
6366 * @rank: the dimension of the array class
6367 * @bounded: whenever the array has non-zero bounds
6369 * Returns: a class object describing the array with element type @element_type and
6373 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6377 MonoClass *parent = NULL;
6378 GSList *list, *rootlist = NULL;
6381 gboolean corlib_type = FALSE;
6383 g_assert (rank <= 255);
6386 /* bounded only matters for one-dimensional arrays */
6389 image = eclass->image;
6391 if (rank == 1 && !bounded) {
6393 * This case is very frequent not just during compilation because of calls
6394 * from mono_class_from_mono_type (), mono_array_new (),
6395 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6397 EnterCriticalSection (&image->szarray_cache_lock);
6398 if (!image->szarray_cache)
6399 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6400 class = g_hash_table_lookup (image->szarray_cache, eclass);
6401 LeaveCriticalSection (&image->szarray_cache_lock);
6405 mono_loader_lock ();
6407 mono_loader_lock ();
6409 if (!image->array_cache)
6410 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6412 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6413 for (; list; list = list->next) {
6415 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6416 mono_loader_unlock ();
6423 /* for the building corlib use System.Array from it */
6424 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6425 parent = mono_class_from_name (image, "System", "Array");
6428 parent = mono_defaults.array_class;
6429 if (!parent->inited)
6430 mono_class_init (parent);
6433 class = mono_image_alloc0 (image, sizeof (MonoClass));
6435 class->image = image;
6436 class->name_space = eclass->name_space;
6437 nsize = strlen (eclass->name);
6438 name = g_malloc (nsize + 2 + rank + 1);
6439 memcpy (name, eclass->name, nsize);
6442 memset (name + nsize + 1, ',', rank - 1);
6444 name [nsize + rank] = '*';
6445 name [nsize + rank + bounded] = ']';
6446 name [nsize + rank + bounded + 1] = 0;
6447 class->name = mono_image_strdup (image, name);
6450 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6452 classes_size += sizeof (MonoClass);
6454 class->type_token = 0;
6455 /* all arrays are marked serializable and sealed, bug #42779 */
6456 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6457 class->parent = parent;
6458 class->instance_size = mono_class_instance_size (class->parent);
6460 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6461 /*Arrays of those two types are invalid.*/
6462 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6463 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6464 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6465 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6466 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6468 /* element_size -1 is ok as this is not an instantitable type*/
6469 class->sizes.element_size = -1;
6471 class->sizes.element_size = mono_class_array_element_size (eclass);
6473 mono_class_setup_supertypes (class);
6475 if (eclass->generic_class)
6476 mono_class_init (eclass);
6477 if (!eclass->size_inited)
6478 mono_class_setup_fields (eclass);
6479 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6480 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6482 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6486 if (eclass->enumtype)
6487 class->cast_class = eclass->element_class;
6489 class->cast_class = eclass;
6491 switch (class->cast_class->byval_arg.type) {
6493 class->cast_class = mono_defaults.byte_class;
6496 class->cast_class = mono_defaults.int16_class;
6499 #if SIZEOF_VOID_P == 4
6503 class->cast_class = mono_defaults.int32_class;
6506 #if SIZEOF_VOID_P == 8
6510 class->cast_class = mono_defaults.int64_class;
6514 class->element_class = eclass;
6516 if ((rank > 1) || bounded) {
6517 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6518 class->byval_arg.type = MONO_TYPE_ARRAY;
6519 class->byval_arg.data.array = at;
6520 at->eklass = eclass;
6522 /* FIXME: complete.... */
6524 class->byval_arg.type = MONO_TYPE_SZARRAY;
6525 class->byval_arg.data.klass = eclass;
6527 class->this_arg = class->byval_arg;
6528 class->this_arg.byref = 1;
6533 class->generic_container = eclass->generic_container;
6535 if (rank == 1 && !bounded) {
6536 MonoClass *prev_class;
6538 EnterCriticalSection (&image->szarray_cache_lock);
6539 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6541 /* Someone got in before us */
6544 g_hash_table_insert (image->szarray_cache, eclass, class);
6545 LeaveCriticalSection (&image->szarray_cache_lock);
6547 list = g_slist_append (rootlist, class);
6548 g_hash_table_insert (image->array_cache, eclass, list);
6551 mono_loader_unlock ();
6553 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6559 * mono_array_class_get:
6560 * @element_class: element class
6561 * @rank: the dimension of the array class
6563 * Returns: a class object describing the array with element type @element_type and
6567 mono_array_class_get (MonoClass *eclass, guint32 rank)
6569 return mono_bounded_array_class_get (eclass, rank, FALSE);
6573 * mono_class_instance_size:
6576 * Returns: the size of an object instance
6579 mono_class_instance_size (MonoClass *klass)
6581 if (!klass->size_inited)
6582 mono_class_init (klass);
6584 return klass->instance_size;
6588 * mono_class_min_align:
6591 * Returns: minimm alignment requirements
6594 mono_class_min_align (MonoClass *klass)
6596 if (!klass->size_inited)
6597 mono_class_init (klass);
6599 return klass->min_align;
6603 * mono_class_value_size:
6606 * This function is used for value types, and return the
6607 * space and the alignment to store that kind of value object.
6609 * Returns: the size of a value of kind @klass
6612 mono_class_value_size (MonoClass *klass, guint32 *align)
6616 /* fixme: check disable, because we still have external revereces to
6617 * mscorlib and Dummy Objects
6619 /*g_assert (klass->valuetype);*/
6621 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6624 *align = klass->min_align;
6630 * mono_class_data_size:
6633 * Returns: the size of the static class data
6636 mono_class_data_size (MonoClass *klass)
6639 mono_class_init (klass);
6641 /* in arrays, sizes.class_size is unioned with element_size
6642 * and arrays have no static fields
6646 return klass->sizes.class_size;
6650 * Auxiliary routine to mono_class_get_field
6652 * Takes a field index instead of a field token.
6654 static MonoClassField *
6655 mono_class_get_field_idx (MonoClass *class, int idx)
6657 mono_class_setup_fields_locking (class);
6658 if (class->exception_type)
6662 if (class->image->uncompressed_metadata) {
6664 * class->field.first points to the FieldPtr table, while idx points into the
6665 * Field table, so we have to do a search.
6667 /*FIXME this is broken for types with multiple fields with the same name.*/
6668 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6671 for (i = 0; i < class->field.count; ++i)
6672 if (mono_field_get_name (&class->fields [i]) == name)
6673 return &class->fields [i];
6674 g_assert_not_reached ();
6676 if (class->field.count) {
6677 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6678 return &class->fields [idx - class->field.first];
6682 class = class->parent;
6688 * mono_class_get_field:
6689 * @class: the class to lookup the field.
6690 * @field_token: the field token
6692 * Returns: A MonoClassField representing the type and offset of
6693 * the field, or a NULL value if the field does not belong to this
6697 mono_class_get_field (MonoClass *class, guint32 field_token)
6699 int idx = mono_metadata_token_index (field_token);
6701 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6703 return mono_class_get_field_idx (class, idx - 1);
6707 * mono_class_get_field_from_name:
6708 * @klass: the class to lookup the field.
6709 * @name: the field name
6711 * Search the class @klass and it's parents for a field with the name @name.
6713 * Returns: the MonoClassField pointer of the named field or NULL
6716 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6718 return mono_class_get_field_from_name_full (klass, name, NULL);
6722 * mono_class_get_field_from_name_full:
6723 * @klass: the class to lookup the field.
6724 * @name: the field name
6725 * @type: the type of the fields. This optional.
6727 * Search the class @klass and it's parents for a field with the name @name and type @type.
6729 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6730 * of its generic type definition.
6732 * Returns: the MonoClassField pointer of the named field or NULL
6735 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6739 mono_class_setup_fields_locking (klass);
6740 if (klass->exception_type)
6744 for (i = 0; i < klass->field.count; ++i) {
6745 MonoClassField *field = &klass->fields [i];
6747 if (strcmp (name, mono_field_get_name (field)) != 0)
6751 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6752 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6757 klass = klass->parent;
6763 * mono_class_get_field_token:
6764 * @field: the field we need the token of
6766 * Get the token of a field. Note that the tokesn is only valid for the image
6767 * the field was loaded from. Don't use this function for fields in dynamic types.
6769 * Returns: the token representing the field in the image it was loaded from.
6772 mono_class_get_field_token (MonoClassField *field)
6774 MonoClass *klass = field->parent;
6777 mono_class_setup_fields_locking (klass);
6782 for (i = 0; i < klass->field.count; ++i) {
6783 if (&klass->fields [i] == field) {
6784 int idx = klass->field.first + i + 1;
6786 if (klass->image->uncompressed_metadata)
6787 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6788 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6791 klass = klass->parent;
6794 g_assert_not_reached ();
6799 mono_field_get_index (MonoClassField *field)
6801 int index = field - field->parent->fields;
6803 g_assert (index >= 0 && index < field->parent->field.count);
6809 * mono_class_get_field_default_value:
6811 * Return the default value of the field as a pointer into the metadata blob.
6814 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6817 guint32 constant_cols [MONO_CONSTANT_SIZE];
6819 MonoClass *klass = field->parent;
6821 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6823 if (!klass->ext || !klass->ext->field_def_values) {
6824 mono_loader_lock ();
6825 mono_class_alloc_ext (klass);
6826 if (!klass->ext->field_def_values)
6827 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6828 mono_loader_unlock ();
6831 field_index = mono_field_get_index (field);
6833 if (!klass->ext->field_def_values [field_index].data) {
6834 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6838 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6840 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6841 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6842 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6845 *def_type = klass->ext->field_def_values [field_index].def_type;
6846 return klass->ext->field_def_values [field_index].data;
6850 mono_property_get_index (MonoProperty *prop)
6852 int index = prop - prop->parent->ext->properties;
6854 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6860 * mono_class_get_property_default_value:
6862 * Return the default value of the field as a pointer into the metadata blob.
6865 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6868 guint32 constant_cols [MONO_CONSTANT_SIZE];
6869 MonoClass *klass = property->parent;
6871 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6873 * We don't cache here because it is not used by C# so it's quite rare, but
6874 * we still do the lookup in klass->ext because that is where the data
6875 * is stored for dynamic assemblies.
6878 if (klass->image->dynamic) {
6879 int prop_index = mono_property_get_index (property);
6880 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6881 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6882 return klass->ext->prop_def_values [prop_index].data;
6886 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6890 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6891 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6892 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6896 mono_class_get_event_token (MonoEvent *event)
6898 MonoClass *klass = event->parent;
6903 for (i = 0; i < klass->ext->event.count; ++i) {
6904 if (&klass->ext->events [i] == event)
6905 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6908 klass = klass->parent;
6911 g_assert_not_reached ();
6916 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6920 gpointer iter = NULL;
6921 while ((p = mono_class_get_properties (klass, &iter))) {
6922 if (! strcmp (name, p->name))
6925 klass = klass->parent;
6931 mono_class_get_property_token (MonoProperty *prop)
6933 MonoClass *klass = prop->parent;
6937 gpointer iter = NULL;
6938 while ((p = mono_class_get_properties (klass, &iter))) {
6939 if (&klass->ext->properties [i] == prop)
6940 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6944 klass = klass->parent;
6947 g_assert_not_reached ();
6952 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6954 const char *name, *nspace;
6956 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6958 switch (type_token & 0xff000000){
6959 case MONO_TOKEN_TYPE_DEF: {
6960 guint32 cols [MONO_TYPEDEF_SIZE];
6961 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6962 guint tidx = mono_metadata_token_index (type_token);
6964 if (tidx > tt->rows)
6965 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6967 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6968 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6969 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6970 if (strlen (nspace) == 0)
6971 return g_strdup_printf ("%s", name);
6973 return g_strdup_printf ("%s.%s", nspace, name);
6976 case MONO_TOKEN_TYPE_REF: {
6978 guint32 cols [MONO_TYPEREF_SIZE];
6979 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6980 guint tidx = mono_metadata_token_index (type_token);
6983 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6985 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6986 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6987 mono_error_cleanup (&error);
6991 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6992 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6993 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6994 if (strlen (nspace) == 0)
6995 return g_strdup_printf ("%s", name);
6997 return g_strdup_printf ("%s.%s", nspace, name);
7000 case MONO_TOKEN_TYPE_SPEC:
7001 return g_strdup_printf ("Typespec 0x%08x", type_token);
7003 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7008 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7011 return g_strdup_printf ("DynamicAssembly %s", image->name);
7013 switch (type_token & 0xff000000){
7014 case MONO_TOKEN_TYPE_DEF:
7015 if (image->assembly)
7016 return mono_stringify_assembly_name (&image->assembly->aname);
7017 else if (image->assembly_name)
7018 return g_strdup (image->assembly_name);
7019 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7020 case MONO_TOKEN_TYPE_REF: {
7022 MonoAssemblyName aname;
7023 guint32 cols [MONO_TYPEREF_SIZE];
7024 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7025 guint32 idx = mono_metadata_token_index (type_token);
7028 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7030 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7031 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7032 mono_error_cleanup (&error);
7035 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7037 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7038 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7039 case MONO_RESOLTION_SCOPE_MODULE:
7041 return g_strdup ("");
7042 case MONO_RESOLTION_SCOPE_MODULEREF:
7044 return g_strdup ("");
7045 case MONO_RESOLTION_SCOPE_TYPEREF:
7047 return g_strdup ("");
7048 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7049 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7050 return mono_stringify_assembly_name (&aname);
7052 g_assert_not_reached ();
7056 case MONO_TOKEN_TYPE_SPEC:
7058 return g_strdup ("");
7060 g_assert_not_reached ();
7067 * mono_class_get_full:
7068 * @image: the image where the class resides
7069 * @type_token: the token for the class
7070 * @context: the generic context used to evaluate generic instantiations in
7072 * Returns: the MonoClass that represents @type_token in @image
7075 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7078 MonoClass *class = NULL;
7080 if (image->dynamic) {
7081 int table = mono_metadata_token_table (type_token);
7083 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7084 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7087 return mono_lookup_dynamic_token (image, type_token, context);
7090 switch (type_token & 0xff000000){
7091 case MONO_TOKEN_TYPE_DEF:
7092 class = mono_class_create_from_typedef (image, type_token, &error);
7093 if (!mono_error_ok (&error)) {
7094 mono_loader_set_error_from_mono_error (&error);
7095 /*FIXME don't swallow the error message*/
7096 mono_error_cleanup (&error);
7100 case MONO_TOKEN_TYPE_REF:
7101 class = mono_class_from_typeref (image, type_token);
7103 case MONO_TOKEN_TYPE_SPEC:
7104 class = mono_class_create_from_typespec (image, type_token, context, &error);
7105 if (!mono_error_ok (&error)) {
7106 /*FIXME don't swallow the error message*/
7107 mono_error_cleanup (&error);
7111 g_warning ("unknown token type %x", type_token & 0xff000000);
7112 g_assert_not_reached ();
7116 char *name = mono_class_name_from_token (image, type_token);
7117 char *assembly = mono_assembly_name_from_token (image, type_token);
7118 mono_loader_set_error_type_load (name, assembly);
7128 * mono_type_get_full:
7129 * @image: the image where the type resides
7130 * @type_token: the token for the type
7131 * @context: the generic context used to evaluate generic instantiations in
7133 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7135 * Returns: the MonoType that represents @type_token in @image
7138 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7141 MonoType *type = NULL;
7142 gboolean inflated = FALSE;
7144 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7146 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7148 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7149 MonoClass *class = mono_class_get_full (image, type_token, context);
7150 return class ? mono_class_get_type (class) : NULL;
7153 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7155 if (!mono_error_ok (&error)) {
7156 /*FIXME don't swalloc the error message.*/
7157 char *name = mono_class_name_from_token (image, type_token);
7158 char *assembly = mono_assembly_name_from_token (image, type_token);
7160 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7162 mono_error_cleanup (&error);
7163 mono_loader_set_error_type_load (name, assembly);
7168 MonoType *tmp = type;
7169 type = mono_class_get_type (mono_class_from_mono_type (type));
7170 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7171 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7172 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7174 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7176 if (type->type != tmp->type)
7179 mono_metadata_free_type (tmp);
7186 mono_class_get (MonoImage *image, guint32 type_token)
7188 return mono_class_get_full (image, type_token, NULL);
7192 * mono_image_init_name_cache:
7194 * Initializes the class name cache stored in image->name_cache.
7196 * LOCKING: Acquires the corresponding image lock.
7199 mono_image_init_name_cache (MonoImage *image)
7201 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7202 guint32 cols [MONO_TYPEDEF_SIZE];
7205 guint32 i, visib, nspace_index;
7206 GHashTable *name_cache2, *nspace_table;
7208 mono_image_lock (image);
7210 if (image->name_cache) {
7211 mono_image_unlock (image);
7215 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7217 if (image->dynamic) {
7218 mono_image_unlock (image);
7222 /* Temporary hash table to avoid lookups in the nspace_table */
7223 name_cache2 = g_hash_table_new (NULL, NULL);
7225 for (i = 1; i <= t->rows; ++i) {
7226 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7227 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7229 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7230 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7232 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7234 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7235 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7237 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7238 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7239 if (!nspace_table) {
7240 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7241 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7242 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7245 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7248 /* Load type names from EXPORTEDTYPES table */
7250 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7251 guint32 cols [MONO_EXP_TYPE_SIZE];
7254 for (i = 0; i < t->rows; ++i) {
7255 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7256 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7257 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7259 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7260 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7261 if (!nspace_table) {
7262 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7263 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7264 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7267 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7271 g_hash_table_destroy (name_cache2);
7272 mono_image_unlock (image);
7275 /*FIXME Only dynamic assemblies should allow this operation.*/
7277 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7278 const char *name, guint32 index)
7280 GHashTable *nspace_table;
7281 GHashTable *name_cache;
7284 mono_image_lock (image);
7286 if (!image->name_cache)
7287 mono_image_init_name_cache (image);
7289 name_cache = image->name_cache;
7290 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7291 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7292 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7295 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7296 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7298 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7300 mono_image_unlock (image);
7309 find_nocase (gpointer key, gpointer value, gpointer user_data)
7311 char *name = (char*)key;
7312 FindUserData *data = (FindUserData*)user_data;
7314 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7315 data->value = value;
7319 * mono_class_from_name_case:
7320 * @image: The MonoImage where the type is looked up in
7321 * @name_space: the type namespace
7322 * @name: the type short name.
7324 * Obtains a MonoClass with a given namespace and a given name which
7325 * is located in the given MonoImage. The namespace and name
7326 * lookups are case insensitive.
7329 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7331 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7332 guint32 cols [MONO_TYPEDEF_SIZE];
7337 if (image->dynamic) {
7339 FindUserData user_data;
7341 mono_image_lock (image);
7343 if (!image->name_cache)
7344 mono_image_init_name_cache (image);
7346 user_data.key = name_space;
7347 user_data.value = NULL;
7348 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7350 if (user_data.value) {
7351 GHashTable *nspace_table = (GHashTable*)user_data.value;
7353 user_data.key = name;
7354 user_data.value = NULL;
7356 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7358 if (user_data.value)
7359 token = GPOINTER_TO_UINT (user_data.value);
7362 mono_image_unlock (image);
7365 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7371 /* add a cache if needed */
7372 for (i = 1; i <= t->rows; ++i) {
7373 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7374 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7376 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7377 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7379 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7381 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7382 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7383 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7384 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7390 return_nested_in (MonoClass *class, char *nested)
7393 char *s = strchr (nested, '/');
7394 gpointer iter = NULL;
7401 while ((found = mono_class_get_nested_types (class, &iter))) {
7402 if (strcmp (found->name, nested) == 0) {
7404 return return_nested_in (found, s);
7412 search_modules (MonoImage *image, const char *name_space, const char *name)
7414 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7415 MonoImage *file_image;
7420 * The EXPORTEDTYPES table only contains public types, so have to search the
7422 * Note: image->modules contains the contents of the MODULEREF table, while
7423 * the real module list is in the FILE table.
7425 for (i = 0; i < file_table->rows; i++) {
7426 guint32 cols [MONO_FILE_SIZE];
7427 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7428 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7431 file_image = mono_image_load_file_for_image (image, i + 1);
7433 class = mono_class_from_name (file_image, name_space, name);
7443 * mono_class_from_name:
7444 * @image: The MonoImage where the type is looked up in
7445 * @name_space: the type namespace
7446 * @name: the type short name.
7448 * Obtains a MonoClass with a given namespace and a given name which
7449 * is located in the given MonoImage.
7451 * To reference nested classes, use the "/" character as a separator.
7452 * For example use "Foo/Bar" to reference the class Bar that is nested
7453 * inside Foo, like this: "class Foo { class Bar {} }".
7456 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7458 GHashTable *nspace_table;
7459 MonoImage *loaded_image;
7466 if ((nested = strchr (name, '/'))) {
7467 int pos = nested - name;
7468 int len = strlen (name);
7471 memcpy (buf, name, len + 1);
7473 nested = buf + pos + 1;
7477 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7478 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7479 gboolean res = get_class_from_name (image, name_space, name, &class);
7482 class = search_modules (image, name_space, name);
7484 return class ? return_nested_in (class, nested) : NULL;
7490 mono_image_lock (image);
7492 if (!image->name_cache)
7493 mono_image_init_name_cache (image);
7495 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7498 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7500 mono_image_unlock (image);
7502 if (!token && image->dynamic && image->modules) {
7503 /* Search modules as well */
7504 for (i = 0; i < image->module_count; ++i) {
7505 MonoImage *module = image->modules [i];
7507 class = mono_class_from_name (module, name_space, name);
7514 class = search_modules (image, name_space, name);
7522 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7523 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7524 guint32 cols [MONO_EXP_TYPE_SIZE];
7527 idx = mono_metadata_token_index (token);
7529 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7531 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7532 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7533 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7536 class = mono_class_from_name (loaded_image, name_space, name);
7538 return return_nested_in (class, nested);
7540 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7541 guint32 assembly_idx;
7543 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7545 mono_assembly_load_reference (image, assembly_idx - 1);
7546 g_assert (image->references [assembly_idx - 1]);
7547 if (image->references [assembly_idx - 1] == (gpointer)-1)
7550 /* FIXME: Cycle detection */
7551 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7553 g_error ("not yet implemented");
7557 token = MONO_TOKEN_TYPE_DEF | token;
7559 class = mono_class_get (image, token);
7561 return return_nested_in (class, nested);
7566 * mono_class_is_subclass_of:
7567 * @klass: class to probe if it is a subclass of another one
7568 * @klassc: the class we suspect is the base class
7569 * @check_interfaces: whether we should perform interface checks
7571 * This method determines whether @klass is a subclass of @klassc.
7573 * If the @check_interfaces flag is set, then if @klassc is an interface
7574 * this method return true if the @klass implements the interface or
7575 * if @klass is an interface, if one of its base classes is @klass.
7577 * If @check_interfaces is false then, then if @klass is not an interface
7578 * then it returns true if the @klass is a subclass of @klassc.
7580 * if @klass is an interface and @klassc is System.Object, then this function
7585 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7586 gboolean check_interfaces)
7588 /*FIXME test for interfaces with variant generic arguments*/
7590 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7591 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7593 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7596 for (i = 0; i < klass->interface_count; i ++) {
7597 MonoClass *ic = klass->interfaces [i];
7602 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7607 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7610 if (klassc == mono_defaults.object_class)
7617 mono_type_is_generic_argument (MonoType *type)
7619 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7623 mono_class_has_variant_generic_params (MonoClass *klass)
7626 MonoGenericContainer *container;
7628 if (!klass->generic_class)
7631 container = klass->generic_class->container_class->generic_container;
7633 for (i = 0; i < container->type_argc; ++i)
7634 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7641 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7643 if (target == candidate)
7646 if (check_for_reference_conv &&
7647 mono_type_is_generic_argument (&target->byval_arg) &&
7648 mono_type_is_generic_argument (&candidate->byval_arg)) {
7649 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7650 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7652 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7655 if (!mono_class_is_assignable_from (target, candidate))
7661 * @container the generic container from the GTD
7662 * @klass: the class to be assigned to
7663 * @oklass: the source class
7665 * Both klass and oklass must be instances of the same generic interface.
7666 * Return true if @klass can be assigned to a @klass variable
7669 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7672 MonoType **klass_argv, **oklass_argv;
7673 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7674 MonoGenericContainer *container = klass_gtd->generic_container;
7676 if (klass == oklass)
7679 /*Viable candidates are instances of the same generic interface*/
7680 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7683 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7684 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7686 for (j = 0; j < container->type_argc; ++j) {
7687 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7688 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7690 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7694 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7695 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7697 if (param1_class != param2_class) {
7698 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7699 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7701 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7702 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7712 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7714 MonoGenericParam *gparam, *ogparam;
7715 MonoGenericParamInfo *tinfo, *cinfo;
7716 MonoClass **candidate_class;
7717 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7720 if (target == candidate)
7722 if (target->byval_arg.type != candidate->byval_arg.type)
7725 gparam = target->byval_arg.data.generic_param;
7726 ogparam = candidate->byval_arg.data.generic_param;
7727 tinfo = mono_generic_param_info (gparam);
7728 cinfo = mono_generic_param_info (ogparam);
7730 class_constraint_satisfied = FALSE;
7731 valuetype_constraint_satisfied = FALSE;
7733 /*candidate must have a super set of target's special constraints*/
7734 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7735 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7737 if (cinfo->constraints) {
7738 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7739 MonoClass *cc = *candidate_class;
7741 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7742 class_constraint_satisfied = TRUE;
7743 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7744 valuetype_constraint_satisfied = TRUE;
7747 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7748 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7750 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7752 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7754 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7755 valuetype_constraint_satisfied)) {
7760 /*candidate type constraints must be a superset of target's*/
7761 if (tinfo->constraints) {
7762 MonoClass **target_class;
7763 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7764 MonoClass *tc = *target_class;
7767 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7768 * check it's constraints since it satisfy the constraint by itself.
7770 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7773 if (!cinfo->constraints)
7776 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7777 MonoClass *cc = *candidate_class;
7779 if (mono_class_is_assignable_from (tc, cc))
7783 * This happens when we have the following:
7785 * Bar<K> where K : IFace
7786 * Foo<T, U> where T : U where U : IFace
7788 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7791 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7792 if (mono_gparam_is_assignable_from (target, cc))
7796 if (!*candidate_class)
7801 /*candidate itself must have a constraint that satisfy target*/
7802 if (cinfo->constraints) {
7803 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7804 MonoClass *cc = *candidate_class;
7805 if (mono_class_is_assignable_from (target, cc))
7813 * mono_class_is_assignable_from:
7814 * @klass: the class to be assigned to
7815 * @oklass: the source class
7817 * Return: true if an instance of object oklass can be assigned to an
7818 * instance of object @klass
7821 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7823 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7825 mono_class_init (klass);
7827 if (!oklass->inited)
7828 mono_class_init (oklass);
7830 if (klass->exception_type || oklass->exception_type)
7833 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7834 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7836 return mono_gparam_is_assignable_from (klass, oklass);
7839 if (MONO_CLASS_IS_INTERFACE (klass)) {
7840 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7841 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7842 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7846 for (i = 0; constraints [i]; ++i) {
7847 if (mono_class_is_assignable_from (klass, constraints [i]))
7855 /* interface_offsets might not be set for dynamic classes */
7856 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7858 * oklass might be a generic type parameter but they have
7859 * interface_offsets set.
7861 return mono_reflection_call_is_assignable_to (oklass, klass);
7862 if (!oklass->interface_bitmap)
7863 /* Happens with generic instances of not-yet created dynamic types */
7865 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7868 if (mono_class_has_variant_generic_params (klass)) {
7871 mono_class_setup_interfaces (oklass, &error);
7872 if (!mono_error_ok (&error)) {
7873 mono_error_cleanup (&error);
7877 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7878 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7879 MonoClass *iface = oklass->interfaces_packed [i];
7881 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7886 } else if (klass->delegate) {
7887 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7889 }else if (klass->rank) {
7890 MonoClass *eclass, *eoclass;
7892 if (oklass->rank != klass->rank)
7895 /* vectors vs. one dimensional arrays */
7896 if (oklass->byval_arg.type != klass->byval_arg.type)
7899 eclass = klass->cast_class;
7900 eoclass = oklass->cast_class;
7903 * a is b does not imply a[] is b[] when a is a valuetype, and
7904 * b is a reference type.
7907 if (eoclass->valuetype) {
7908 if ((eclass == mono_defaults.enum_class) ||
7909 (eclass == mono_defaults.enum_class->parent) ||
7910 (eclass == mono_defaults.object_class))
7914 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7915 } else if (mono_class_is_nullable (klass)) {
7916 if (mono_class_is_nullable (oklass))
7917 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7919 return mono_class_is_assignable_from (klass->cast_class, oklass);
7920 } else if (klass == mono_defaults.object_class)
7923 return mono_class_has_parent (oklass, klass);
7926 /*Check if @oklass is variant compatible with @klass.*/
7928 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7931 MonoType **klass_argv, **oklass_argv;
7932 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7933 MonoGenericContainer *container = klass_gtd->generic_container;
7935 /*Viable candidates are instances of the same generic interface*/
7936 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7939 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7940 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7942 for (j = 0; j < container->type_argc; ++j) {
7943 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7944 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7946 if (param1_class->valuetype != param2_class->valuetype)
7950 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7951 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7953 if (param1_class != param2_class) {
7954 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7955 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7957 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7958 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7966 /*Check if @candidate implements the interface @target*/
7968 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7972 gboolean is_variant = mono_class_has_variant_generic_params (target);
7974 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7975 if (mono_class_is_variant_compatible_slow (target, candidate))
7980 if (candidate == target)
7983 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7984 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7985 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7987 if (tb && tb->interfaces) {
7988 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7989 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7990 MonoClass *iface_class;
7992 /* we can't realize the type here since it can do pretty much anything. */
7995 iface_class = mono_class_from_mono_type (iface->type);
7996 if (iface_class == target)
7998 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8000 if (mono_class_implement_interface_slow (target, iface_class))
8005 /*setup_interfaces don't mono_class_init anything*/
8006 mono_class_setup_interfaces (candidate, &error);
8007 if (!mono_error_ok (&error)) {
8008 mono_error_cleanup (&error);
8012 for (i = 0; i < candidate->interface_count; ++i) {
8013 if (candidate->interfaces [i] == target)
8016 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8019 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8023 candidate = candidate->parent;
8024 } while (candidate);
8030 * Check if @oklass can be assigned to @klass.
8031 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8034 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8036 if (candidate == target)
8038 if (target == mono_defaults.object_class)
8041 if (mono_class_has_parent (candidate, target))
8044 /*If target is not an interface there is no need to check them.*/
8045 if (MONO_CLASS_IS_INTERFACE (target))
8046 return mono_class_implement_interface_slow (target, candidate);
8048 if (target->delegate && mono_class_has_variant_generic_params (target))
8049 return mono_class_is_variant_compatible (target, candidate, FALSE);
8051 /*FIXME properly handle nullables and arrays */
8052 /*FIXME properly handle (M)VAR */
8057 * mono_class_get_cctor:
8058 * @klass: A MonoClass pointer
8060 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8063 mono_class_get_cctor (MonoClass *klass)
8065 MonoCachedClassInfo cached_info;
8067 if (klass->image->dynamic) {
8069 * has_cctor is not set for these classes because mono_class_init () is
8072 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8075 if (!klass->has_cctor)
8078 if (mono_class_get_cached_class_info (klass, &cached_info))
8079 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8081 if (klass->generic_class && !klass->methods)
8082 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8084 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8088 * mono_class_get_finalizer:
8089 * @klass: The MonoClass pointer
8091 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8094 mono_class_get_finalizer (MonoClass *klass)
8096 MonoCachedClassInfo cached_info;
8099 mono_class_init (klass);
8100 if (!mono_class_has_finalizer (klass))
8103 if (mono_class_get_cached_class_info (klass, &cached_info))
8104 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8106 mono_class_setup_vtable (klass);
8107 return klass->vtable [finalize_slot];
8112 * mono_class_needs_cctor_run:
8113 * @klass: the MonoClass pointer
8114 * @caller: a MonoMethod describing the caller
8116 * Determines whenever the class has a static constructor and whenever it
8117 * needs to be called when executing CALLER.
8120 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8124 method = mono_class_get_cctor (klass);
8126 return (method == caller) ? FALSE : TRUE;
8132 * mono_class_array_element_size:
8135 * Returns: the number of bytes an element of type @klass
8136 * uses when stored into an array.
8139 mono_class_array_element_size (MonoClass *klass)
8141 MonoType *type = &klass->byval_arg;
8144 switch (type->type) {
8147 case MONO_TYPE_BOOLEAN:
8151 case MONO_TYPE_CHAR:
8160 case MONO_TYPE_CLASS:
8161 case MONO_TYPE_STRING:
8162 case MONO_TYPE_OBJECT:
8163 case MONO_TYPE_SZARRAY:
8164 case MONO_TYPE_ARRAY:
8166 case MONO_TYPE_MVAR:
8167 return sizeof (gpointer);
8172 case MONO_TYPE_VALUETYPE:
8173 if (type->data.klass->enumtype) {
8174 type = mono_class_enum_basetype (type->data.klass);
8175 klass = klass->element_class;
8178 return mono_class_instance_size (klass) - sizeof (MonoObject);
8179 case MONO_TYPE_GENERICINST:
8180 type = &type->data.generic_class->container_class->byval_arg;
8183 case MONO_TYPE_VOID:
8187 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8193 * mono_array_element_size:
8194 * @ac: pointer to a #MonoArrayClass
8196 * Returns: the size of single array element.
8199 mono_array_element_size (MonoClass *ac)
8201 g_assert (ac->rank);
8202 return ac->sizes.element_size;
8206 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8207 MonoGenericContext *context)
8209 if (image->dynamic) {
8210 MonoClass *tmp_handle_class;
8211 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8213 g_assert (tmp_handle_class);
8215 *handle_class = tmp_handle_class;
8217 if (tmp_handle_class == mono_defaults.typehandle_class)
8218 return &((MonoClass*)obj)->byval_arg;
8223 switch (token & 0xff000000) {
8224 case MONO_TOKEN_TYPE_DEF:
8225 case MONO_TOKEN_TYPE_REF:
8226 case MONO_TOKEN_TYPE_SPEC: {
8229 *handle_class = mono_defaults.typehandle_class;
8230 type = mono_type_get_full (image, token, context);
8233 mono_class_init (mono_class_from_mono_type (type));
8234 /* We return a MonoType* as handle */
8237 case MONO_TOKEN_FIELD_DEF: {
8239 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8243 *handle_class = mono_defaults.fieldhandle_class;
8244 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8247 mono_class_init (class);
8248 return mono_class_get_field (class, token);
8250 case MONO_TOKEN_METHOD_DEF:
8251 case MONO_TOKEN_METHOD_SPEC: {
8253 meth = mono_get_method_full (image, token, NULL, context);
8255 *handle_class = mono_defaults.methodhandle_class;
8258 case MONO_TOKEN_MEMBER_REF: {
8259 guint32 cols [MONO_MEMBERREF_SIZE];
8261 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8262 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8263 mono_metadata_decode_blob_size (sig, &sig);
8264 if (*sig == 0x6) { /* it's a field */
8266 MonoClassField *field;
8267 field = mono_field_from_token (image, token, &klass, context);
8269 *handle_class = mono_defaults.fieldhandle_class;
8273 meth = mono_get_method_full (image, token, NULL, context);
8275 *handle_class = mono_defaults.methodhandle_class;
8280 g_warning ("Unknown token 0x%08x in ldtoken", token);
8287 * This function might need to call runtime functions so it can't be part
8288 * of the metadata library.
8290 static MonoLookupDynamicToken lookup_dynamic = NULL;
8293 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8295 lookup_dynamic = func;
8299 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8301 MonoClass *handle_class;
8303 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8307 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8309 return lookup_dynamic (image, token, valid_token, handle_class, context);
8312 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8315 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8317 get_cached_class_info = func;
8321 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8323 if (!get_cached_class_info)
8326 return get_cached_class_info (klass, res);
8330 mono_install_get_class_from_name (MonoGetClassFromName func)
8332 get_class_from_name = func;
8336 mono_class_get_image (MonoClass *klass)
8338 return klass->image;
8342 * mono_class_get_element_class:
8343 * @klass: the MonoClass to act on
8345 * Returns: the element class of an array or an enumeration.
8348 mono_class_get_element_class (MonoClass *klass)
8350 return klass->element_class;
8354 * mono_class_is_valuetype:
8355 * @klass: the MonoClass to act on
8357 * Returns: true if the MonoClass represents a ValueType.
8360 mono_class_is_valuetype (MonoClass *klass)
8362 return klass->valuetype;
8366 * mono_class_is_enum:
8367 * @klass: the MonoClass to act on
8369 * Returns: true if the MonoClass represents an enumeration.
8372 mono_class_is_enum (MonoClass *klass)
8374 return klass->enumtype;
8378 * mono_class_enum_basetype:
8379 * @klass: the MonoClass to act on
8381 * Returns: the underlying type representation for an enumeration.
8384 mono_class_enum_basetype (MonoClass *klass)
8386 if (klass->element_class == klass)
8387 /* SRE or broken types */
8390 return &klass->element_class->byval_arg;
8394 * mono_class_get_parent
8395 * @klass: the MonoClass to act on
8397 * Returns: the parent class for this class.
8400 mono_class_get_parent (MonoClass *klass)
8402 return klass->parent;
8406 * mono_class_get_nesting_type;
8407 * @klass: the MonoClass to act on
8409 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8412 mono_class_get_nesting_type (MonoClass *klass)
8414 return klass->nested_in;
8418 * mono_class_get_rank:
8419 * @klass: the MonoClass to act on
8421 * Returns: the rank for the array (the number of dimensions).
8424 mono_class_get_rank (MonoClass *klass)
8430 * mono_class_get_flags:
8431 * @klass: the MonoClass to act on
8433 * The type flags from the TypeDef table from the metadata.
8434 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8437 * Returns: the flags from the TypeDef table.
8440 mono_class_get_flags (MonoClass *klass)
8442 return klass->flags;
8446 * mono_class_get_name
8447 * @klass: the MonoClass to act on
8449 * Returns: the name of the class.
8452 mono_class_get_name (MonoClass *klass)
8458 * mono_class_get_namespace:
8459 * @klass: the MonoClass to act on
8461 * Returns: the namespace of the class.
8464 mono_class_get_namespace (MonoClass *klass)
8466 return klass->name_space;
8470 * mono_class_get_type:
8471 * @klass: the MonoClass to act on
8473 * This method returns the internal Type representation for the class.
8475 * Returns: the MonoType from the class.
8478 mono_class_get_type (MonoClass *klass)
8480 return &klass->byval_arg;
8484 * mono_class_get_type_token
8485 * @klass: the MonoClass to act on
8487 * This method returns type token for the class.
8489 * Returns: the type token for the class.
8492 mono_class_get_type_token (MonoClass *klass)
8494 return klass->type_token;
8498 * mono_class_get_byref_type:
8499 * @klass: the MonoClass to act on
8504 mono_class_get_byref_type (MonoClass *klass)
8506 return &klass->this_arg;
8510 * mono_class_num_fields:
8511 * @klass: the MonoClass to act on
8513 * Returns: the number of static and instance fields in the class.
8516 mono_class_num_fields (MonoClass *klass)
8518 return klass->field.count;
8522 * mono_class_num_methods:
8523 * @klass: the MonoClass to act on
8525 * Returns: the number of methods in the class.
8528 mono_class_num_methods (MonoClass *klass)
8530 return klass->method.count;
8534 * mono_class_num_properties
8535 * @klass: the MonoClass to act on
8537 * Returns: the number of properties in the class.
8540 mono_class_num_properties (MonoClass *klass)
8542 mono_class_setup_properties (klass);
8544 return klass->ext->property.count;
8548 * mono_class_num_events:
8549 * @klass: the MonoClass to act on
8551 * Returns: the number of events in the class.
8554 mono_class_num_events (MonoClass *klass)
8556 mono_class_setup_events (klass);
8558 return klass->ext->event.count;
8562 * mono_class_get_fields:
8563 * @klass: the MonoClass to act on
8565 * This routine is an iterator routine for retrieving the fields in a class.
8567 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8568 * iterate over all of the elements. When no more values are
8569 * available, the return value is NULL.
8571 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8574 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8576 MonoClassField* field;
8580 mono_class_setup_fields_locking (klass);
8581 if (klass->exception_type)
8583 /* start from the first */
8584 if (klass->field.count) {
8585 return *iter = &klass->fields [0];
8593 if (field < &klass->fields [klass->field.count]) {
8594 return *iter = field;
8600 * mono_class_get_methods
8601 * @klass: the MonoClass to act on
8603 * This routine is an iterator routine for retrieving the fields in a class.
8605 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8606 * iterate over all of the elements. When no more values are
8607 * available, the return value is NULL.
8609 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8612 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8614 MonoMethod** method;
8618 mono_class_setup_methods (klass);
8621 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8622 * FIXME we should better report this error to the caller
8624 if (!klass->methods)
8626 /* start from the first */
8627 if (klass->method.count) {
8628 *iter = &klass->methods [0];
8629 return klass->methods [0];
8637 if (method < &klass->methods [klass->method.count]) {
8645 * mono_class_get_virtual_methods:
8647 * Iterate over the virtual methods of KLASS.
8649 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8652 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8654 MonoMethod** method;
8657 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass) || mono_debug_using_mono_debugger ()) {
8659 mono_class_setup_methods (klass);
8661 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8662 * FIXME we should better report this error to the caller
8664 if (!klass->methods)
8666 /* start from the first */
8667 method = &klass->methods [0];
8672 while (method < &klass->methods [klass->method.count]) {
8673 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8677 if (method < &klass->methods [klass->method.count]) {
8684 /* Search directly in metadata to avoid calling setup_methods () */
8685 MonoMethod *res = NULL;
8691 start_index = GPOINTER_TO_UINT (*iter);
8694 for (i = start_index; i < klass->method.count; ++i) {
8697 /* class->method.first points into the methodptr table */
8698 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8700 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8704 if (i < klass->method.count) {
8705 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8706 /* Add 1 here so the if (*iter) check fails */
8707 *iter = GUINT_TO_POINTER (i + 1);
8716 * mono_class_get_properties:
8717 * @klass: the MonoClass to act on
8719 * This routine is an iterator routine for retrieving the properties in a class.
8721 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8722 * iterate over all of the elements. When no more values are
8723 * available, the return value is NULL.
8725 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8728 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8730 MonoProperty* property;
8734 mono_class_setup_properties (klass);
8735 /* start from the first */
8736 if (klass->ext->property.count) {
8737 return *iter = &klass->ext->properties [0];
8745 if (property < &klass->ext->properties [klass->ext->property.count]) {
8746 return *iter = property;
8752 * mono_class_get_events:
8753 * @klass: the MonoClass to act on
8755 * This routine is an iterator routine for retrieving the properties in a class.
8757 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8758 * iterate over all of the elements. When no more values are
8759 * available, the return value is NULL.
8761 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8764 mono_class_get_events (MonoClass* klass, gpointer *iter)
8770 mono_class_setup_events (klass);
8771 /* start from the first */
8772 if (klass->ext->event.count) {
8773 return *iter = &klass->ext->events [0];
8781 if (event < &klass->ext->events [klass->ext->event.count]) {
8782 return *iter = event;
8788 * mono_class_get_interfaces
8789 * @klass: the MonoClass to act on
8791 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8793 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8794 * iterate over all of the elements. When no more values are
8795 * available, the return value is NULL.
8797 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8800 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8808 mono_class_init (klass);
8809 if (!klass->interfaces_inited) {
8810 mono_class_setup_interfaces (klass, &error);
8811 if (!mono_error_ok (&error)) {
8812 mono_error_cleanup (&error);
8816 /* start from the first */
8817 if (klass->interface_count) {
8818 *iter = &klass->interfaces [0];
8819 return klass->interfaces [0];
8827 if (iface < &klass->interfaces [klass->interface_count]) {
8835 * mono_class_get_nested_types
8836 * @klass: the MonoClass to act on
8838 * This routine is an iterator routine for retrieving the nested types of a class.
8839 * This works only if @klass is non-generic, or a generic type definition.
8841 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8842 * iterate over all of the elements. When no more values are
8843 * available, the return value is NULL.
8845 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8848 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8856 if (!klass->nested_classes_inited) {
8857 if (!klass->type_token)
8858 klass->nested_classes_inited = TRUE;
8859 mono_loader_lock ();
8860 if (!klass->nested_classes_inited) {
8861 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8864 guint32 cols [MONO_NESTED_CLASS_SIZE];
8865 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8866 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8867 if (!mono_error_ok (&error)) {
8868 /*FIXME don't swallow the error message*/
8869 mono_error_cleanup (&error);
8871 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8874 mono_class_alloc_ext (klass);
8875 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8877 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8880 mono_memory_barrier ();
8881 klass->nested_classes_inited = TRUE;
8882 mono_loader_unlock ();
8886 /* start from the first */
8887 if (klass->ext && klass->ext->nested_classes) {
8888 *iter = klass->ext->nested_classes;
8889 return klass->ext->nested_classes->data;
8891 /* no nested types */
8905 * mono_field_get_name:
8906 * @field: the MonoClassField to act on
8908 * Returns: the name of the field.
8911 mono_field_get_name (MonoClassField *field)
8917 * mono_field_get_type:
8918 * @field: the MonoClassField to act on
8920 * Returns: MonoType of the field.
8923 mono_field_get_type (MonoClassField *field)
8926 MonoType *type = mono_field_get_type_checked (field, &error);
8927 if (!mono_error_ok (&error)) {
8928 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8929 mono_error_cleanup (&error);
8936 * mono_field_get_type_checked:
8937 * @field: the MonoClassField to act on
8938 * @error: used to return any erro found while retrieving @field type
8940 * Returns: MonoType of the field.
8943 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8945 mono_error_init (error);
8947 mono_field_resolve_type (field, error);
8952 * mono_field_get_parent:
8953 * @field: the MonoClassField to act on
8955 * Returns: MonoClass where the field was defined.
8958 mono_field_get_parent (MonoClassField *field)
8960 return field->parent;
8964 * mono_field_get_flags;
8965 * @field: the MonoClassField to act on
8967 * The metadata flags for a field are encoded using the
8968 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8970 * Returns: the flags for the field.
8973 mono_field_get_flags (MonoClassField *field)
8976 return mono_field_resolve_flags (field);
8977 return field->type->attrs;
8981 * mono_field_get_offset;
8982 * @field: the MonoClassField to act on
8984 * Returns: the field offset.
8987 mono_field_get_offset (MonoClassField *field)
8989 return field->offset;
8993 mono_field_get_rva (MonoClassField *field)
8997 MonoClass *klass = field->parent;
8999 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9001 if (!klass->ext || !klass->ext->field_def_values) {
9002 mono_loader_lock ();
9003 mono_class_alloc_ext (klass);
9004 if (!klass->ext->field_def_values)
9005 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9006 mono_loader_unlock ();
9009 field_index = mono_field_get_index (field);
9011 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
9012 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9014 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9015 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9018 return klass->ext->field_def_values [field_index].data;
9022 * mono_field_get_data;
9023 * @field: the MonoClassField to act on
9025 * Returns: pointer to the metadata constant value or to the field
9026 * data if it has an RVA flag.
9029 mono_field_get_data (MonoClassField *field)
9031 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9032 MonoTypeEnum def_type;
9034 return mono_class_get_field_default_value (field, &def_type);
9035 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9036 return mono_field_get_rva (field);
9043 * mono_property_get_name:
9044 * @prop: the MonoProperty to act on
9046 * Returns: the name of the property
9049 mono_property_get_name (MonoProperty *prop)
9055 * mono_property_get_set_method
9056 * @prop: the MonoProperty to act on.
9058 * Returns: the setter method of the property (A MonoMethod)
9061 mono_property_get_set_method (MonoProperty *prop)
9067 * mono_property_get_get_method
9068 * @prop: the MonoProperty to act on.
9070 * Returns: the setter method of the property (A MonoMethod)
9073 mono_property_get_get_method (MonoProperty *prop)
9079 * mono_property_get_parent:
9080 * @prop: the MonoProperty to act on.
9082 * Returns: the MonoClass where the property was defined.
9085 mono_property_get_parent (MonoProperty *prop)
9087 return prop->parent;
9091 * mono_property_get_flags:
9092 * @prop: the MonoProperty to act on.
9094 * The metadata flags for a property are encoded using the
9095 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9097 * Returns: the flags for the property.
9100 mono_property_get_flags (MonoProperty *prop)
9106 * mono_event_get_name:
9107 * @event: the MonoEvent to act on
9109 * Returns: the name of the event.
9112 mono_event_get_name (MonoEvent *event)
9118 * mono_event_get_add_method:
9119 * @event: The MonoEvent to act on.
9121 * Returns: the @add' method for the event (a MonoMethod).
9124 mono_event_get_add_method (MonoEvent *event)
9130 * mono_event_get_remove_method:
9131 * @event: The MonoEvent to act on.
9133 * Returns: the @remove method for the event (a MonoMethod).
9136 mono_event_get_remove_method (MonoEvent *event)
9138 return event->remove;
9142 * mono_event_get_raise_method:
9143 * @event: The MonoEvent to act on.
9145 * Returns: the @raise method for the event (a MonoMethod).
9148 mono_event_get_raise_method (MonoEvent *event)
9150 return event->raise;
9154 * mono_event_get_parent:
9155 * @event: the MonoEvent to act on.
9157 * Returns: the MonoClass where the event is defined.
9160 mono_event_get_parent (MonoEvent *event)
9162 return event->parent;
9166 * mono_event_get_flags
9167 * @event: the MonoEvent to act on.
9169 * The metadata flags for an event are encoded using the
9170 * EVENT_* constants. See the tabledefs.h file for details.
9172 * Returns: the flags for the event.
9175 mono_event_get_flags (MonoEvent *event)
9177 return event->attrs;
9181 * mono_class_get_method_from_name:
9182 * @klass: where to look for the method
9183 * @name_space: name of the method
9184 * @param_count: number of parameters. -1 for any number.
9186 * Obtains a MonoMethod with a given name and number of parameters.
9187 * It only works if there are no multiple signatures for any given method name.
9190 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9192 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9196 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9198 MonoMethod *res = NULL;
9201 /* Search directly in the metadata to avoid calling setup_methods () */
9202 for (i = 0; i < klass->method.count; ++i) {
9203 guint32 cols [MONO_METHOD_SIZE];
9205 MonoMethodSignature *sig;
9207 /* class->method.first points into the methodptr table */
9208 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9210 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9211 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9212 if (param_count == -1) {
9216 sig = mono_method_signature (method);
9217 if (sig && sig->param_count == param_count) {
9228 * mono_class_get_method_from_name_flags:
9229 * @klass: where to look for the method
9230 * @name_space: name of the method
9231 * @param_count: number of parameters. -1 for any number.
9232 * @flags: flags which must be set in the method
9234 * Obtains a MonoMethod with a given name and number of parameters.
9235 * It only works if there are no multiple signatures for any given method name.
9238 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9240 MonoMethod *res = NULL;
9243 mono_class_init (klass);
9245 if (klass->generic_class && !klass->methods) {
9246 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9248 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9252 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9253 mono_class_setup_methods (klass);
9255 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9256 See mono/tests/array_load_exception.il
9257 FIXME we should better report this error to the caller
9259 if (!klass->methods)
9261 for (i = 0; i < klass->method.count; ++i) {
9262 MonoMethod *method = klass->methods [i];
9264 if (method->name[0] == name [0] &&
9265 !strcmp (name, method->name) &&
9266 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9267 ((method->flags & flags) == flags)) {
9274 res = find_method_in_metadata (klass, name, param_count, flags);
9281 * mono_class_set_failure:
9282 * @klass: class in which the failure was detected
9283 * @ex_type: the kind of exception/error to be thrown (later)
9284 * @ex_data: exception data (specific to each type of exception/error)
9286 * Keep a detected failure informations in the class for later processing.
9287 * Note that only the first failure is kept.
9289 * LOCKING: Acquires the loader lock.
9292 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9294 if (klass->exception_type)
9297 mono_loader_lock ();
9298 klass->exception_type = ex_type;
9300 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9301 mono_loader_unlock ();
9307 * mono_class_get_exception_data:
9309 * Return the exception_data property of KLASS.
9311 * LOCKING: Acquires the loader lock.
9314 mono_class_get_exception_data (MonoClass *klass)
9316 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9320 * mono_classes_init:
9322 * Initialize the resources used by this module.
9325 mono_classes_init (void)
9327 mono_counters_register ("Inflated methods size",
9328 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9329 mono_counters_register ("Inflated classes",
9330 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9331 mono_counters_register ("Inflated classes size",
9332 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9333 mono_counters_register ("MonoClass size",
9334 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9335 mono_counters_register ("MonoClassExt size",
9336 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9340 * mono_classes_cleanup:
9342 * Free the resources used by this module.
9345 mono_classes_cleanup (void)
9347 if (global_interface_bitset)
9348 mono_bitset_free (global_interface_bitset);
9349 global_interface_bitset = NULL;
9353 * mono_class_get_exception_for_failure:
9354 * @klass: class in which the failure was detected
9356 * Return a constructed MonoException than the caller can then throw
9357 * using mono_raise_exception - or NULL if no failure is present (or
9358 * doesn't result in an exception).
9361 mono_class_get_exception_for_failure (MonoClass *klass)
9363 gpointer exception_data = mono_class_get_exception_data (klass);
9365 switch (klass->exception_type) {
9366 #ifndef DISABLE_SECURITY
9367 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9368 MonoDomain *domain = mono_domain_get ();
9369 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9370 MonoMethod *method = exception_data;
9371 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9372 MonoObject *exc = NULL;
9376 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9377 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9378 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9380 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9381 return (MonoException*) exc;
9384 case MONO_EXCEPTION_TYPE_LOAD: {
9387 char *str = mono_type_get_full_name (klass);
9388 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9389 name = mono_string_new (mono_domain_get (), str);
9391 ex = mono_get_exception_type_load (name, astr);
9395 case MONO_EXCEPTION_MISSING_METHOD: {
9396 char *class_name = exception_data;
9397 char *assembly_name = class_name + strlen (class_name) + 1;
9399 return mono_get_exception_missing_method (class_name, assembly_name);
9401 case MONO_EXCEPTION_MISSING_FIELD: {
9402 char *class_name = exception_data;
9403 char *member_name = class_name + strlen (class_name) + 1;
9405 return mono_get_exception_missing_field (class_name, member_name);
9407 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9408 char *msg_format = exception_data;
9409 char *assembly_name = msg_format + strlen (msg_format) + 1;
9410 char *msg = g_strdup_printf (msg_format, assembly_name);
9413 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9419 case MONO_EXCEPTION_BAD_IMAGE: {
9420 return mono_get_exception_bad_image_format (exception_data);
9423 MonoLoaderError *error;
9426 error = mono_loader_get_last_error ();
9428 ex = mono_loader_error_prepare_exception (error);
9432 /* TODO - handle other class related failures */
9439 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9441 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9442 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9444 if (outer_klass == inner_klass)
9446 inner_klass = inner_klass->nested_in;
9447 } while (inner_klass);
9452 mono_class_get_generic_type_definition (MonoClass *klass)
9454 return klass->generic_class ? klass->generic_class->container_class : klass;
9458 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9460 * Generic instantiations are ignored for all super types of @klass.
9462 * Visibility checks ignoring generic instantiations.
9465 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9468 klass = mono_class_get_generic_type_definition (klass);
9469 parent = mono_class_get_generic_type_definition (parent);
9470 mono_class_setup_supertypes (klass);
9472 for (i = 0; i < klass->idepth; ++i) {
9473 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9479 * Subtype can only access parent members with family protection if the site object
9480 * is subclass of Subtype. For example:
9481 * class A { protected int x; }
9483 * void valid_access () {
9487 * void invalid_access () {
9494 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9496 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9499 if (context_klass == NULL)
9501 /*if access_klass is not member_klass context_klass must be type compat*/
9502 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9508 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9511 if (accessing == accessed)
9513 if (!accessed || !accessing)
9516 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9517 * anywhere so untrusted friends are not safe to access platform's code internals */
9518 if (mono_security_core_clr_enabled ()) {
9519 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9523 mono_assembly_load_friends (accessed);
9524 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9525 MonoAssemblyName *friend = tmp->data;
9526 /* Be conservative with checks */
9529 if (strcmp (accessing->aname.name, friend->name))
9531 if (friend->public_key_token [0]) {
9532 if (!accessing->aname.public_key_token [0])
9534 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9543 * If klass is a generic type or if it is derived from a generic type, return the
9544 * MonoClass of the generic definition
9545 * Returns NULL if not found
9548 get_generic_definition_class (MonoClass *klass)
9551 if (klass->generic_class && klass->generic_class->container_class)
9552 return klass->generic_class->container_class;
9553 klass = klass->parent;
9559 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9562 for (i = 0; i < ginst->type_argc; ++i) {
9563 MonoType *type = ginst->type_argv[i];
9564 switch (type->type) {
9565 case MONO_TYPE_SZARRAY:
9566 if (!can_access_type (access_klass, type->data.klass))
9569 case MONO_TYPE_ARRAY:
9570 if (!can_access_type (access_klass, type->data.array->eklass))
9574 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9577 case MONO_TYPE_CLASS:
9578 case MONO_TYPE_VALUETYPE:
9579 case MONO_TYPE_GENERICINST:
9580 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9588 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9592 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9595 if (access_klass->element_class && !access_klass->enumtype)
9596 access_klass = access_klass->element_class;
9598 if (member_klass->element_class && !member_klass->enumtype)
9599 member_klass = member_klass->element_class;
9601 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9603 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9606 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9609 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9612 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9615 /*Non nested type with nested visibility. We just fail it.*/
9616 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9619 switch (access_level) {
9620 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9621 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9623 case TYPE_ATTRIBUTE_PUBLIC:
9626 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9629 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9630 return is_nesting_type (member_klass, access_klass);
9632 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9633 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9635 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9636 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9638 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9639 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9640 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9642 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9643 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9644 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9649 /* FIXME: check visibility of type, too */
9651 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9653 MonoClass *member_generic_def;
9654 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9657 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9658 access_klass->generic_container) &&
9659 (member_generic_def = get_generic_definition_class (member_klass))) {
9660 MonoClass *access_container;
9662 if (access_klass->generic_container)
9663 access_container = access_klass;
9665 access_container = access_klass->generic_class->container_class;
9667 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9671 /* Partition I 8.5.3.2 */
9672 /* the access level values are the same for fields and methods */
9673 switch (access_level) {
9674 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9675 /* same compilation unit */
9676 return access_klass->image == member_klass->image;
9677 case FIELD_ATTRIBUTE_PRIVATE:
9678 return access_klass == member_klass;
9679 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9680 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9681 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9684 case FIELD_ATTRIBUTE_ASSEMBLY:
9685 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9686 case FIELD_ATTRIBUTE_FAMILY:
9687 if (is_valid_family_access (access_klass, member_klass, context_klass))
9690 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9691 if (is_valid_family_access (access_klass, member_klass, context_klass))
9693 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9694 case FIELD_ATTRIBUTE_PUBLIC:
9701 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9703 /* FIXME: check all overlapping fields */
9704 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9706 MonoClass *nested = method->klass->nested_in;
9708 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9711 nested = nested->nested_in;
9718 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9720 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9722 MonoClass *nested = method->klass->nested_in;
9724 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9727 nested = nested->nested_in;
9732 * with generics calls to explicit interface implementations can be expressed
9733 * directly: the method is private, but we must allow it. This may be opening
9734 * a hole or the generics code should handle this differently.
9735 * Maybe just ensure the interface type is public.
9737 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9743 * mono_method_can_access_method_full:
9744 * @method: The caller method
9745 * @called: The called method
9746 * @context_klass: The static type on stack of the owner @called object used
9748 * This function must be used with instance calls, as they have more strict family accessibility.
9749 * It can be used with static methods, but context_klass should be NULL.
9751 * Returns: TRUE if caller have proper visibility and acessibility to @called
9754 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9756 MonoClass *access_class = method->klass;
9757 MonoClass *member_class = called->klass;
9758 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9760 MonoClass *nested = access_class->nested_in;
9762 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9765 nested = nested->nested_in;
9772 can = can_access_type (access_class, member_class);
9774 MonoClass *nested = access_class->nested_in;
9776 can = can_access_type (nested, member_class);
9779 nested = nested->nested_in;
9786 if (called->is_inflated) {
9787 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9788 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9797 * mono_method_can_access_field_full:
9798 * @method: The caller method
9799 * @field: The accessed field
9800 * @context_klass: The static type on stack of the owner @field object used
9802 * This function must be used with instance fields, as they have more strict family accessibility.
9803 * It can be used with static fields, but context_klass should be NULL.
9805 * Returns: TRUE if caller have proper visibility and acessibility to @field
9808 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9810 MonoClass *access_class = method->klass;
9811 MonoClass *member_class = field->parent;
9812 /* FIXME: check all overlapping fields */
9813 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9815 MonoClass *nested = access_class->nested_in;
9817 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9820 nested = nested->nested_in;
9827 can = can_access_type (access_class, member_class);
9829 MonoClass *nested = access_class->nested_in;
9831 can = can_access_type (nested, member_class);
9834 nested = nested->nested_in;
9844 * mono_class_can_access_class:
9845 * @source_class: The source class
9846 * @target_class: The accessed class
9848 * This function returns is @target_class is visible to @source_class
9850 * Returns: TRUE if source have proper visibility and acessibility to target
9853 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9855 return can_access_type (source_class, target_class);
9859 * mono_type_is_valid_enum_basetype:
9860 * @type: The MonoType to check
9862 * Returns: TRUE if the type can be used as the basetype of an enum
9864 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9865 switch (type->type) {
9868 case MONO_TYPE_BOOLEAN:
9871 case MONO_TYPE_CHAR:
9884 * mono_class_is_valid_enum:
9885 * @klass: An enum class to be validated
9887 * This method verify the required properties an enum should have.
9889 * Returns: TRUE if the informed enum class is valid
9891 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9892 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9893 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9895 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9896 MonoClassField * field;
9897 gpointer iter = NULL;
9898 gboolean found_base_field = FALSE;
9900 g_assert (klass->enumtype);
9901 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9902 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9906 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9909 while ((field = mono_class_get_fields (klass, &iter))) {
9910 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9911 if (found_base_field)
9913 found_base_field = TRUE;
9914 if (!mono_type_is_valid_enum_basetype (field->type))
9919 if (!found_base_field)
9922 if (klass->method.count > 0)
9929 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9931 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9935 * mono_class_setup_interface_id:
9937 * Initializes MonoClass::interface_id if required.
9939 * LOCKING: Acquires the loader lock.
9942 mono_class_setup_interface_id (MonoClass *class)
9944 mono_loader_lock ();
9945 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9946 class->interface_id = mono_get_unique_iid (class);
9947 mono_loader_unlock ();
9951 * mono_class_alloc_ext:
9953 * Allocate klass->ext if not already done.
9954 * LOCKING: Assumes the loader lock is held.
9957 mono_class_alloc_ext (MonoClass *klass)
9960 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9961 class_ext_size += sizeof (MonoClassExt);
9966 * mono_class_setup_interfaces:
9968 * Initialize class->interfaces/interfaces_count.
9969 * LOCKING: Acquires the loader lock.
9970 * This function can fail the type.
9973 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
9977 mono_error_init (error);
9979 if (klass->interfaces_inited)
9982 mono_loader_lock ();
9984 if (klass->interfaces_inited) {
9985 mono_loader_unlock ();
9989 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
9992 /* generic IList, ICollection, IEnumerable */
9993 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
9994 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
9996 args [0] = &klass->element_class->byval_arg;
9997 klass->interfaces [0] = mono_class_bind_generic_parameters (
9998 mono_defaults.generic_ilist_class, 1, args, FALSE);
9999 if (klass->interface_count > 1)
10000 klass->interfaces [1] = mono_class_bind_generic_parameters (
10001 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10002 } else if (klass->generic_class) {
10003 MonoClass *gklass = klass->generic_class->container_class;
10005 klass->interface_count = gklass->interface_count;
10006 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10007 for (i = 0; i < klass->interface_count; i++) {
10008 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10009 if (!mono_error_ok (error)) {
10010 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10011 klass->interfaces = NULL;
10017 mono_memory_barrier ();
10019 klass->interfaces_inited = TRUE;
10021 mono_loader_unlock ();
10025 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10027 MonoClass *class = field->parent;
10028 MonoImage *image = class->image;
10029 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10030 int field_idx = field - class->fields;
10032 mono_error_init (error);
10035 MonoClassField *gfield = >d->fields [field_idx];
10036 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10037 if (!mono_error_ok (error)) {
10038 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10039 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10043 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10044 if (!mono_error_ok (error)) {
10045 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10046 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10051 guint32 cols [MONO_FIELD_SIZE];
10052 MonoGenericContainer *container = NULL;
10053 int idx = class->field.first + field_idx;
10055 /*FIXME, in theory we do not lazy load SRE fields*/
10056 g_assert (!image->dynamic);
10058 if (class->generic_container) {
10059 container = class->generic_container;
10061 container = gtd->generic_container;
10062 g_assert (container);
10065 /* class->field.first and idx points into the fieldptr table */
10066 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10068 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10069 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10070 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10074 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10076 mono_metadata_decode_value (sig, &sig);
10077 /* FIELD signature == 0x06 */
10078 g_assert (*sig == 0x06);
10079 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10081 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10086 mono_field_resolve_flags (MonoClassField *field)
10088 MonoClass *class = field->parent;
10089 MonoImage *image = class->image;
10090 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10091 int field_idx = field - class->fields;
10095 MonoClassField *gfield = >d->fields [field_idx];
10096 return mono_field_get_flags (gfield);
10098 int idx = class->field.first + field_idx;
10100 /*FIXME, in theory we do not lazy load SRE fields*/
10101 g_assert (!image->dynamic);
10103 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10108 * mono_class_setup_basic_field_info:
10109 * @class: The class to initialize
10111 * Initializes the class->fields array of fields.
10112 * Aquires the loader lock.
10115 mono_class_setup_basic_field_info_locking (MonoClass *class)
10117 mono_loader_lock ();
10118 mono_class_setup_basic_field_info (class);
10119 mono_loader_unlock ();
10123 * mono_class_get_fields_lazy:
10124 * @klass: the MonoClass to act on
10126 * This routine is an iterator routine for retrieving the fields in a class.
10127 * Only minimal information about fields are loaded. Accessors must be used
10128 * for all MonoClassField returned.
10130 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10131 * iterate over all of the elements. When no more values are
10132 * available, the return value is NULL.
10134 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10137 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10139 MonoClassField* field;
10143 mono_class_setup_basic_field_info_locking (klass);
10144 if (!klass->fields)
10146 /* start from the first */
10147 if (klass->field.count) {
10148 return *iter = &klass->fields [0];
10156 if (field < &klass->fields [klass->field.count]) {
10157 return *iter = field;
10163 mono_class_full_name (MonoClass *klass)
10165 return mono_type_full_name (&klass->byval_arg);