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;
77 We use gclass recording to allow recursive system f types to be referenced by a parent.
79 Given the following type hierarchy:
81 class TextBox : TextBoxBase<TextBox> {}
82 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
83 class TextInput<T> : Input<T> where T: TextInput<T> {}
86 The runtime tries to load TextBoxBase<>.
87 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
88 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
89 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
91 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
92 at this point, iow, both are registered in the type map and both and a NULL parent. This means
93 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
95 To fix that what we do is to record all generic instantes created while resolving the parent of
96 any generic type definition and, after resolved, correct the parent field if needed.
99 static int record_gclass_instantiation;
100 static GSList *gclass_recorded_list;
101 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
104 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
107 enable_gclass_recording (void)
109 ++record_gclass_instantiation;
113 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
116 disable_gclass_recording (gclass_record_func func, void *user_data)
118 GSList **head = &gclass_recorded_list;
120 g_assert (record_gclass_instantiation > 0);
121 --record_gclass_instantiation;
124 GSList *node = *head;
125 if (func ((MonoClass*)node->data, user_data)) {
127 g_slist_free_1 (node);
133 /* We automatically discard all recorded gclasses when disabled. */
134 if (!record_gclass_instantiation && gclass_recorded_list) {
135 g_slist_free (gclass_recorded_list);
136 gclass_recorded_list = NULL;
141 * mono_class_from_typeref:
142 * @image: a MonoImage
143 * @type_token: a TypeRef token
145 * Creates the MonoClass* structure representing the type defined by
146 * the typeref token valid inside @image.
147 * Returns: the MonoClass* representing the typeref token, NULL ifcould
151 mono_class_from_typeref (MonoImage *image, guint32 type_token)
154 guint32 cols [MONO_TYPEREF_SIZE];
155 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
157 const char *name, *nspace;
161 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, &error)) {
162 mono_trace_warning (MONO_TRACE_TYPE, "Failed to resolve typeref from %s due to '%s'", image->name, mono_error_get_message (&error));
166 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
168 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
169 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
171 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
172 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
173 case MONO_RESOLTION_SCOPE_MODULE:
175 g_error ("null ResolutionScope not yet handled");
176 /* a typedef in disguise */
177 return mono_class_from_name (image, nspace, name);
178 case MONO_RESOLTION_SCOPE_MODULEREF:
179 module = mono_image_load_module (image, idx);
181 return mono_class_from_name (module, nspace, name);
183 char *msg = g_strdup_printf ("%s%s%s", nspace, nspace [0] ? "." : "", name);
186 human_name = mono_stringify_assembly_name (&image->assembly->aname);
187 mono_loader_set_error_type_load (msg, human_name);
193 case MONO_RESOLTION_SCOPE_TYPEREF: {
194 MonoClass *enclosing;
197 if (idx == mono_metadata_token_index (type_token)) {
198 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with self-referencing typeref token %08x.", image->name, type_token));
202 enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
206 if (enclosing->nested_classes_inited && enclosing->ext) {
207 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
208 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
210 if (strcmp (res->name, name) == 0)
214 /* Don't call mono_class_init as we might've been called by it recursively */
215 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
217 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
218 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
219 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
221 if (strcmp (nname, name) == 0) {
222 MonoClass *res = mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, &error);
223 if (!mono_error_ok (&error)) {
224 mono_loader_set_error_from_mono_error (&error);
225 mono_error_cleanup (&error); /*FIXME don't swallow error message.*/
231 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
234 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
237 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
241 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
242 mono_loader_set_error_bad_image (g_strdup_printf ("Image %s with invalid assemblyref token %08x.", image->name, idx));
246 if (!image->references || !image->references [idx - 1])
247 mono_assembly_load_reference (image, idx - 1);
248 g_assert (image->references [idx - 1]);
250 /* If the assembly did not load, register this as a type load exception */
251 if (image->references [idx - 1] == REFERENCE_MISSING){
252 MonoAssemblyName aname;
255 mono_assembly_get_assemblyref (image, idx - 1, &aname);
256 human_name = mono_stringify_assembly_name (&aname);
257 mono_loader_set_error_assembly_load (human_name, image->assembly ? image->assembly->ref_only : FALSE);
263 return mono_class_from_name (image->references [idx - 1]->image, nspace, name);
268 mono_image_memdup (MonoImage *image, void *data, guint size)
270 void *res = mono_image_alloc (image, size);
271 memcpy (res, data, size);
275 /* Copy everything mono_metadata_free_array free. */
277 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
280 a = mono_image_memdup (image, a, sizeof (MonoArrayType));
282 a->sizes = mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
284 a->lobounds = mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
286 a = g_memdup (a, sizeof (MonoArrayType));
288 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
290 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
295 /* Copy everything mono_metadata_free_method_signature free. */
297 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
301 sig = mono_metadata_signature_dup_full (image, sig);
303 sig->ret = mono_metadata_type_dup (image, sig->ret);
304 for (i = 0; i < sig->param_count; ++i)
305 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
311 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
313 MonoAssembly *ta = klass->image->assembly;
316 name = mono_stringify_assembly_name (&ta->aname);
317 g_string_append_printf (str, ", %s", name);
322 mono_type_name_check_byref (MonoType *type, GString *str)
325 g_string_append_c (str, '&');
329 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
330 MonoTypeNameFormat format)
334 switch (type->type) {
335 case MONO_TYPE_ARRAY: {
336 int i, rank = type->data.array->rank;
337 MonoTypeNameFormat nested_format;
339 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
340 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
342 mono_type_get_name_recurse (
343 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
344 g_string_append_c (str, '[');
346 g_string_append_c (str, '*');
347 for (i = 1; i < rank; i++)
348 g_string_append_c (str, ',');
349 g_string_append_c (str, ']');
351 mono_type_name_check_byref (type, str);
353 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
354 _mono_type_get_assembly_name (type->data.array->eklass, str);
357 case MONO_TYPE_SZARRAY: {
358 MonoTypeNameFormat nested_format;
360 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
361 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
363 mono_type_get_name_recurse (
364 &type->data.klass->byval_arg, str, FALSE, nested_format);
365 g_string_append (str, "[]");
367 mono_type_name_check_byref (type, str);
369 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
370 _mono_type_get_assembly_name (type->data.klass, str);
373 case MONO_TYPE_PTR: {
374 MonoTypeNameFormat nested_format;
376 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
377 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
379 mono_type_get_name_recurse (
380 type->data.type, str, FALSE, nested_format);
381 g_string_append_c (str, '*');
383 mono_type_name_check_byref (type, str);
385 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
386 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
391 if (!mono_generic_param_info (type->data.generic_param))
392 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
394 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
396 mono_type_name_check_byref (type, str);
400 klass = mono_class_from_mono_type (type);
401 if (klass->nested_in) {
402 mono_type_get_name_recurse (
403 &klass->nested_in->byval_arg, str, TRUE, format);
404 if (format == MONO_TYPE_NAME_FORMAT_IL)
405 g_string_append_c (str, '.');
407 g_string_append_c (str, '+');
408 } else if (*klass->name_space) {
409 g_string_append (str, klass->name_space);
410 g_string_append_c (str, '.');
412 if (format == MONO_TYPE_NAME_FORMAT_IL) {
413 char *s = strchr (klass->name, '`');
414 int len = s ? s - klass->name : strlen (klass->name);
416 g_string_append_len (str, klass->name, len);
418 g_string_append (str, klass->name);
421 if (klass->generic_class) {
422 MonoGenericClass *gclass = klass->generic_class;
423 MonoGenericInst *inst = gclass->context.class_inst;
424 MonoTypeNameFormat nested_format;
427 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
428 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
430 if (format == MONO_TYPE_NAME_FORMAT_IL)
431 g_string_append_c (str, '<');
433 g_string_append_c (str, '[');
434 for (i = 0; i < inst->type_argc; i++) {
435 MonoType *t = inst->type_argv [i];
438 g_string_append_c (str, ',');
439 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
440 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
441 g_string_append_c (str, '[');
442 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
443 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
444 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
445 g_string_append_c (str, ']');
447 if (format == MONO_TYPE_NAME_FORMAT_IL)
448 g_string_append_c (str, '>');
450 g_string_append_c (str, ']');
451 } else if (klass->generic_container &&
452 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
453 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
456 if (format == MONO_TYPE_NAME_FORMAT_IL)
457 g_string_append_c (str, '<');
459 g_string_append_c (str, '[');
460 for (i = 0; i < klass->generic_container->type_argc; i++) {
462 g_string_append_c (str, ',');
463 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
465 if (format == MONO_TYPE_NAME_FORMAT_IL)
466 g_string_append_c (str, '>');
468 g_string_append_c (str, ']');
471 mono_type_name_check_byref (type, str);
473 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
474 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
475 _mono_type_get_assembly_name (klass, str);
481 * mono_type_get_name_full:
483 * @format: the format for the return string.
486 * Returns: the string representation in a number of formats:
488 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
489 * returned in the formatrequired by System.Reflection, this is the
490 * inverse of mono_reflection_parse_type ().
492 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
493 * be used by the IL assembler.
495 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
497 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
500 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
504 result = g_string_new ("");
506 mono_type_get_name_recurse (type, result, FALSE, format);
508 return g_string_free (result, FALSE);
512 * mono_type_get_full_name:
515 * Returns: the string representation for type as required by System.Reflection.
516 * The inverse of mono_reflection_parse_type ().
519 mono_type_get_full_name (MonoClass *class)
521 return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
525 * mono_type_get_name:
528 * Returns: the string representation for type as it would be represented in IL code.
531 mono_type_get_name (MonoType *type)
533 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
537 * mono_type_get_underlying_type:
540 * Returns: the MonoType for the underlying integer type if @type
541 * is an enum and byref is false, otherwise the type itself.
544 mono_type_get_underlying_type (MonoType *type)
546 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
547 return mono_class_enum_basetype (type->data.klass);
548 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
549 return mono_class_enum_basetype (type->data.generic_class->container_class);
554 * mono_class_is_open_constructed_type:
557 * Returns TRUE if type represents a generics open constructed type.
558 * IOW, not all type parameters required for the instantiation have
559 * been provided or it's a generic type definition.
561 * An open constructed type means it's a non realizable type. Not to
562 * be mixed up with an abstract type - we can't cast or dispatch to
563 * an open type, for example.
566 mono_class_is_open_constructed_type (MonoType *t)
572 case MONO_TYPE_SZARRAY:
573 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
574 case MONO_TYPE_ARRAY:
575 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
577 return mono_class_is_open_constructed_type (t->data.type);
578 case MONO_TYPE_GENERICINST:
579 return t->data.generic_class->context.class_inst->is_open;
580 case MONO_TYPE_CLASS:
581 case MONO_TYPE_VALUETYPE:
582 return t->data.klass->generic_container != NULL;
589 This is a simple function to catch the most common bad instances of generic types.
590 Specially those that might lead to further failures in the runtime.
593 is_valid_generic_argument (MonoType *type)
595 switch (type->type) {
597 //case MONO_TYPE_TYPEDBYREF:
604 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
606 mono_error_init (error);
608 switch (type->type) {
609 case MONO_TYPE_MVAR: {
611 int num = mono_type_get_generic_param_num (type);
612 MonoGenericInst *inst = context->method_inst;
613 if (!inst || !inst->type_argv)
615 if (num >= inst->type_argc) {
616 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
617 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
618 num, info ? info->name : "", inst->type_argc);
622 if (!is_valid_generic_argument (inst->type_argv [num])) {
623 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
624 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
625 num, info ? info->name : "", inst->type_argv [num]->type);
629 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
630 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
631 * ->byref and ->attrs from @type are propagated to the returned type.
633 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
634 nt->byref = type->byref;
635 nt->attrs = type->attrs;
638 case MONO_TYPE_VAR: {
640 int num = mono_type_get_generic_param_num (type);
641 MonoGenericInst *inst = context->class_inst;
644 if (num >= inst->type_argc) {
645 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
646 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
647 num, info ? info->name : "", inst->type_argc);
650 if (!is_valid_generic_argument (inst->type_argv [num])) {
651 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
652 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
653 num, info ? info->name : "", inst->type_argv [num]->type);
656 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
657 nt->byref = type->byref;
658 nt->attrs = type->attrs;
661 case MONO_TYPE_SZARRAY: {
662 MonoClass *eclass = type->data.klass;
663 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
664 if (!inflated || !mono_error_ok (error))
666 nt = mono_metadata_type_dup (image, type);
667 nt->data.klass = mono_class_from_mono_type (inflated);
668 mono_metadata_free_type (inflated);
671 case MONO_TYPE_ARRAY: {
672 MonoClass *eclass = type->data.array->eklass;
673 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
674 if (!inflated || !mono_error_ok (error))
676 nt = mono_metadata_type_dup (image, type);
677 nt->data.array->eklass = mono_class_from_mono_type (inflated);
678 mono_metadata_free_type (inflated);
681 case MONO_TYPE_GENERICINST: {
682 MonoGenericClass *gclass = type->data.generic_class;
683 MonoGenericInst *inst;
685 if (!gclass->context.class_inst->is_open)
688 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
689 if (!mono_error_ok (error))
691 if (inst != gclass->context.class_inst)
692 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
694 if (gclass == type->data.generic_class)
697 nt = mono_metadata_type_dup (image, type);
698 nt->data.generic_class = gclass;
701 case MONO_TYPE_CLASS:
702 case MONO_TYPE_VALUETYPE: {
703 MonoClass *klass = type->data.klass;
704 MonoGenericContainer *container = klass->generic_container;
705 MonoGenericInst *inst;
706 MonoGenericClass *gclass = NULL;
712 /* We can't use context->class_inst directly, since it can have more elements */
713 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
714 if (!mono_error_ok (error))
716 if (inst == container->context.class_inst)
719 gclass = mono_metadata_lookup_generic_class (klass, inst, klass->image->dynamic);
721 nt = mono_metadata_type_dup (image, type);
722 nt->type = MONO_TYPE_GENERICINST;
723 nt->data.generic_class = gclass;
733 mono_generic_class_get_context (MonoGenericClass *gclass)
735 return &gclass->context;
739 mono_class_get_context (MonoClass *class)
741 return class->generic_class ? mono_generic_class_get_context (class->generic_class) : NULL;
745 * mono_class_get_generic_container:
747 * Return the generic container of KLASS which should be a generic type definition.
749 MonoGenericContainer*
750 mono_class_get_generic_container (MonoClass *klass)
752 g_assert (klass->is_generic);
754 return klass->generic_container;
758 * mono_class_get_generic_class:
760 * Return the MonoGenericClass of KLASS, which should be a generic instance.
763 mono_class_get_generic_class (MonoClass *klass)
765 g_assert (klass->is_inflated);
767 return klass->generic_class;
771 * mono_class_inflate_generic_type_with_mempool:
772 * @mempool: a mempool
774 * @context: a generics context
775 * @error: error context
777 * The same as mono_class_inflate_generic_type, but allocates the MonoType
778 * from mempool if it is non-NULL. If it is NULL, the MonoType is
779 * allocated on the heap and is owned by the caller.
780 * The returned type can potentially be the same as TYPE, so it should not be
781 * modified by the caller, and it should be freed using mono_metadata_free_type ().
784 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
786 MonoType *inflated = NULL;
787 mono_error_init (error);
790 inflated = inflate_generic_type (image, type, context, error);
791 if (!mono_error_ok (error))
795 MonoType *shared = mono_metadata_get_shared_type (type);
800 return mono_metadata_type_dup (image, type);
804 mono_stats.inflated_type_count++;
809 * mono_class_inflate_generic_type:
811 * @context: a generics context
813 * If @type is a generic type and @context is not NULL, instantiate it using the
814 * generics context @context.
816 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
817 * on the heap and is owned by the caller. Returns NULL on error.
819 * @deprecated Please use mono_class_inflate_generic_type_checked instead
822 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
826 result = mono_class_inflate_generic_type_checked (type, context, &error);
828 if (!mono_error_ok (&error)) {
829 mono_error_cleanup (&error);
836 * mono_class_inflate_generic_type:
838 * @context: a generics context
839 * @error: error context to use
841 * If @type is a generic type and @context is not NULL, instantiate it using the
842 * generics context @context.
844 * Returns: the instantiated type or a copy of @type. The returned MonoType is allocated
845 * on the heap and is owned by the caller.
848 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
850 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
854 * mono_class_inflate_generic_type_no_copy:
856 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
860 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
862 MonoType *inflated = NULL;
864 mono_error_init (error);
866 inflated = inflate_generic_type (image, type, context, error);
867 if (!mono_error_ok (error))
874 mono_stats.inflated_type_count++;
879 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
884 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
885 if (!mono_error_ok (error))
888 res = mono_class_from_mono_type (inflated);
889 mono_metadata_free_type (inflated);
894 * mono_class_inflate_generic_class:
896 * Inflate the class GKLASS with CONTEXT.
899 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
904 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
905 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
912 static MonoGenericContext
913 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
915 MonoGenericInst *class_inst = NULL;
916 MonoGenericInst *method_inst = NULL;
917 MonoGenericContext res = { NULL, NULL };
919 mono_error_init (error);
921 if (context->class_inst) {
922 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
923 if (!mono_error_ok (error))
927 if (context->method_inst) {
928 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
929 if (!mono_error_ok (error))
933 res.class_inst = class_inst;
934 res.method_inst = method_inst;
940 * mono_class_inflate_generic_method:
941 * @method: a generic method
942 * @context: a generics context
944 * Instantiate the generic method @method using the generics context @context.
946 * Returns: the new instantiated method
949 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
951 return mono_class_inflate_generic_method_full (method, NULL, context);
955 * mono_class_inflate_generic_method_full:
957 * Instantiate method @method with the generic context @context.
958 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
959 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
962 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
965 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
966 if (!mono_error_ok (&error))
967 /*FIXME do proper error handling - on this case, kill this function. */
968 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
974 * mono_class_inflate_generic_method_full_checked:
975 * Same as mono_class_inflate_generic_method_full but return failure using @error.
978 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
981 MonoMethodInflated *iresult, *cached;
982 MonoMethodSignature *sig;
983 MonoGenericContext tmp_context;
984 gboolean is_mb_open = FALSE;
986 mono_error_init (error);
988 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
989 while (method->is_inflated) {
990 MonoGenericContext *method_context = mono_method_get_context (method);
991 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
993 tmp_context = inflate_generic_context (method_context, context, error);
994 if (!mono_error_ok (error))
996 context = &tmp_context;
998 if (mono_metadata_generic_context_equal (method_context, context))
1001 method = imethod->declaring;
1005 * A method only needs to be inflated if the context has argument for which it is
1008 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1009 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1012 if (!((method->is_generic && context->method_inst) ||
1013 (method->klass->generic_container && context->class_inst)))
1017 * The reason for this hack is to fix the behavior of inflating generic methods that come from a MethodBuilder.
1018 * What happens is that instantiating a generic MethodBuilder with its own arguments should create a diferent object.
1019 * This is opposite to the way non-SRE MethodInfos behave.
1021 * This happens, for example, when we want to emit a recursive generic method. Given the following C# code:
1023 * void Example<T> () {
1027 * In Example, the method token must be encoded as: "void Example<!!0>()"
1029 * The reference to the first generic argument, "!!0", must be explicit otherwise it won't be inflated
1030 * properly. To get that we need to inflate the MethodBuilder with its own arguments.
1032 * On the other hand, inflating a non-SRE generic method with its own arguments should
1033 * return itself. For example:
1035 * MethodInfo m = ... //m is a generic method definition
1036 * MethodInfo res = m.MakeGenericMethod (m.GetGenericArguments ());
1039 * To allow such scenarios we must allow inflation of MethodBuilder to happen in a diferent way than
1040 * what happens with regular methods.
1042 * There is one last touch to this madness, once a TypeBuilder is finished, IOW CreateType() is called,
1043 * everything should behave like a regular type or method.
1046 is_mb_open = method->is_generic &&
1047 method->klass->image->dynamic && !method->klass->wastypebuilder && /* that is a MethodBuilder from an unfinished TypeBuilder */
1048 context->method_inst == mono_method_get_generic_container (method)->context.method_inst; /* and it's been instantiated with its own arguments. */
1050 iresult = g_new0 (MonoMethodInflated, 1);
1051 iresult->context = *context;
1052 iresult->declaring = method;
1053 iresult->method.method.is_mb_open = is_mb_open;
1055 if (!context->method_inst && method->is_generic)
1056 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1058 if (!context->class_inst) {
1059 g_assert (!iresult->declaring->klass->generic_class);
1060 if (iresult->declaring->klass->generic_container)
1061 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1062 else if (iresult->declaring->klass->generic_class)
1063 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1066 mono_loader_lock ();
1067 cached = mono_method_inflated_lookup (iresult, FALSE);
1069 mono_loader_unlock ();
1071 return (MonoMethod*)cached;
1074 mono_stats.inflated_method_count++;
1076 inflated_methods_size += sizeof (MonoMethodInflated);
1078 sig = mono_method_signature (method);
1080 char *name = mono_type_get_full_name (method->klass);
1081 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1087 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1089 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1092 result = (MonoMethod *) iresult;
1093 result->is_inflated = TRUE;
1094 result->is_generic = FALSE;
1095 result->sre_method = FALSE;
1096 result->signature = NULL;
1097 result->is_mb_open = is_mb_open;
1099 if (!context->method_inst) {
1100 /* Set the generic_container of the result to the generic_container of method */
1101 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1103 if (generic_container) {
1104 result->is_generic = 1;
1105 mono_method_set_generic_container (result, generic_container);
1109 if (!klass_hint || !klass_hint->generic_class ||
1110 klass_hint->generic_class->container_class != method->klass ||
1111 klass_hint->generic_class->context.class_inst != context->class_inst)
1114 if (method->klass->generic_container)
1115 result->klass = klass_hint;
1117 if (!result->klass) {
1118 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1119 if (!mono_error_ok (error))
1122 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1124 mono_metadata_free_type (inflated);
1128 * FIXME: This should hold, but it doesn't:
1130 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1131 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1132 * g_assert (result->is_generic);
1135 * Fixing this here causes other things to break, hence a very
1136 * ugly hack in mini-trampolines.c - see
1137 * is_generic_method_definition().
1140 mono_method_inflated_lookup (iresult, TRUE);
1141 mono_loader_unlock ();
1145 mono_loader_unlock ();
1151 * mono_get_inflated_method:
1153 * Obsolete. We keep it around since it's mentioned in the public API.
1156 mono_get_inflated_method (MonoMethod *method)
1162 * mono_method_get_context_general:
1164 * @uninflated: handle uninflated methods?
1166 * Returns the generic context of a method or NULL if it doesn't have
1167 * one. For an inflated method that's the context stored in the
1168 * method. Otherwise it's in the method's generic container or in the
1169 * generic container of the method's class.
1172 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1174 if (method->is_inflated) {
1175 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1176 return &imethod->context;
1180 if (method->is_generic)
1181 return &(mono_method_get_generic_container (method)->context);
1182 if (method->klass->generic_container)
1183 return &method->klass->generic_container->context;
1188 * mono_method_get_context:
1191 * Returns the generic context for method if it's inflated, otherwise
1195 mono_method_get_context (MonoMethod *method)
1197 return mono_method_get_context_general (method, FALSE);
1201 * mono_method_get_generic_container:
1203 * Returns the generic container of METHOD, which should be a generic method definition.
1204 * Returns NULL if METHOD is not a generic method definition.
1205 * LOCKING: Acquires the loader lock.
1207 MonoGenericContainer*
1208 mono_method_get_generic_container (MonoMethod *method)
1210 MonoGenericContainer *container;
1212 if (!method->is_generic)
1215 container = mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1216 g_assert (container);
1222 * mono_method_set_generic_container:
1224 * Sets the generic container of METHOD to CONTAINER.
1225 * LOCKING: Acquires the loader lock.
1228 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1230 g_assert (method->is_generic);
1232 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1236 * mono_class_find_enum_basetype:
1237 * @class: The enum class
1239 * Determine the basetype of an enum by iterating through its fields. We do this
1240 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1243 mono_class_find_enum_basetype (MonoClass *class)
1245 MonoGenericContainer *container = NULL;
1246 MonoImage *m = class->image;
1247 const int top = class->field.count;
1250 g_assert (class->enumtype);
1252 if (class->generic_container)
1253 container = class->generic_container;
1254 else if (class->generic_class) {
1255 MonoClass *gklass = class->generic_class->container_class;
1257 container = gklass->generic_container;
1258 g_assert (container);
1262 * Fetch all the field information.
1264 for (i = 0; i < top; i++){
1266 guint32 cols [MONO_FIELD_SIZE];
1267 int idx = class->field.first + i;
1270 /* class->field.first and idx points into the fieldptr table */
1271 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1273 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1276 if (!mono_verifier_verify_field_signature (class->image, cols [MONO_FIELD_SIGNATURE], NULL))
1279 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1280 mono_metadata_decode_value (sig, &sig);
1281 /* FIELD signature == 0x06 */
1285 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1288 if (class->generic_class) {
1289 //FIXME do we leak here?
1290 ftype = mono_class_inflate_generic_type (ftype, mono_class_get_context (class));
1291 ftype->attrs = cols [MONO_FIELD_FLAGS];
1301 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1304 mono_type_has_exceptions (MonoType *type)
1306 switch (type->type) {
1307 case MONO_TYPE_CLASS:
1308 case MONO_TYPE_VALUETYPE:
1309 case MONO_TYPE_SZARRAY:
1310 return type->data.klass->exception_type;
1311 case MONO_TYPE_ARRAY:
1312 return type->data.array->eklass->exception_type;
1313 case MONO_TYPE_GENERICINST:
1314 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1322 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1326 mono_class_alloc (MonoClass *class, int size)
1328 if (class->generic_class)
1329 return mono_image_set_alloc (class->generic_class->owner, size);
1331 return mono_image_alloc (class->image, size);
1335 mono_class_alloc0 (MonoClass *class, int size)
1339 res = mono_class_alloc (class, size);
1340 memset (res, 0, size);
1344 #define mono_class_new0(class,struct_type, n_structs) \
1345 ((struct_type *) mono_class_alloc0 ((class), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1348 * mono_class_setup_basic_field_info:
1349 * @class: The class to initialize
1351 * Initializes the class->fields.
1352 * LOCKING: Assumes the loader lock is held.
1355 mono_class_setup_basic_field_info (MonoClass *class)
1357 MonoClassField *field;
1365 gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1366 image = class->image;
1367 top = class->field.count;
1369 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1371 * This happens when a generic instance of an unfinished generic typebuilder
1372 * is used as an element type for creating an array type. We can't initialize
1373 * the fields of this class using the fields of gklass, since gklass is not
1374 * finished yet, fields could be added to it later.
1380 mono_class_setup_basic_field_info (gtd);
1382 top = gtd->field.count;
1383 class->field.first = gtd->field.first;
1384 class->field.count = gtd->field.count;
1387 class->fields = mono_class_alloc0 (class, sizeof (MonoClassField) * top);
1390 * Fetch all the field information.
1392 for (i = 0; i < top; i++){
1393 field = &class->fields [i];
1394 field->parent = class;
1397 field->name = mono_field_get_name (>d->fields [i]);
1399 int idx = class->field.first + i;
1400 /* class->field.first and idx points into the fieldptr table */
1401 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1402 /* The name is needed for fieldrefs */
1403 field->name = mono_metadata_string_heap (image, name_idx);
1409 * mono_class_setup_fields:
1410 * @class: The class to initialize
1412 * Initializes the class->fields.
1413 * LOCKING: Assumes the loader lock is held.
1416 mono_class_setup_fields (MonoClass *class)
1419 MonoImage *m = class->image;
1421 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1422 int i, blittable = TRUE;
1423 guint32 real_size = 0;
1424 guint32 packing_size = 0;
1425 gboolean explicit_size;
1426 MonoClassField *field;
1427 MonoGenericContainer *container = NULL;
1428 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
1431 * FIXME: We have a race condition here. It's possible that this function returns
1432 * to its caller with `instance_size` set to `0` instead of the actual size. This
1433 * is not a problem when the function is called recursively on the same class,
1434 * because the size will be initialized by the outer invocation. What follows is a
1435 * description of how it can occur in other cases, too. There it is a problem,
1436 * because it can lead to the GC being asked to allocate an object of size `0`,
1437 * which SGen chokes on. The race condition is triggered infrequently by
1438 * `tests/sgen-suspend.cs`.
1440 * This function is called for a class whenever one of its subclasses is inited.
1441 * For example, it's called for every subclass of Object. What it does is this:
1443 * if (class->setup_fields_called)
1446 * class->instance_size = 0;
1448 * class->setup_fields_called = 1;
1449 * ... critical point
1450 * class->instance_size = actual_instance_size;
1452 * The last two steps are sometimes reversed, but that only changes the way in which
1453 * the race condition works.
1455 * Assume thread A goes through this function and makes it to the critical point.
1456 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1457 * immediately, but `instance_size` is incorrect.
1459 * The other case looks like this:
1461 * if (class->setup_fields_called)
1463 * ... critical point X
1464 * class->instance_size = 0;
1465 * ... critical point Y
1466 * class->instance_size = actual_instance_size;
1468 * class->setup_fields_called = 1;
1470 * Assume thread A goes through the function and makes it to critical point X. Now
1471 * thread B runs through the whole of the function, returning, assuming
1472 * `instance_size` is set. At that point thread A gets to run and makes it to
1473 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1476 if (class->setup_fields_called)
1479 if (class->generic_class && class->generic_class->container_class->image->dynamic && !class->generic_class->container_class->wastypebuilder) {
1481 * This happens when a generic instance of an unfinished generic typebuilder
1482 * is used as an element type for creating an array type. We can't initialize
1483 * the fields of this class using the fields of gklass, since gklass is not
1484 * finished yet, fields could be added to it later.
1489 mono_class_setup_basic_field_info (class);
1490 top = class->field.count;
1493 mono_class_setup_fields (gtd);
1494 if (gtd->exception_type) {
1495 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1500 class->instance_size = 0;
1502 class->sizes.class_size = 0;
1504 if (class->parent) {
1505 /* For generic instances, class->parent might not have been initialized */
1506 mono_class_init (class->parent);
1507 if (!class->parent->size_inited) {
1508 mono_class_setup_fields (class->parent);
1509 if (class->parent->exception_type) {
1510 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1514 class->instance_size += class->parent->instance_size;
1515 class->min_align = class->parent->min_align;
1516 /* we use |= since it may have been set already */
1517 class->has_references |= class->parent->has_references;
1518 blittable = class->parent->blittable;
1520 class->instance_size = sizeof (MonoObject);
1521 class->min_align = 1;
1524 /* We can't really enable 16 bytes alignment until the GC supports it.
1525 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1526 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1527 Bug #506144 is an example of this issue.
1529 if (class->simd_type)
1530 class->min_align = 16;
1532 /* Get the real size */
1533 explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
1535 if (explicit_size) {
1536 if ((packing_size & 0xfffffff0) != 0) {
1537 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 16", class->name, packing_size);
1538 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1541 class->packing_size = packing_size;
1542 real_size += class->instance_size;
1546 if (explicit_size && real_size) {
1547 class->instance_size = MAX (real_size, class->instance_size);
1549 class->blittable = blittable;
1550 mono_memory_barrier ();
1551 class->size_inited = 1;
1552 class->fields_inited = 1;
1553 class->setup_fields_called = 1;
1557 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
1560 /* Prevent infinite loops if the class references itself */
1561 class->setup_fields_called = 1;
1563 if (class->generic_container) {
1564 container = class->generic_container;
1566 container = gtd->generic_container;
1567 g_assert (container);
1571 * Fetch all the field information.
1573 for (i = 0; i < top; i++){
1574 int idx = class->field.first + i;
1575 field = &class->fields [i];
1577 field->parent = class;
1580 mono_field_resolve_type (field, &error);
1581 if (!mono_error_ok (&error)) {
1582 /*mono_field_resolve_type already failed class*/
1583 mono_error_cleanup (&error);
1587 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(class), field->name);
1588 g_assert (field->type);
1591 if (mono_field_is_deleted (field))
1594 MonoClassField *gfield = >d->fields [i];
1595 field->offset = gfield->offset;
1597 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1599 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1600 field->offset = offset;
1602 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1603 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1606 if (field->offset < -1) { /*-1 is used to encode special static fields */
1607 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1613 /* Only do these checks if we still think this type is blittable */
1614 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1615 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1618 MonoClass *field_class = mono_class_from_mono_type (field->type);
1620 mono_class_setup_fields (field_class);
1621 if (field_class->exception_type) {
1622 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1626 if (!field_class || !field_class->blittable)
1631 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1632 class->cast_class = class->element_class = mono_class_from_mono_type (field->type);
1633 blittable = class->element_class->blittable;
1636 if (mono_type_has_exceptions (field->type)) {
1637 char *class_name = mono_type_get_full_name (class);
1638 char *type_name = mono_type_full_name (field->type);
1640 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1641 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1642 g_free (class_name);
1646 /* The def_value of fields is compute lazily during vtable creation */
1649 if (class == mono_defaults.string_class)
1652 class->blittable = blittable;
1654 if (class->enumtype && !mono_class_enum_basetype (class)) {
1655 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1658 if (explicit_size && real_size) {
1659 class->instance_size = MAX (real_size, class->instance_size);
1662 if (class->exception_type)
1664 mono_class_layout_fields (class);
1666 /*valuetypes can't be neither bigger than 1Mb or empty. */
1667 if (class->valuetype && (class->instance_size <= 0 || class->instance_size > (0x100000 + sizeof (MonoObject))))
1668 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1670 mono_memory_barrier ();
1671 class->fields_inited = 1;
1675 * mono_class_setup_fields_locking:
1676 * @class: The class to initialize
1678 * Initializes the class->fields array of fields.
1679 * Aquires the loader lock.
1682 mono_class_setup_fields_locking (MonoClass *class)
1684 /* This can be checked without locks */
1685 if (class->fields_inited)
1687 mono_loader_lock ();
1688 mono_class_setup_fields (class);
1689 mono_loader_unlock ();
1693 * mono_class_has_references:
1695 * Returns whenever @klass->has_references is set, initializing it if needed.
1696 * Aquires the loader lock.
1699 mono_class_has_references (MonoClass *klass)
1701 if (klass->init_pending) {
1702 /* Be conservative */
1705 mono_class_init (klass);
1707 return klass->has_references;
1712 * mono_type_get_basic_type_from_generic:
1715 * Returns a closed type corresponding to the possibly open type
1719 mono_type_get_basic_type_from_generic (MonoType *type)
1721 /* When we do generic sharing we let type variables stand for reference types. */
1722 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR))
1723 return &mono_defaults.object_class->byval_arg;
1728 * mono_class_layout_fields:
1731 * Compute the placement of fields inside an object or struct, according to
1732 * the layout rules and set the following fields in @class:
1733 * - has_references (if the class contains instance references firled or structs that contain references)
1734 * - has_static_refs (same, but for static fields)
1735 * - instance_size (size of the object in memory)
1736 * - class_size (size needed for the static fields)
1737 * - size_inited (flag set when the instance_size is set)
1739 * LOCKING: this is supposed to be called with the loader lock held.
1742 mono_class_layout_fields (MonoClass *class)
1745 const int top = class->field.count;
1746 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1747 guint32 pass, passes, real_size;
1748 gboolean gc_aware_layout = FALSE;
1749 MonoClassField *field;
1752 * When we do generic sharing we need to have layout
1753 * information for open generic classes (either with a generic
1754 * context containing type variables or with a generic
1755 * container), so we don't return in that case anymore.
1759 * Enable GC aware auto layout: in this mode, reference
1760 * fields are grouped together inside objects, increasing collector
1762 * Requires that all classes whose layout is known to native code be annotated
1763 * with [StructLayout (LayoutKind.Sequential)]
1764 * Value types have gc_aware_layout disabled by default, as per
1765 * what the default is for other runtimes.
1767 /* corlib is missing [StructLayout] directives in many places */
1768 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1769 if (!class->valuetype)
1770 gc_aware_layout = TRUE;
1773 /* Compute klass->has_references */
1775 * Process non-static fields first, since static fields might recursively
1776 * refer to the class itself.
1778 for (i = 0; i < top; i++) {
1781 field = &class->fields [i];
1783 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1784 ftype = mono_type_get_underlying_type (field->type);
1785 ftype = mono_type_get_basic_type_from_generic (ftype);
1786 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1787 class->has_references = TRUE;
1791 for (i = 0; i < top; i++) {
1794 field = &class->fields [i];
1796 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1797 ftype = mono_type_get_underlying_type (field->type);
1798 ftype = mono_type_get_basic_type_from_generic (ftype);
1799 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1800 class->has_static_refs = TRUE;
1804 for (i = 0; i < top; i++) {
1807 field = &class->fields [i];
1809 ftype = mono_type_get_underlying_type (field->type);
1810 ftype = mono_type_get_basic_type_from_generic (ftype);
1811 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1812 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1813 class->has_static_refs = TRUE;
1815 class->has_references = TRUE;
1820 * Compute field layout and total size (not considering static fields)
1824 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1825 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1827 if (gc_aware_layout)
1832 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1835 if (class->parent) {
1836 mono_class_setup_fields (class->parent);
1837 if (class->parent->exception_type) {
1838 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1841 real_size = class->parent->instance_size;
1843 real_size = sizeof (MonoObject);
1846 for (pass = 0; pass < passes; ++pass) {
1847 for (i = 0; i < top; i++){
1852 field = &class->fields [i];
1854 if (mono_field_is_deleted (field))
1856 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1859 ftype = mono_type_get_underlying_type (field->type);
1860 ftype = mono_type_get_basic_type_from_generic (ftype);
1861 if (gc_aware_layout) {
1862 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1871 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1872 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1873 /* This field is a hack inserted by MCS to empty structures */
1877 size = mono_type_size (field->type, &align);
1879 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1880 align = class->packing_size ? MIN (class->packing_size, align): align;
1881 /* if the field has managed references, we need to force-align it
1884 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1885 align = MAX (align, sizeof (gpointer));
1887 class->min_align = MAX (align, class->min_align);
1888 field->offset = real_size;
1890 field->offset += align - 1;
1891 field->offset &= ~(align - 1);
1893 /*TypeBuilders produce all sort of weird things*/
1894 g_assert (class->image->dynamic || field->offset > 0);
1895 real_size = field->offset + size;
1898 class->instance_size = MAX (real_size, class->instance_size);
1900 if (class->instance_size & (class->min_align - 1)) {
1901 class->instance_size += class->min_align - 1;
1902 class->instance_size &= ~(class->min_align - 1);
1906 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1908 for (i = 0; i < top; i++) {
1913 field = &class->fields [i];
1916 * There must be info about all the fields in a type if it
1917 * uses explicit layout.
1920 if (mono_field_is_deleted (field))
1922 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1925 size = mono_type_size (field->type, &align);
1926 align = class->packing_size ? MIN (class->packing_size, align): align;
1927 class->min_align = MAX (align, class->min_align);
1930 * When we get here, field->offset is already set by the
1931 * loader (for either runtime fields or fields loaded from metadata).
1932 * The offset is from the start of the object: this works for both
1933 * classes and valuetypes.
1935 field->offset += sizeof (MonoObject);
1936 ftype = mono_type_get_underlying_type (field->type);
1937 ftype = mono_type_get_basic_type_from_generic (ftype);
1938 if (MONO_TYPE_IS_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1939 if (field->offset % sizeof (gpointer)) {
1940 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1947 real_size = MAX (real_size, size + field->offset);
1949 class->instance_size = MAX (real_size, class->instance_size);
1950 if (class->instance_size & (class->min_align - 1)) {
1951 class->instance_size += class->min_align - 1;
1952 class->instance_size &= ~(class->min_align - 1);
1957 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1959 * For small structs, set min_align to at least the struct size to improve
1960 * performance, and since the JIT memset/memcpy code assumes this and generates
1961 * unaligned accesses otherwise. See #78990 for a testcase.
1963 if (class->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
1964 class->min_align = MAX (class->min_align, class->instance_size - sizeof (MonoObject));
1967 mono_memory_barrier ();
1968 class->size_inited = 1;
1971 * Compute static field layout and size
1973 for (i = 0; i < top; i++){
1977 field = &class->fields [i];
1979 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1981 if (mono_field_is_deleted (field))
1984 if (mono_type_has_exceptions (field->type)) {
1985 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
1989 size = mono_type_size (field->type, &align);
1990 field->offset = class->sizes.class_size;
1991 /*align is always non-zero here*/
1992 field->offset += align - 1;
1993 field->offset &= ~(align - 1);
1994 class->sizes.class_size = field->offset + size;
1999 create_array_method (MonoClass *class, const char *name, MonoMethodSignature *sig)
2003 method = (MonoMethod *) mono_image_alloc0 (class->image, sizeof (MonoMethodPInvoke));
2004 method->klass = class;
2005 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2006 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2007 method->signature = sig;
2008 method->name = name;
2011 if (name [0] == '.') {
2012 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2014 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2020 * mono_class_setup_methods:
2023 * Initializes the 'methods' array in the klass.
2024 * Calling this method should be avoided if possible since it allocates a lot
2025 * of long-living MonoMethod structures.
2026 * Methods belonging to an interface are assigned a sequential slot starting
2029 * On failure this function sets class->exception_type
2032 mono_class_setup_methods (MonoClass *class)
2035 MonoMethod **methods;
2040 mono_loader_lock ();
2042 if (class->methods) {
2043 mono_loader_unlock ();
2047 if (class->generic_class) {
2049 MonoClass *gklass = class->generic_class->container_class;
2051 mono_class_init (gklass);
2052 if (!gklass->exception_type)
2053 mono_class_setup_methods (gklass);
2054 if (gklass->exception_type) {
2055 /*FIXME make exception_data less opaque so it's possible to dup it here*/
2056 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2057 mono_loader_unlock ();
2061 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2062 class->method.count = gklass->method.count;
2063 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * (class->method.count + 1));
2065 for (i = 0; i < class->method.count; i++) {
2066 methods [i] = mono_class_inflate_generic_method_full_checked (
2067 gklass->methods [i], class, mono_class_get_context (class), &error);
2068 if (!mono_error_ok (&error)) {
2069 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2070 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)));
2073 mono_error_cleanup (&error);
2074 mono_loader_unlock ();
2078 } else if (class->rank) {
2080 MonoMethod *amethod;
2081 MonoMethodSignature *sig;
2082 int count_generic = 0, first_generic = 0;
2085 class->method.count = 3 + (class->rank > 1? 2: 1);
2087 mono_class_setup_interfaces (class, &error);
2088 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2090 if (class->interface_count) {
2091 count_generic = generic_array_methods (class);
2092 first_generic = class->method.count;
2093 class->method.count += class->interface_count * count_generic;
2096 methods = mono_class_alloc0 (class, sizeof (MonoMethod*) * class->method.count);
2098 sig = mono_metadata_signature_alloc (class->image, class->rank);
2099 sig->ret = &mono_defaults.void_class->byval_arg;
2100 sig->pinvoke = TRUE;
2101 sig->hasthis = TRUE;
2102 for (i = 0; i < class->rank; ++i)
2103 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2105 amethod = create_array_method (class, ".ctor", sig);
2106 methods [method_num++] = amethod;
2107 if (class->rank > 1) {
2108 sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2109 sig->ret = &mono_defaults.void_class->byval_arg;
2110 sig->pinvoke = TRUE;
2111 sig->hasthis = TRUE;
2112 for (i = 0; i < class->rank * 2; ++i)
2113 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2115 amethod = create_array_method (class, ".ctor", sig);
2116 methods [method_num++] = amethod;
2118 /* element Get (idx11, [idx2, ...]) */
2119 sig = mono_metadata_signature_alloc (class->image, class->rank);
2120 sig->ret = &class->element_class->byval_arg;
2121 sig->pinvoke = TRUE;
2122 sig->hasthis = TRUE;
2123 for (i = 0; i < class->rank; ++i)
2124 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2125 amethod = create_array_method (class, "Get", sig);
2126 methods [method_num++] = amethod;
2127 /* element& Address (idx11, [idx2, ...]) */
2128 sig = mono_metadata_signature_alloc (class->image, class->rank);
2129 sig->ret = &class->element_class->this_arg;
2130 sig->pinvoke = TRUE;
2131 sig->hasthis = TRUE;
2132 for (i = 0; i < class->rank; ++i)
2133 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2134 amethod = create_array_method (class, "Address", sig);
2135 methods [method_num++] = amethod;
2136 /* void Set (idx11, [idx2, ...], element) */
2137 sig = mono_metadata_signature_alloc (class->image, class->rank + 1);
2138 sig->ret = &mono_defaults.void_class->byval_arg;
2139 sig->pinvoke = TRUE;
2140 sig->hasthis = TRUE;
2141 for (i = 0; i < class->rank; ++i)
2142 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2143 sig->params [i] = &class->element_class->byval_arg;
2144 amethod = create_array_method (class, "Set", sig);
2145 methods [method_num++] = amethod;
2147 for (i = 0; i < class->interface_count; i++)
2148 setup_generic_array_ifaces (class, class->interfaces [i], methods, first_generic + i * count_generic);
2150 methods = mono_class_alloc (class, sizeof (MonoMethod*) * class->method.count);
2151 for (i = 0; i < class->method.count; ++i) {
2152 int idx = mono_metadata_translate_token_index (class->image, MONO_TABLE_METHOD, class->method.first + i + 1);
2153 methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | idx, class);
2157 if (MONO_CLASS_IS_INTERFACE (class)) {
2159 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2160 for (i = 0; i < class->method.count; ++i) {
2161 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2162 methods [i]->slot = slot++;
2166 /* Needed because of the double-checking locking pattern */
2167 mono_memory_barrier ();
2169 class->methods = methods;
2171 mono_loader_unlock ();
2175 * mono_class_get_method_by_index:
2177 * Returns class->methods [index], initializing class->methods if neccesary.
2179 * LOCKING: Acquires the loader lock.
2182 mono_class_get_method_by_index (MonoClass *class, int index)
2184 /* Avoid calling setup_methods () if possible */
2185 if (class->generic_class && !class->methods) {
2186 MonoClass *gklass = class->generic_class->container_class;
2189 m = mono_class_inflate_generic_method_full (
2190 gklass->methods [index], class, mono_class_get_context (class));
2192 * If setup_methods () is called later for this class, no duplicates are created,
2193 * since inflate_generic_method guarantees that only one instance of a method
2194 * is created for each context.
2197 mono_class_setup_methods (class);
2198 g_assert (m == class->methods [index]);
2202 mono_class_setup_methods (class);
2203 if (class->exception_type) /*FIXME do proper error handling*/
2205 g_assert (index >= 0 && index < class->method.count);
2206 return class->methods [index];
2211 * mono_class_get_inflated_method:
2213 * Given an inflated class CLASS and a method METHOD which should be a method of
2214 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2217 mono_class_get_inflated_method (MonoClass *class, MonoMethod *method)
2219 MonoClass *gklass = class->generic_class->container_class;
2222 g_assert (method->klass == gklass);
2224 mono_class_setup_methods (gklass);
2225 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2227 for (i = 0; i < gklass->method.count; ++i) {
2228 if (gklass->methods [i] == method) {
2230 return class->methods [i];
2232 return mono_class_inflate_generic_method_full (gklass->methods [i], class, mono_class_get_context (class));
2240 * mono_class_get_vtable_entry:
2242 * Returns class->vtable [offset], computing it if neccesary. Returns NULL on failure.
2243 * LOCKING: Acquires the loader lock.
2246 mono_class_get_vtable_entry (MonoClass *class, int offset)
2250 if (class->rank == 1) {
2252 * szarrays do not overwrite any methods of Array, so we can avoid
2253 * initializing their vtables in some cases.
2255 mono_class_setup_vtable (class->parent);
2256 if (offset < class->parent->vtable_size)
2257 return class->parent->vtable [offset];
2260 if (class->generic_class) {
2261 MonoClass *gklass = class->generic_class->container_class;
2262 mono_class_setup_vtable (gklass);
2263 m = gklass->vtable [offset];
2265 m = mono_class_inflate_generic_method_full (m, class, mono_class_get_context (class));
2267 mono_class_setup_vtable (class);
2268 if (class->exception_type)
2270 m = class->vtable [offset];
2277 * mono_class_get_vtable_size:
2279 * Return the vtable size for KLASS.
2282 mono_class_get_vtable_size (MonoClass *klass)
2284 mono_class_setup_vtable (klass);
2286 return klass->vtable_size;
2289 /*This method can fail the class.*/
2291 mono_class_setup_properties (MonoClass *class)
2293 guint startm, endm, i, j;
2294 guint32 cols [MONO_PROPERTY_SIZE];
2295 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2296 MonoProperty *properties;
2299 if (class->ext && class->ext->properties)
2302 mono_loader_lock ();
2304 if (class->ext && class->ext->properties) {
2305 mono_loader_unlock ();
2309 mono_class_alloc_ext (class);
2311 if (class->generic_class) {
2312 MonoClass *gklass = class->generic_class->container_class;
2314 mono_class_init (gklass);
2315 mono_class_setup_properties (gklass);
2316 if (gklass->exception_type) {
2317 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2318 mono_loader_unlock ();
2322 class->ext->property = gklass->ext->property;
2324 properties = mono_class_new0 (class, MonoProperty, class->ext->property.count + 1);
2326 for (i = 0; i < class->ext->property.count; i++) {
2327 MonoProperty *prop = &properties [i];
2329 *prop = gklass->ext->properties [i];
2332 prop->get = mono_class_inflate_generic_method_full (
2333 prop->get, class, mono_class_get_context (class));
2335 prop->set = mono_class_inflate_generic_method_full (
2336 prop->set, class, mono_class_get_context (class));
2338 prop->parent = class;
2341 int first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2342 int count = last - first;
2345 mono_class_setup_methods (class);
2346 if (class->exception_type) {
2347 mono_loader_unlock ();
2352 class->ext->property.first = first;
2353 class->ext->property.count = count;
2354 properties = mono_class_alloc0 (class, sizeof (MonoProperty) * count);
2355 for (i = first; i < last; ++i) {
2356 mono_metadata_decode_table_row (class->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2357 properties [i - first].parent = class;
2358 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2359 properties [i - first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
2361 startm = mono_metadata_methods_from_property (class->image, i, &endm);
2362 for (j = startm; j < endm; ++j) {
2365 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2367 if (class->image->uncompressed_metadata)
2368 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2369 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2371 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2373 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2374 case METHOD_SEMANTIC_SETTER:
2375 properties [i - first].set = method;
2377 case METHOD_SEMANTIC_GETTER:
2378 properties [i - first].get = method;
2386 /*Flush any pending writes as we do double checked locking on class->properties */
2387 mono_memory_barrier ();
2389 /* Leave this assignment as the last op in the function */
2390 class->ext->properties = properties;
2392 mono_loader_unlock ();
2396 inflate_method_listz (MonoMethod **methods, MonoClass *class, MonoGenericContext *context)
2398 MonoMethod **om, **retval;
2401 for (om = methods, count = 0; *om; ++om, ++count)
2404 retval = g_new0 (MonoMethod*, count + 1);
2406 for (om = methods, count = 0; *om; ++om, ++count)
2407 retval [count] = mono_class_inflate_generic_method_full (*om, class, context);
2412 /*This method can fail the class.*/
2414 mono_class_setup_events (MonoClass *class)
2417 guint startm, endm, i, j;
2418 guint32 cols [MONO_EVENT_SIZE];
2419 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
2423 if (class->ext && class->ext->events)
2426 mono_loader_lock ();
2428 if (class->ext && class->ext->events) {
2429 mono_loader_unlock ();
2433 mono_class_alloc_ext (class);
2435 if (class->generic_class) {
2436 MonoClass *gklass = class->generic_class->container_class;
2437 MonoGenericContext *context;
2439 mono_class_setup_events (gklass);
2440 if (gklass->exception_type) {
2441 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2442 mono_loader_unlock ();
2446 class->ext->event = gklass->ext->event;
2447 class->ext->events = mono_class_new0 (class, MonoEvent, class->ext->event.count);
2449 if (class->ext->event.count)
2450 context = mono_class_get_context (class);
2452 for (i = 0; i < class->ext->event.count; i++) {
2453 MonoEvent *event = &class->ext->events [i];
2454 MonoEvent *gevent = &gklass->ext->events [i];
2456 event->parent = class;
2457 event->name = gevent->name;
2458 event->add = gevent->add ? mono_class_inflate_generic_method_full (gevent->add, class, context) : NULL;
2459 event->remove = gevent->remove ? mono_class_inflate_generic_method_full (gevent->remove, class, context) : NULL;
2460 event->raise = gevent->raise ? mono_class_inflate_generic_method_full (gevent->raise, class, context) : NULL;
2461 #ifndef MONO_SMALL_CONFIG
2462 event->other = gevent->other ? inflate_method_listz (gevent->other, class, context) : NULL;
2464 event->attrs = gevent->attrs;
2467 mono_loader_unlock ();
2471 first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
2472 count = last - first;
2475 mono_class_setup_methods (class);
2476 if (class->exception_type) {
2477 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2478 mono_loader_unlock ();
2482 class->ext->event.first = first;
2483 class->ext->event.count = count;
2484 events = mono_class_alloc0 (class, sizeof (MonoEvent) * class->ext->event.count);
2485 for (i = first; i < last; ++i) {
2486 MonoEvent *event = &events [i - first];
2488 mono_metadata_decode_table_row (class->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2489 event->parent = class;
2490 event->attrs = cols [MONO_EVENT_FLAGS];
2491 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
2493 startm = mono_metadata_methods_from_event (class->image, i, &endm);
2494 for (j = startm; j < endm; ++j) {
2497 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2499 if (class->image->uncompressed_metadata)
2500 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2501 method = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], class);
2503 method = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
2505 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2506 case METHOD_SEMANTIC_ADD_ON:
2507 event->add = method;
2509 case METHOD_SEMANTIC_REMOVE_ON:
2510 event->remove = method;
2512 case METHOD_SEMANTIC_FIRE:
2513 event->raise = method;
2515 case METHOD_SEMANTIC_OTHER: {
2516 #ifndef MONO_SMALL_CONFIG
2519 if (event->other == NULL) {
2520 event->other = g_new0 (MonoMethod*, 2);
2522 while (event->other [n])
2524 event->other = g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2526 event->other [n] = method;
2527 /* NULL terminated */
2528 event->other [n + 1] = NULL;
2537 /*Flush any pending writes as we do double checked locking on class->properties */
2538 mono_memory_barrier ();
2540 /* Leave this assignment as the last op in the function */
2541 class->ext->events = events;
2543 mono_loader_unlock ();
2547 * Global pool of interface IDs, represented as a bitset.
2548 * LOCKING: this is supposed to be accessed with the loader lock held.
2550 static MonoBitSet *global_interface_bitset = NULL;
2553 * mono_unload_interface_ids:
2554 * @bitset: bit set of interface IDs
2556 * When an image is unloaded, the interface IDs associated with
2557 * the image are put back in the global pool of IDs so the numbers
2561 mono_unload_interface_ids (MonoBitSet *bitset)
2563 mono_loader_lock ();
2564 mono_bitset_sub (global_interface_bitset, bitset);
2565 mono_loader_unlock ();
2569 mono_unload_interface_id (MonoClass *class)
2571 if (global_interface_bitset && class->interface_id) {
2572 mono_loader_lock ();
2573 mono_bitset_clear (global_interface_bitset, class->interface_id);
2574 mono_loader_unlock ();
2579 * mono_get_unique_iid:
2582 * Assign a unique integer ID to the interface represented by @class.
2583 * The ID will positive and as small as possible.
2584 * LOCKING: this is supposed to be called with the loader lock held.
2585 * Returns: the new ID.
2588 mono_get_unique_iid (MonoClass *class)
2592 g_assert (MONO_CLASS_IS_INTERFACE (class));
2594 if (!global_interface_bitset) {
2595 global_interface_bitset = mono_bitset_new (128, 0);
2598 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2600 int old_size = mono_bitset_size (global_interface_bitset);
2601 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2602 mono_bitset_free (global_interface_bitset);
2603 global_interface_bitset = new_set;
2606 mono_bitset_set (global_interface_bitset, iid);
2607 /* set the bit also in the per-image set */
2608 if (!class->generic_class) {
2609 if (class->image->interface_bitset) {
2610 if (iid >= mono_bitset_size (class->image->interface_bitset)) {
2611 MonoBitSet *new_set = mono_bitset_clone (class->image->interface_bitset, iid + 1);
2612 mono_bitset_free (class->image->interface_bitset);
2613 class->image->interface_bitset = new_set;
2616 class->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2618 mono_bitset_set (class->image->interface_bitset, iid);
2621 #ifndef MONO_SMALL_CONFIG
2622 if (mono_print_vtable) {
2624 char *type_name = mono_type_full_name (&class->byval_arg);
2625 if (class->generic_class && !class->generic_class->context.class_inst->is_open) {
2626 generic_id = class->generic_class->context.class_inst->id;
2627 g_assert (generic_id != 0);
2631 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, class->image->name, type_name, generic_id);
2636 g_assert (iid <= 65535);
2641 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2646 mono_class_setup_interfaces (klass, error);
2647 if (!mono_error_ok (error))
2650 for (i = 0; i < klass->interface_count; i++) {
2651 ic = klass->interfaces [i];
2654 *res = g_ptr_array_new ();
2655 g_ptr_array_add (*res, ic);
2656 mono_class_init (ic);
2657 if (ic->exception_type) {
2658 mono_error_set_type_load_class (error, ic, "Error Loading class");
2662 collect_implemented_interfaces_aux (ic, res, error);
2663 if (!mono_error_ok (error))
2669 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2671 GPtrArray *res = NULL;
2673 collect_implemented_interfaces_aux (klass, &res, error);
2674 if (!mono_error_ok (error)) {
2676 g_ptr_array_free (res, TRUE);
2683 compare_interface_ids (const void *p_key, const void *p_element) {
2684 const MonoClass *key = p_key;
2685 const MonoClass *element = *(MonoClass**) p_element;
2687 return (key->interface_id - element->interface_id);
2690 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2692 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2693 MonoClass **result = mono_binary_search (
2695 klass->interfaces_packed,
2696 klass->interface_offsets_count,
2697 sizeof (MonoClass *),
2698 compare_interface_ids);
2700 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2707 * mono_class_interface_offset_with_variance:
2709 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2710 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2712 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2714 * FIXME figure out MS disambiguation rules and fix this function.
2717 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2718 int i = mono_class_interface_offset (klass, itf);
2719 *non_exact_match = FALSE;
2723 if (!mono_class_has_variant_generic_params (itf))
2726 for (i = 0; i < klass->interface_offsets_count; i++) {
2727 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2728 *non_exact_match = TRUE;
2729 return klass->interface_offsets_packed [i];
2737 print_implemented_interfaces (MonoClass *klass) {
2740 GPtrArray *ifaces = NULL;
2742 int ancestor_level = 0;
2744 name = mono_type_get_full_name (klass);
2745 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2748 for (i = 0; i < klass->interface_offsets_count; i++)
2749 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2750 klass->interfaces_packed [i]->interface_id,
2751 klass->interface_offsets_packed [i],
2752 klass->interfaces_packed [i]->method.count,
2753 klass->interfaces_packed [i]->name_space,
2754 klass->interfaces_packed [i]->name );
2755 printf ("Interface flags: ");
2756 for (i = 0; i <= klass->max_interface_id; i++)
2757 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2758 printf ("(%d,T)", i);
2760 printf ("(%d,F)", i);
2762 printf ("Dump interface flags:");
2763 #ifdef COMPRESSED_INTERFACE_BITMAP
2765 const uint8_t* p = klass->interface_bitmap;
2766 i = klass->max_interface_id;
2768 printf (" %d x 00 %02X", p [0], p [1]);
2774 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2775 printf (" %02X", klass->interface_bitmap [i]);
2778 while (klass != NULL) {
2779 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2780 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2781 if (!mono_error_ok (&error)) {
2782 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2783 mono_error_cleanup (&error);
2784 } else if (ifaces) {
2785 for (i = 0; i < ifaces->len; i++) {
2786 MonoClass *ic = g_ptr_array_index (ifaces, i);
2787 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2788 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2790 mono_class_interface_offset (klass, ic),
2795 g_ptr_array_free (ifaces, TRUE);
2798 klass = klass->parent;
2803 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
2806 args [0] = &arg0->byval_arg;
2808 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
2812 array_class_get_if_rank (MonoClass *class, guint rank)
2814 return rank ? mono_array_class_get (class, rank) : class;
2818 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
2820 valuetype_types [0] = eclass;
2821 if (eclass == mono_defaults.int16_class)
2822 valuetype_types [1] = mono_defaults.uint16_class;
2823 else if (eclass == mono_defaults.uint16_class)
2824 valuetype_types [1] = mono_defaults.int16_class;
2825 else if (eclass == mono_defaults.int32_class)
2826 valuetype_types [1] = mono_defaults.uint32_class;
2827 else if (eclass == mono_defaults.uint32_class)
2828 valuetype_types [1] = mono_defaults.int32_class;
2829 else if (eclass == mono_defaults.int64_class)
2830 valuetype_types [1] = mono_defaults.uint64_class;
2831 else if (eclass == mono_defaults.uint64_class)
2832 valuetype_types [1] = mono_defaults.int64_class;
2833 else if (eclass == mono_defaults.byte_class)
2834 valuetype_types [1] = mono_defaults.sbyte_class;
2835 else if (eclass == mono_defaults.sbyte_class)
2836 valuetype_types [1] = mono_defaults.byte_class;
2837 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
2838 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
2841 /* this won't be needed once bug #325495 is completely fixed
2842 * though we'll need something similar to know which interfaces to allow
2843 * in arrays when they'll be lazyly created
2845 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
2846 * MS returns diferrent types based on which instance is called. For example:
2847 * object obj = new byte[10][];
2848 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
2849 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
2852 * Fixing this should kill quite some code, save some bits and improve compatibility.
2855 get_implicit_generic_array_interfaces (MonoClass *class, int *num, int *is_enumerator)
2857 MonoClass *eclass = class->element_class;
2858 static MonoClass* generic_icollection_class = NULL;
2859 static MonoClass* generic_ienumerable_class = NULL;
2860 static MonoClass* generic_ienumerator_class = NULL;
2861 static MonoClass* generic_ireadonlylist_class = NULL;
2862 static MonoClass* generic_ireadonlycollection_class = NULL;
2863 MonoClass *valuetype_types[2] = { NULL, NULL };
2864 MonoClass **interfaces = NULL;
2865 int i, nifaces, interface_count, real_count, original_rank;
2867 gboolean internal_enumerator;
2868 gboolean eclass_is_valuetype;
2870 if (!mono_defaults.generic_ilist_class) {
2874 internal_enumerator = FALSE;
2875 eclass_is_valuetype = FALSE;
2876 original_rank = eclass->rank;
2877 if (class->byval_arg.type != MONO_TYPE_SZARRAY) {
2878 if (class->generic_class && class->nested_in == mono_defaults.array_class && strcmp (class->name, "InternalEnumerator`1") == 0) {
2880 * For a Enumerator<T[]> we need to get the list of interfaces for T.
2882 eclass = mono_class_from_mono_type (class->generic_class->context.class_inst->type_argv [0]);
2883 original_rank = eclass->rank;
2885 eclass = eclass->element_class;
2886 internal_enumerator = TRUE;
2887 *is_enumerator = TRUE;
2895 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
2896 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
2898 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
2900 if (!generic_icollection_class) {
2901 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
2902 "System.Collections.Generic", "ICollection`1");
2903 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
2904 "System.Collections.Generic", "IEnumerable`1");
2905 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
2906 "System.Collections.Generic", "IEnumerator`1");
2907 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
2908 "System.Collections.Generic", "IReadOnlyList`1");
2909 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
2910 "System.Collections.Generic", "IReadOnlyCollection`1");
2913 mono_class_init (eclass);
2916 * Arrays in 2.0 need to implement a number of generic interfaces
2917 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
2918 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
2919 * We collect the types needed to build the
2920 * instantiations in interfaces at intervals of 3/5, because 3/5 are
2921 * the generic interfaces needed to implement.
2923 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
2924 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
2926 if (eclass->valuetype) {
2927 nifaces = generic_ireadonlylist_class ? 5 : 3;
2928 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
2930 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
2931 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
2932 if (internal_enumerator) {
2934 if (valuetype_types [1])
2938 interfaces = g_malloc0 (sizeof (MonoClass*) * real_count);
2939 interfaces [0] = valuetype_types [0];
2940 if (valuetype_types [1])
2941 interfaces [nifaces] = valuetype_types [1];
2943 eclass_is_valuetype = TRUE;
2946 int idepth = eclass->idepth;
2947 if (!internal_enumerator)
2949 nifaces = generic_ireadonlylist_class ? 2 : 3;
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);
3014 if (eclass->valuetype) {
3015 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3016 if (generic_ireadonlylist_class) {
3017 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3018 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3021 if (!generic_ireadonlylist_class)
3022 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3025 if (internal_enumerator) {
3027 /* instantiate IEnumerator<iface> */
3028 for (i = 0; i < interface_count; i++) {
3029 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3031 j = interface_count;
3032 if (!eclass_is_valuetype) {
3033 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3034 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3037 for (i = 0; i < eclass->idepth; i++) {
3038 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3042 for (i = 0; i < eclass->interface_offsets_count; i++) {
3043 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3047 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3049 if (valuetype_types [1])
3050 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3054 char *type_name = mono_type_get_name_full (&class->byval_arg, 0);
3055 for (i = 0; i < real_count; ++i) {
3056 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3057 g_print ("%s implements %s\n", type_name, name);
3068 find_array_interface (MonoClass *klass, const char *name)
3071 for (i = 0; i < klass->interface_count; ++i) {
3072 if (strcmp (klass->interfaces [i]->name, name) == 0)
3079 * Return the number of virtual methods.
3080 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3081 * Return -1 on failure.
3082 * FIXME It would be nice if this information could be cached somewhere.
3085 count_virtual_methods (MonoClass *class)
3089 class = mono_class_get_generic_type_definition (class); /*We can find this information by looking at the GTD*/
3091 if (class->methods || !MONO_CLASS_HAS_STATIC_METADATA (class)) {
3092 mono_class_setup_methods (class);
3093 if (class->exception_type)
3096 for (i = 0; i < class->method.count; ++i) {
3097 flags = class->methods [i]->flags;
3098 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3102 for (i = 0; i < class->method.count; ++i) {
3103 flags = mono_metadata_decode_table_row_col (class->image, MONO_TABLE_METHOD, class->method.first + i, MONO_METHOD_FLAGS);
3105 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3113 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3121 m = (l + num_ifaces) / 2;
3122 if (interfaces_full [m] == ic)
3124 if (l == num_ifaces)
3126 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3135 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3137 int i = find_interface (num_ifaces, interfaces_full, ic);
3139 return interface_offsets_full [i];
3144 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3146 int i = find_interface (num_ifaces, interfaces_full, ic);
3150 interface_offsets_full [i] = offset;
3153 for (i = 0; i < num_ifaces; ++i) {
3154 if (interfaces_full [i]) {
3156 if (interfaces_full [i]->interface_id < ic->interface_id)
3159 while (end < num_ifaces && interfaces_full [end]) end++;
3160 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3161 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3163 interfaces_full [i] = ic;
3164 interface_offsets_full [i] = offset;
3170 #ifdef COMPRESSED_INTERFACE_BITMAP
3173 * Compressed interface bitmap design.
3175 * Interface bitmaps take a large amount of memory, because their size is
3176 * linear with the maximum interface id assigned in the process (each interface
3177 * is assigned a unique id as it is loaded). The number of interface classes
3178 * is high because of the many implicit interfaces implemented by arrays (we'll
3179 * need to lazy-load them in the future).
3180 * Most classes implement a very small number of interfaces, so the bitmap is
3181 * sparse. This bitmap needs to be checked by interface casts, so access to the
3182 * needed bit must be fast and doable with few jit instructions.
3184 * The current compression format is as follows:
3185 * *) it is a sequence of one or more two-byte elements
3186 * *) the first byte in the element is the count of empty bitmap bytes
3187 * at the current bitmap position
3188 * *) the second byte in the element is an actual bitmap byte at the current
3191 * As an example, the following compressed bitmap bytes:
3192 * 0x07 0x01 0x00 0x7
3193 * correspond to the following bitmap:
3194 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3196 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3197 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3198 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3202 * mono_compress_bitmap:
3203 * @dest: destination buffer
3204 * @bitmap: bitmap buffer
3205 * @size: size of @bitmap in bytes
3207 * This is a mono internal function.
3208 * The @bitmap data is compressed into a format that is small but
3209 * still searchable in few instructions by the JIT and runtime.
3210 * The compressed data is stored in the buffer pointed to by the
3211 * @dest array. Passing a #NULL value for @dest allows to just compute
3212 * the size of the buffer.
3213 * This compression algorithm assumes the bits set in the bitmap are
3214 * few and far between, like in interface bitmaps.
3215 * Returns: the size of the compressed bitmap in bytes.
3218 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3222 const uint8_t *end = bitmap + size;
3223 while (bitmap < end) {
3224 if (*bitmap || numz == 255) {
3248 * mono_class_interface_match:
3249 * @bitmap: a compressed bitmap buffer
3250 * @id: the index to check in the bitmap
3252 * This is a mono internal function.
3253 * Checks if a bit is set in a compressed interface bitmap. @id must
3254 * be already checked for being smaller than the maximum id encoded in the
3257 * Returns: a non-zero value if bit @id is set in the bitmap @bitmap,
3261 mono_class_interface_match (const uint8_t *bitmap, int id)
3264 id -= bitmap [0] * 8;
3268 return bitmap [1] & (1 << id);
3277 * LOCKING: this is supposed to be called with the loader lock held.
3278 * Return -1 on failure and set exception_type
3281 setup_interface_offsets (MonoClass *class, int cur_slot, gboolean overwrite)
3285 int i, j, max_iid, num_ifaces;
3286 MonoClass **interfaces_full = NULL;
3287 int *interface_offsets_full = NULL;
3289 GPtrArray **ifaces_array = NULL;
3290 int interface_offsets_count;
3291 MonoClass **array_interfaces = NULL;
3292 int num_array_interfaces;
3293 int is_enumerator = FALSE;
3295 mono_class_setup_supertypes (class);
3297 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3298 * implicit interfaces have the property that they are assigned the same slot in the
3299 * vtables for compatible interfaces
3301 array_interfaces = get_implicit_generic_array_interfaces (class, &num_array_interfaces, &is_enumerator);
3303 /* compute maximum number of slots and maximum interface id */
3305 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3306 ifaces_array = g_new0 (GPtrArray *, class->idepth);
3307 for (j = 0; j < class->idepth; j++) {
3308 k = class->supertypes [j];
3309 num_ifaces += k->interface_count;
3310 for (i = 0; i < k->interface_count; i++) {
3311 ic = k->interfaces [i];
3314 mono_class_init (ic);
3316 if (max_iid < ic->interface_id)
3317 max_iid = ic->interface_id;
3319 ifaces = mono_class_get_implemented_interfaces (k, &error);
3320 if (!mono_error_ok (&error)) {
3321 char *name = mono_type_get_full_name (k);
3322 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)));
3324 mono_error_cleanup (&error);
3329 num_ifaces += ifaces->len;
3330 for (i = 0; i < ifaces->len; ++i) {
3331 ic = g_ptr_array_index (ifaces, i);
3332 if (max_iid < ic->interface_id)
3333 max_iid = ic->interface_id;
3335 ifaces_array [j] = ifaces;
3339 for (i = 0; i < num_array_interfaces; ++i) {
3340 ic = array_interfaces [i];
3341 mono_class_init (ic);
3342 if (max_iid < ic->interface_id)
3343 max_iid = ic->interface_id;
3346 if (MONO_CLASS_IS_INTERFACE (class)) {
3348 if (max_iid < class->interface_id)
3349 max_iid = class->interface_id;
3351 class->max_interface_id = max_iid;
3352 /* compute vtable offset for interfaces */
3353 interfaces_full = g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3354 interface_offsets_full = g_malloc (sizeof (int) * num_ifaces);
3356 for (i = 0; i < num_ifaces; i++) {
3357 interface_offsets_full [i] = -1;
3360 /* skip the current class */
3361 for (j = 0; j < class->idepth - 1; j++) {
3362 k = class->supertypes [j];
3363 ifaces = ifaces_array [j];
3366 for (i = 0; i < ifaces->len; ++i) {
3368 ic = g_ptr_array_index (ifaces, i);
3370 /*Force the sharing of interface offsets between parent and subtypes.*/
3371 io = mono_class_interface_offset (k, ic);
3373 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3378 g_assert (class == class->supertypes [class->idepth - 1]);
3379 ifaces = ifaces_array [class->idepth - 1];
3381 for (i = 0; i < ifaces->len; ++i) {
3383 ic = g_ptr_array_index (ifaces, i);
3384 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3386 count = count_virtual_methods (ic);
3388 char *name = mono_type_get_full_name (ic);
3389 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3398 if (MONO_CLASS_IS_INTERFACE (class))
3399 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, class, cur_slot, TRUE);
3401 if (num_array_interfaces) {
3402 if (is_enumerator) {
3403 int ienumerator_idx = find_array_interface (class, "IEnumerator`1");
3404 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ienumerator_idx]);
3405 g_assert (ienumerator_offset >= 0);
3406 for (i = 0; i < num_array_interfaces; ++i) {
3407 ic = array_interfaces [i];
3408 if (strcmp (ic->name, "IEnumerator`1") == 0)
3409 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3411 g_assert_not_reached ();
3412 /*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);*/
3415 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3416 int ilist_iface_idx = find_array_interface (class, "IList`1");
3417 MonoClass* ilist_class = class->interfaces [ilist_iface_idx];
3418 int ireadonlylist_iface_idx = find_array_interface (class, "IReadOnlyList`1");
3419 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? class->interfaces [ireadonlylist_iface_idx] : NULL;
3420 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3421 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3422 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3423 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ilist_iface_idx]);
3424 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3425 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3426 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, class->interfaces [ireadonlylist_iface_idx]) : -1;
3427 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3428 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3429 for (i = 0; i < num_array_interfaces; ++i) {
3431 ic = array_interfaces [i];
3432 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3433 offset = ilist_offset;
3434 else if (strcmp (ic->name, "ICollection`1") == 0)
3435 offset = icollection_offset;
3436 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3437 offset = ienumerable_offset;
3438 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3439 offset = ireadonlylist_offset;
3440 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3441 offset = ireadonlycollection_offset;
3443 g_assert_not_reached ();
3444 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3445 /*g_print ("type %s has %s offset at %d (%s)\n", class->name, ic->name, offset, class->interfaces [0]->name);*/
3450 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3451 if (interface_offsets_full [i] != -1) {
3452 interface_offsets_count ++;
3457 * We might get called multiple times:
3458 * - mono_class_init ()
3459 * - mono_class_setup_vtable ().
3460 * - mono_class_setup_interface_offsets ().
3461 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3462 * means we have to overwrite those when called from other places (#4440).
3464 if (class->interfaces_packed && !overwrite) {
3465 g_assert (class->interface_offsets_count == interface_offsets_count);
3469 class->interface_offsets_count = interface_offsets_count;
3470 class->interfaces_packed = mono_class_alloc (class, sizeof (MonoClass*) * interface_offsets_count);
3471 class->interface_offsets_packed = mono_class_alloc (class, sizeof (guint16) * interface_offsets_count);
3472 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3473 #ifdef COMPRESSED_INTERFACE_BITMAP
3474 bitmap = g_malloc0 (bsize);
3476 bitmap = mono_class_alloc0 (class, bsize);
3478 for (i = 0; i < interface_offsets_count; i++) {
3479 int id = interfaces_full [i]->interface_id;
3480 bitmap [id >> 3] |= (1 << (id & 7));
3481 class->interfaces_packed [i] = interfaces_full [i];
3482 class->interface_offsets_packed [i] = interface_offsets_full [i];
3483 /*if (num_array_interfaces)
3484 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]);*/
3486 #ifdef COMPRESSED_INTERFACE_BITMAP
3487 i = mono_compress_bitmap (NULL, bitmap, bsize);
3488 class->interface_bitmap = mono_class_alloc0 (class, i);
3489 mono_compress_bitmap (class->interface_bitmap, bitmap, bsize);
3492 class->interface_bitmap = bitmap;
3497 g_free (interfaces_full);
3498 g_free (interface_offsets_full);
3499 g_free (array_interfaces);
3500 for (i = 0; i < class->idepth; i++) {
3501 ifaces = ifaces_array [i];
3503 g_ptr_array_free (ifaces, TRUE);
3505 g_free (ifaces_array);
3507 //printf ("JUST DONE: ");
3508 //print_implemented_interfaces (class);
3514 * Setup interface offsets for interfaces.
3516 * - class->max_interface_id
3517 * - class->interface_offsets_count
3518 * - class->interfaces_packed
3519 * - class->interface_offsets_packed
3520 * - class->interface_bitmap
3522 * This function can fail @class.
3525 mono_class_setup_interface_offsets (MonoClass *class)
3527 mono_loader_lock ();
3529 setup_interface_offsets (class, 0, FALSE);
3531 mono_loader_unlock ();
3534 /*Checks if @klass has @parent as one of it's parents type gtd
3538 * Bar<T> : Foo<Bar<Bar<T>>>
3542 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3544 klass = mono_class_get_generic_type_definition (klass);
3545 parent = mono_class_get_generic_type_definition (parent);
3546 mono_class_setup_supertypes (klass);
3547 mono_class_setup_supertypes (parent);
3549 return klass->idepth >= parent->idepth &&
3550 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3554 mono_class_check_vtable_constraints (MonoClass *class, GList *in_setup)
3556 MonoGenericInst *ginst;
3558 if (!class->generic_class) {
3559 mono_class_setup_vtable_full (class, in_setup);
3560 return class->exception_type == 0;
3563 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (class), in_setup);
3564 if (class->generic_class->container_class->exception_type) {
3565 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3569 ginst = class->generic_class->context.class_inst;
3570 for (i = 0; i < ginst->type_argc; ++i) {
3572 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3574 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3575 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3576 if (mono_class_has_gtd_parent (class, arg) || mono_class_has_gtd_parent (arg, class))
3578 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3579 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3587 * mono_class_setup_vtable:
3589 * Creates the generic vtable of CLASS.
3590 * Initializes the following fields in MonoClass:
3593 * Plus all the fields initialized by setup_interface_offsets ().
3594 * If there is an error during vtable construction, class->exception_type is set.
3596 * LOCKING: Acquires the loader lock.
3599 mono_class_setup_vtable (MonoClass *class)
3601 mono_class_setup_vtable_full (class, NULL);
3605 mono_class_setup_vtable_full (MonoClass *class, GList *in_setup)
3607 MonoMethod **overrides;
3608 MonoGenericContext *context;
3616 if (MONO_CLASS_IS_INTERFACE (class)) {
3617 /* This sets method->slot for all methods if this is an interface */
3618 mono_class_setup_methods (class);
3622 if (class->exception_type)
3625 if (g_list_find (in_setup, class))
3628 mono_loader_lock ();
3630 if (class->vtable) {
3631 mono_loader_unlock ();
3635 mono_stats.generic_vtable_count ++;
3636 in_setup = g_list_prepend (in_setup, class);
3638 if (class->generic_class) {
3639 if (!mono_class_check_vtable_constraints (class, in_setup)) {
3640 mono_loader_unlock ();
3641 g_list_remove (in_setup, class);
3645 context = mono_class_get_context (class);
3646 type_token = class->generic_class->container_class->type_token;
3648 context = (MonoGenericContext *) class->generic_container;
3649 type_token = class->type_token;
3652 if (class->image->dynamic) {
3653 /* Generic instances can have zero method overrides without causing any harm.
3654 * This is true since we don't do layout all over again for them, we simply inflate
3655 * the layout of the parent.
3657 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
3659 /* The following call fails if there are missing methods in the type */
3660 /* FIXME it's probably a good idea to avoid this for generic instances. */
3661 ok = mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
3665 mono_class_setup_vtable_general (class, overrides, onum, in_setup);
3667 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3671 mono_loader_unlock ();
3672 g_list_remove (in_setup, class);
3677 #define DEBUG_INTERFACE_VTABLE_CODE 0
3678 #define TRACE_INTERFACE_VTABLE_CODE 0
3679 #define VERIFY_INTERFACE_VTABLE_CODE 0
3680 #define VTABLE_SELECTOR (1)
3682 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3683 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3684 if (!(VTABLE_SELECTOR)) break; \
3688 #define DEBUG_INTERFACE_VTABLE(stmt)
3691 #if TRACE_INTERFACE_VTABLE_CODE
3692 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3693 if (!(VTABLE_SELECTOR)) break; \
3697 #define TRACE_INTERFACE_VTABLE(stmt)
3700 #if VERIFY_INTERFACE_VTABLE_CODE
3701 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3702 if (!(VTABLE_SELECTOR)) break; \
3706 #define VERIFY_INTERFACE_VTABLE(stmt)
3710 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3712 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3716 GString *res = g_string_new ("");
3718 g_string_append_c (res, '(');
3719 for (i = 0; i < sig->param_count; ++i) {
3721 g_string_append_c (res, ',');
3722 mono_type_get_desc (res, sig->params [i], include_namespace);
3724 g_string_append (res, ")=>");
3725 if (sig->ret != NULL) {
3726 mono_type_get_desc (res, sig->ret, include_namespace);
3728 g_string_append (res, "NULL");
3731 g_string_free (res, FALSE);
3735 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3736 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3737 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3738 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3746 is_wcf_hack_disabled (void)
3748 static gboolean disabled;
3749 static gboolean inited = FALSE;
3751 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3758 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) {
3759 MonoMethodSignature *cmsig, *imsig;
3760 if (strcmp (im->name, cm->name) == 0) {
3761 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3762 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3765 if (! slot_is_empty) {
3766 if (require_newslot) {
3767 if (! interface_is_explicitly_implemented_by_class) {
3768 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3771 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3772 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3776 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3779 cmsig = mono_method_signature (cm);
3780 imsig = mono_method_signature (im);
3781 if (!cmsig || !imsig) {
3782 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3786 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3787 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3788 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3789 TRACE_INTERFACE_VTABLE (printf ("]"));
3792 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
3793 /* CAS - SecurityAction.InheritanceDemand on interface */
3794 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3795 mono_secman_inheritancedemand_method (cm, im);
3798 if (mono_security_core_clr_enabled ())
3799 mono_security_core_clr_check_override (class, cm, im);
3801 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
3802 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3803 char *body_name = mono_method_full_name (cm, TRUE);
3804 char *decl_name = mono_method_full_name (im, TRUE);
3805 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));
3813 MonoClass *ic = im->klass;
3814 const char *ic_name_space = ic->name_space;
3815 const char *ic_name = ic->name;
3818 if (! require_newslot) {
3819 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
3822 if (cm->klass->rank == 0) {
3823 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
3826 cmsig = mono_method_signature (cm);
3827 imsig = mono_method_signature (im);
3828 if (!cmsig || !imsig) {
3829 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3833 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3834 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
3835 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3836 TRACE_INTERFACE_VTABLE (printf ("]"));
3839 if (mono_class_get_image (ic) != mono_defaults.corlib) {
3840 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
3843 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
3844 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
3847 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))) {
3848 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
3852 subname = strstr (cm->name, ic_name_space);
3853 if (subname != cm->name) {
3854 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
3857 subname += strlen (ic_name_space);
3858 if (subname [0] != '.') {
3859 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
3863 if (strstr (subname, ic_name) != subname) {
3864 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
3867 subname += strlen (ic_name);
3868 if (subname [0] != '.') {
3869 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
3873 if (strcmp (subname, im->name) != 0) {
3874 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
3878 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
3879 /* CAS - SecurityAction.InheritanceDemand on interface */
3880 if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
3881 mono_secman_inheritancedemand_method (cm, im);
3884 if (mono_security_core_clr_enabled ())
3885 mono_security_core_clr_check_override (class, cm, im);
3887 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
3888 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
3889 char *body_name = mono_method_full_name (cm, TRUE);
3890 char *decl_name = mono_method_full_name (im, TRUE);
3891 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));
3901 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3903 foreach_override (gpointer key, gpointer value, gpointer user_data) {
3904 MonoMethod *method = key;
3905 MonoMethod *override = value;
3906 MonoClass *method_class = mono_method_get_class (method);
3907 MonoClass *override_class = mono_method_get_class (override);
3909 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
3910 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
3911 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
3914 print_overrides (GHashTable *override_map, const char *message) {
3916 printf ("Override map \"%s\" START:\n", message);
3917 g_hash_table_foreach (override_map, foreach_override, NULL);
3918 printf ("Override map \"%s\" END.\n", message);
3920 printf ("Override map \"%s\" EMPTY.\n", message);
3924 print_vtable_full (MonoClass *class, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
3925 char *full_name = mono_type_full_name (&class->byval_arg);
3929 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
3931 if (print_interfaces) {
3932 print_implemented_interfaces (class);
3933 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
3936 if (class->parent) {
3937 parent_size = class->parent->vtable_size;
3941 for (i = 0; i < size; ++i) {
3942 MonoMethod *cm = vtable [i];
3943 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
3944 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
3946 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
3954 #if VERIFY_INTERFACE_VTABLE_CODE
3956 mono_method_try_get_vtable_index (MonoMethod *method)
3958 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
3959 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
3960 if (imethod->declaring->is_generic)
3961 return imethod->declaring->slot;
3963 return method->slot;
3967 mono_class_verify_vtable (MonoClass *class)
3970 char *full_name = mono_type_full_name (&class->byval_arg);
3972 printf ("*** Verifying VTable of class '%s' \n", full_name);
3976 if (!class->methods)
3979 for (i = 0; i < class->method.count; ++i) {
3980 MonoMethod *cm = class->methods [i];
3983 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
3987 full_name = mono_method_full_name (cm, TRUE);
3989 slot = mono_method_try_get_vtable_index (cm);
3991 if (slot >= class->vtable_size) {
3992 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, class->vtable_size);
3996 if (slot >= 0 && class->vtable [slot] != cm && (class->vtable [slot])) {
3997 char *other_name = class->vtable [slot] ? mono_method_full_name (class->vtable [slot], TRUE) : g_strdup ("[null value]");
3998 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
3999 g_free (other_name);
4002 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4009 print_unimplemented_interface_method_info (MonoClass *class, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4011 char *method_signature;
4014 for (index = 0; index < onum; ++index) {
4015 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4016 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4018 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4019 type_name = mono_type_full_name (&class->byval_arg);
4020 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4021 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4022 g_free (method_signature);
4024 mono_class_setup_methods (class);
4025 if (class->exception_type) {
4026 char *name = mono_type_get_full_name (class);
4027 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4031 for (index = 0; index < class->method.count; ++index) {
4032 MonoMethod *cm = class->methods [index];
4033 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4035 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4036 g_free (method_signature);
4041 mono_method_get_method_definition (MonoMethod *method)
4043 while (method->is_inflated)
4044 method = ((MonoMethodInflated*)method)->declaring;
4049 verify_class_overrides (MonoClass *class, MonoMethod **overrides, int onum)
4053 for (i = 0; i < onum; ++i) {
4054 MonoMethod *decl = overrides [i * 2];
4055 MonoMethod *body = overrides [i * 2 + 1];
4057 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (class)) {
4058 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4062 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4063 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4064 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4066 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4070 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4071 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4072 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4074 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4078 if (!mono_class_is_assignable_from_slow (decl->klass, class)) {
4079 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that extended or implemented by this type"));
4083 body = mono_method_get_method_definition (body);
4084 decl = mono_method_get_method_definition (decl);
4086 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4087 char *body_name = mono_method_full_name (body, TRUE);
4088 char *decl_name = mono_method_full_name (decl, TRUE);
4089 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));
4099 mono_class_need_stelemref_method (MonoClass *class)
4101 return class->rank == 1 && MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg);
4105 * LOCKING: this is supposed to be called with the loader lock held.
4108 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum, GList *in_setup)
4112 MonoMethod **vtable;
4113 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4114 GPtrArray *ifaces = NULL;
4115 GHashTable *override_map = NULL;
4116 gboolean security_enabled = mono_security_enabled ();
4118 gpointer class_iter;
4119 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4120 int first_non_interface_slot;
4122 GSList *virt_methods = NULL, *l;
4123 int stelemref_slot = 0;
4128 if (overrides && !verify_class_overrides (class, overrides, onum))
4131 ifaces = mono_class_get_implemented_interfaces (class, &error);
4132 if (!mono_error_ok (&error)) {
4133 char *name = mono_type_get_full_name (class);
4134 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)));
4136 mono_error_cleanup (&error);
4138 } else if (ifaces) {
4139 for (i = 0; i < ifaces->len; i++) {
4140 MonoClass *ic = g_ptr_array_index (ifaces, i);
4141 max_vtsize += ic->method.count;
4143 g_ptr_array_free (ifaces, TRUE);
4147 if (class->parent) {
4148 mono_class_init (class->parent);
4149 mono_class_setup_vtable_full (class->parent, in_setup);
4151 if (class->parent->exception_type) {
4152 char *name = mono_type_get_full_name (class->parent);
4153 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4158 max_vtsize += class->parent->vtable_size;
4159 cur_slot = class->parent->vtable_size;
4162 max_vtsize += class->method.count;
4164 /*Array have a slot for stelemref*/
4165 if (mono_class_need_stelemref_method (class)) {
4166 stelemref_slot = cur_slot;
4171 vtable = alloca (sizeof (gpointer) * max_vtsize);
4172 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4174 /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
4176 cur_slot = setup_interface_offsets (class, cur_slot, TRUE);
4177 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4180 max_iid = class->max_interface_id;
4181 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4183 /* Optimized version for generic instances */
4184 if (class->generic_class) {
4186 MonoClass *gklass = class->generic_class->container_class;
4189 mono_class_setup_vtable_full (gklass, in_setup);
4190 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4191 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4195 tmp = mono_class_alloc0 (class, sizeof (gpointer) * gklass->vtable_size);
4196 class->vtable_size = gklass->vtable_size;
4197 for (i = 0; i < gklass->vtable_size; ++i)
4198 if (gklass->vtable [i]) {
4199 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], class, mono_class_get_context (class), &error);
4200 if (!mono_error_ok (&error)) {
4201 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4202 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4204 mono_error_cleanup (&error);
4208 tmp [i]->slot = gklass->vtable [i]->slot;
4210 mono_memory_barrier ();
4211 class->vtable = tmp;
4213 /* Have to set method->slot for abstract virtual methods */
4214 if (class->methods && gklass->methods) {
4215 for (i = 0; i < class->method.count; ++i)
4216 if (class->methods [i]->slot == -1)
4217 class->methods [i]->slot = gklass->methods [i]->slot;
4223 if (class->parent && class->parent->vtable_size) {
4224 MonoClass *parent = class->parent;
4227 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4229 // Also inherit parent interface vtables, just as a starting point.
4230 // This is needed otherwise bug-77127.exe fails when the property methods
4231 // have different names in the iterface and the class, because for child
4232 // classes the ".override" information is not used anymore.
4233 for (i = 0; i < parent->interface_offsets_count; i++) {
4234 MonoClass *parent_interface = parent->interfaces_packed [i];
4235 int interface_offset = mono_class_interface_offset (class, parent_interface);
4236 /*FIXME this is now dead code as this condition will never hold true.
4237 Since interface offsets are inherited then the offset of an interface implemented
4238 by a parent will never be the out of it's vtable boundary.
4240 if (interface_offset >= parent->vtable_size) {
4241 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4244 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4245 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4246 for (j = 0; j < parent_interface->method.count && !class->exception_type; j++) {
4247 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4248 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4249 parent_interface_offset + j, parent_interface_offset, j,
4250 interface_offset + j, interface_offset, j));
4257 /*Array have a slot for stelemref*/
4258 if (mono_class_need_stelemref_method (class)) {
4259 MonoMethod *method = mono_marshal_get_virtual_stelemref (class);
4261 method->slot = stelemref_slot;
4263 g_assert (method->slot == stelemref_slot);
4265 vtable [stelemref_slot] = method;
4268 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4269 /* override interface methods */
4270 for (i = 0; i < onum; i++) {
4271 MonoMethod *decl = overrides [i*2];
4272 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4274 dslot = mono_method_get_vtable_slot (decl);
4276 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4280 dslot += mono_class_interface_offset (class, decl->klass);
4281 vtable [dslot] = overrides [i*2 + 1];
4282 vtable [dslot]->slot = dslot;
4284 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4286 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4288 if (mono_security_core_clr_enabled ())
4289 mono_security_core_clr_check_override (class, vtable [dslot], decl);
4292 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4293 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4296 * Create a list of virtual methods to avoid calling
4297 * mono_class_get_virtual_methods () which is slow because of the metadata
4301 gpointer iter = NULL;
4304 virt_methods = NULL;
4305 while ((cm = mono_class_get_virtual_methods (class, &iter))) {
4306 virt_methods = g_slist_prepend (virt_methods, cm);
4308 if (class->exception_type)
4312 // Loop on all implemented interfaces...
4313 for (i = 0; i < class->interface_offsets_count; i++) {
4314 MonoClass *parent = class->parent;
4316 gboolean interface_is_explicitly_implemented_by_class;
4319 ic = class->interfaces_packed [i];
4320 ic_offset = mono_class_interface_offset (class, ic);
4322 mono_class_setup_methods (ic);
4323 if (ic->exception_type)
4326 // Check if this interface is explicitly implemented (instead of just inherited)
4327 if (parent != NULL) {
4328 int implemented_interfaces_index;
4329 interface_is_explicitly_implemented_by_class = FALSE;
4330 for (implemented_interfaces_index = 0; implemented_interfaces_index < class->interface_count; implemented_interfaces_index++) {
4331 if (ic == class->interfaces [implemented_interfaces_index]) {
4332 interface_is_explicitly_implemented_by_class = TRUE;
4337 interface_is_explicitly_implemented_by_class = TRUE;
4340 // Loop on all interface methods...
4341 for (im_index = 0; im_index < ic->method.count; im_index++) {
4342 MonoMethod *im = ic->methods [im_index];
4343 int im_slot = ic_offset + im->slot;
4344 MonoMethod *override_im = (override_map != NULL) ? g_hash_table_lookup (override_map, im) : NULL;
4346 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4349 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4351 // If there is an explicit implementation, just use it right away,
4352 // otherwise look for a matching method
4353 if (override_im == NULL) {
4358 // First look for a suitable method among the class methods
4360 for (l = virt_methods; l; l = l->next) {
4362 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)));
4363 if (check_interface_method_override (class, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL), security_enabled)) {
4364 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4365 vtable [im_slot] = cm;
4366 /* Why do we need this? */
4371 TRACE_INTERFACE_VTABLE (printf ("\n"));
4372 if (class->exception_type) /*Might be set by check_interface_method_override*/
4376 // If the slot is still empty, look in all the inherited virtual methods...
4377 if ((vtable [im_slot] == NULL) && class->parent != NULL) {
4378 MonoClass *parent = class->parent;
4379 // Reverse order, so that last added methods are preferred
4380 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4381 MonoMethod *cm = parent->vtable [cm_index];
4383 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));
4384 if ((cm != NULL) && check_interface_method_override (class, im, cm, FALSE, FALSE, TRUE, security_enabled)) {
4385 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4386 vtable [im_slot] = cm;
4387 /* Why do we need this? */
4393 if (class->exception_type) /*Might be set by check_interface_method_override*/
4395 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4399 g_assert (vtable [im_slot] == override_im);
4404 // If the class is not abstract, check that all its interface slots are full.
4405 // The check is done here and not directly at the end of the loop above because
4406 // it can happen (for injected generic array interfaces) that the same slot is
4407 // processed multiple times (those interfaces have overlapping slots), and it
4408 // will not always be the first pass the one that fills the slot.
4409 if (! (class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4410 for (i = 0; i < class->interface_offsets_count; i++) {
4414 ic = class->interfaces_packed [i];
4415 ic_offset = mono_class_interface_offset (class, ic);
4417 for (im_index = 0; im_index < ic->method.count; im_index++) {
4418 MonoMethod *im = ic->methods [im_index];
4419 int im_slot = ic_offset + im->slot;
4421 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4424 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4425 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4426 if (vtable [im_slot] == NULL) {
4427 print_unimplemented_interface_method_info (class, ic, im, im_slot, overrides, onum);
4434 TRACE_INTERFACE_VTABLE (print_vtable_full (class, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4436 for (l = virt_methods; l; l = l->next) {
4439 * If the method is REUSE_SLOT, we must check in the
4440 * base class for a method to override.
4442 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4444 for (k = class->parent; k ; k = k->parent) {
4449 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4450 MonoMethodSignature *cmsig, *m1sig;
4452 cmsig = mono_method_signature (cm);
4453 m1sig = mono_method_signature (m1);
4455 if (!cmsig || !m1sig) {
4456 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4460 if (!strcmp(cm->name, m1->name) &&
4461 mono_metadata_signature_equal (cmsig, m1sig)) {
4463 /* CAS - SecurityAction.InheritanceDemand */
4464 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
4465 mono_secman_inheritancedemand_method (cm, m1);
4468 if (mono_security_core_clr_enabled ())
4469 mono_security_core_clr_check_override (class, cm, m1);
4471 slot = mono_method_get_vtable_slot (m1);
4475 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4476 char *body_name = mono_method_full_name (cm, TRUE);
4477 char *decl_name = mono_method_full_name (m1, TRUE);
4478 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));
4484 g_assert (cm->slot < max_vtsize);
4486 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4487 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4488 mono_method_full_name (m1, 1), m1,
4489 mono_method_full_name (cm, 1), cm));
4490 g_hash_table_insert (override_map, m1, cm);
4494 if (k->exception_type)
4504 /*Non final newslot methods must be given a non-interface vtable slot*/
4505 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4509 cm->slot = cur_slot++;
4511 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4512 vtable [cm->slot] = cm;
4515 /* override non interface methods */
4516 for (i = 0; i < onum; i++) {
4517 MonoMethod *decl = overrides [i*2];
4518 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4519 g_assert (decl->slot != -1);
4520 vtable [decl->slot] = overrides [i*2 + 1];
4521 overrides [i * 2 + 1]->slot = decl->slot;
4523 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4524 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4525 mono_method_full_name (decl, 1), decl,
4526 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4527 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4529 if (mono_security_core_clr_enabled ())
4530 mono_security_core_clr_check_override (class, vtable [decl->slot], decl);
4535 * If a method occupies more than one place in the vtable, and it is
4536 * overriden, then change the other occurances too.
4541 for (i = 0; i < max_vtsize; ++i)
4543 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4545 cm = g_hash_table_lookup (override_map, vtable [i]);
4550 g_hash_table_destroy (override_map);
4551 override_map = NULL;
4554 g_slist_free (virt_methods);
4555 virt_methods = NULL;
4557 /* Ensure that all vtable slots are filled with concrete instance methods */
4558 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4559 for (i = 0; i < cur_slot; ++i) {
4560 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4561 char *type_name = mono_type_get_full_name (class);
4562 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4563 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));
4565 g_free (method_name);
4571 if (class->generic_class) {
4572 MonoClass *gklass = class->generic_class->container_class;
4574 mono_class_init (gklass);
4576 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
4578 /* Check that the vtable_size value computed in mono_class_init () is correct */
4579 if (class->vtable_size)
4580 g_assert (cur_slot == class->vtable_size);
4581 class->vtable_size = cur_slot;
4584 /* Try to share the vtable with our parent. */
4585 if (class->parent && (class->parent->vtable_size == class->vtable_size) && (memcmp (class->parent->vtable, vtable, sizeof (gpointer) * class->vtable_size) == 0)) {
4586 mono_memory_barrier ();
4587 class->vtable = class->parent->vtable;
4589 MonoMethod **tmp = mono_class_alloc0 (class, sizeof (gpointer) * class->vtable_size);
4590 memcpy (tmp, vtable, sizeof (gpointer) * class->vtable_size);
4591 mono_memory_barrier ();
4592 class->vtable = tmp;
4595 DEBUG_INTERFACE_VTABLE (print_vtable_full (class, class->vtable, class->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4596 if (mono_print_vtable) {
4599 print_implemented_interfaces (class);
4601 for (i = 0; i <= max_iid; i++)
4602 if (MONO_CLASS_IMPLEMENTS_INTERFACE (class, i))
4605 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg),
4606 class->vtable_size, icount);
4608 for (i = 0; i < cur_slot; ++i) {
4613 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4614 mono_method_full_name (cm, TRUE));
4620 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
4621 class->name, max_iid);
4623 for (i = 0; i < class->interface_count; i++) {
4624 ic = class->interfaces [i];
4625 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4626 mono_class_interface_offset (class, ic),
4627 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4630 for (k = class->parent; k ; k = k->parent) {
4631 for (i = 0; i < k->interface_count; i++) {
4632 ic = k->interfaces [i];
4633 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4634 mono_class_interface_offset (class, ic),
4635 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4641 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (class));
4646 char *name = mono_type_get_full_name (class);
4647 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4650 g_hash_table_destroy (override_map);
4652 g_slist_free (virt_methods);
4657 * mono_method_get_vtable_slot:
4659 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4660 * LOCKING: Acquires the loader lock.
4662 * FIXME Use proper MonoError machinery here.
4665 mono_method_get_vtable_slot (MonoMethod *method)
4667 if (method->slot == -1) {
4668 mono_class_setup_vtable (method->klass);
4669 if (method->klass->exception_type)
4671 if (method->slot == -1) {
4675 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4676 g_assert (method->klass->generic_class);
4677 gklass = method->klass->generic_class->container_class;
4678 mono_class_setup_methods (method->klass);
4679 g_assert (method->klass->methods);
4680 for (i = 0; i < method->klass->method.count; ++i) {
4681 if (method->klass->methods [i] == method)
4684 g_assert (i < method->klass->method.count);
4685 g_assert (gklass->methods);
4686 method->slot = gklass->methods [i]->slot;
4688 g_assert (method->slot != -1);
4690 return method->slot;
4694 * mono_method_get_vtable_index:
4697 * Returns the index into the runtime vtable to access the method or,
4698 * in the case of a virtual generic method, the virtual generic method
4699 * thunk. Returns -1 on failure.
4701 * FIXME Use proper MonoError machinery here.
4704 mono_method_get_vtable_index (MonoMethod *method)
4706 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4707 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4708 if (imethod->declaring->is_generic)
4709 return mono_method_get_vtable_slot (imethod->declaring);
4711 return mono_method_get_vtable_slot (method);
4714 static MonoMethod *default_ghc = NULL;
4715 static MonoMethod *default_finalize = NULL;
4716 static int finalize_slot = -1;
4717 static int ghc_slot = -1;
4720 initialize_object_slots (MonoClass *class)
4725 if (class == mono_defaults.object_class) {
4726 mono_class_setup_vtable (class);
4727 for (i = 0; i < class->vtable_size; ++i) {
4728 MonoMethod *cm = class->vtable [i];
4730 if (!strcmp (cm->name, "GetHashCode"))
4732 else if (!strcmp (cm->name, "Finalize"))
4736 g_assert (ghc_slot > 0);
4737 default_ghc = class->vtable [ghc_slot];
4739 g_assert (finalize_slot > 0);
4740 default_finalize = class->vtable [finalize_slot];
4745 MonoMethod *array_method;
4747 } GenericArrayMethodInfo;
4749 static int generic_array_method_num = 0;
4750 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4753 generic_array_methods (MonoClass *class)
4755 int i, count_generic = 0;
4756 GList *list = NULL, *tmp;
4757 if (generic_array_method_num)
4758 return generic_array_method_num;
4759 mono_class_setup_methods (class->parent); /*This is setting up System.Array*/
4760 g_assert (!class->parent->exception_type); /*So hitting this assert is a huge problem*/
4761 for (i = 0; i < class->parent->method.count; i++) {
4762 MonoMethod *m = class->parent->methods [i];
4763 if (!strncmp (m->name, "InternalArray__", 15)) {
4765 list = g_list_prepend (list, m);
4768 list = g_list_reverse (list);
4769 generic_array_method_info = mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4771 for (tmp = list; tmp; tmp = tmp->next) {
4772 const char *mname, *iname;
4774 MonoMethod *m = tmp->data;
4775 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4776 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4778 generic_array_method_info [i].array_method = m;
4779 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4780 iname = "System.Collections.Generic.ICollection`1.";
4781 mname = m->name + 27;
4782 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4783 iname = "System.Collections.Generic.IEnumerable`1.";
4784 mname = m->name + 27;
4785 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4786 iname = "System.Collections.Generic.IReadOnlyList`1.";
4787 mname = m->name + strlen (ireadonlylist_prefix);
4788 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4789 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4790 mname = m->name + strlen (ireadonlycollection_prefix);
4791 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4792 iname = "System.Collections.Generic.IList`1.";
4793 mname = m->name + 15;
4795 g_assert_not_reached ();
4798 name = mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4799 strcpy (name, iname);
4800 strcpy (name + strlen (iname), mname);
4801 generic_array_method_info [i].name = name;
4804 /*g_print ("array generic methods: %d\n", count_generic);*/
4806 generic_array_method_num = count_generic;
4808 return generic_array_method_num;
4812 setup_generic_array_ifaces (MonoClass *class, MonoClass *iface, MonoMethod **methods, int pos)
4814 MonoGenericContext tmp_context;
4817 tmp_context.class_inst = NULL;
4818 tmp_context.method_inst = iface->generic_class->context.class_inst;
4819 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4821 for (i = 0; i < generic_array_method_num; i++) {
4822 MonoMethod *m = generic_array_method_info [i].array_method;
4823 MonoMethod *inflated;
4825 inflated = mono_class_inflate_generic_method (m, &tmp_context);
4826 methods [pos++] = mono_marshal_get_generic_array_helper (class, iface, generic_array_method_info [i].name, inflated);
4831 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4833 int null_length = strlen ("(null)");
4834 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4835 char *s = mono_image_alloc (image, len);
4838 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4839 g_assert (result == len - 1);
4845 set_failure_from_loader_error (MonoClass *class, MonoLoaderError *error)
4847 gpointer exception_data = NULL;
4849 switch (error->exception_type) {
4850 case MONO_EXCEPTION_TYPE_LOAD:
4851 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->assembly_name);
4854 case MONO_EXCEPTION_MISSING_METHOD:
4855 exception_data = concat_two_strings_with_zero (class->image, error->class_name, error->member_name);
4858 case MONO_EXCEPTION_MISSING_FIELD: {
4859 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
4860 const char *class_name;
4863 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
4865 class_name = error->klass->name;
4867 exception_data = concat_two_strings_with_zero (class->image, class_name, error->member_name);
4870 g_free ((void*)class_name);
4874 case MONO_EXCEPTION_FILE_NOT_FOUND: {
4877 if (error->ref_only)
4878 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.";
4880 msg = "Could not load file or assembly '%s' or one of its dependencies.";
4882 exception_data = concat_two_strings_with_zero (class->image, msg, error->assembly_name);
4886 case MONO_EXCEPTION_BAD_IMAGE:
4887 exception_data = error->msg;
4891 g_assert_not_reached ();
4894 mono_class_set_failure (class, error->exception_type, exception_data);
4899 * @class: the class to initialize
4901 * Compute the instance_size, class_size and other infos that cannot be
4902 * computed at mono_class_get() time. Also compute vtable_size if possible.
4903 * Returns TRUE on success or FALSE if there was a problem in loading
4904 * the type (incorrect assemblies, missing assemblies, methods, etc).
4906 * LOCKING: Acquires the loader lock.
4909 mono_class_init (MonoClass *class)
4912 MonoCachedClassInfo cached_info;
4913 gboolean has_cached_info;
4917 /* Double-checking locking pattern */
4918 if (class->inited || class->exception_type)
4919 return class->exception_type == MONO_EXCEPTION_NONE;
4921 /*g_print ("Init class %s\n", mono_type_get_full_name (class));*/
4923 /* We do everything inside the lock to prevent races */
4924 mono_loader_lock ();
4926 if (class->inited || class->exception_type) {
4927 mono_loader_unlock ();
4928 /* Somebody might have gotten in before us */
4929 return class->exception_type == MONO_EXCEPTION_NONE;
4932 if (class->init_pending) {
4933 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
4937 class->init_pending = 1;
4939 if (mono_verifier_is_enabled_for_class (class) && !mono_verifier_verify_class (class)) {
4940 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (class->image, class->name, class->image->assembly_name));
4945 if (class->byval_arg.type == MONO_TYPE_ARRAY || class->byval_arg.type == MONO_TYPE_SZARRAY) {
4946 MonoClass *element_class = class->element_class;
4947 if (!element_class->inited)
4948 mono_class_init (element_class);
4949 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
4950 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
4955 /* CAS - SecurityAction.InheritanceDemand */
4956 if (mono_security_enabled () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
4957 mono_secman_inheritancedemand_class (class, class->parent);
4960 mono_stats.initialized_class_count++;
4962 if (class->generic_class && !class->generic_class->is_dynamic) {
4963 MonoClass *gklass = class->generic_class->container_class;
4965 mono_stats.generic_class_count++;
4967 class->method = gklass->method;
4968 class->field = gklass->field;
4970 mono_class_init (gklass);
4971 // FIXME: Why is this needed ?
4972 if (!gklass->exception_type)
4973 mono_class_setup_methods (gklass);
4974 if (gklass->exception_type) {
4975 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
4979 if (MONO_CLASS_IS_INTERFACE (class))
4980 class->interface_id = mono_get_unique_iid (class);
4983 if (class->parent && !class->parent->inited)
4984 mono_class_init (class->parent);
4986 has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
4988 if (class->generic_class || class->image->dynamic || !class->type_token || (has_cached_info && !cached_info.has_nested_classes))
4989 class->nested_classes_inited = TRUE;
4992 * Computes the size used by the fields, and their locations
4994 if (has_cached_info) {
4995 class->instance_size = cached_info.instance_size;
4996 class->sizes.class_size = cached_info.class_size;
4997 class->packing_size = cached_info.packing_size;
4998 class->min_align = cached_info.min_align;
4999 class->blittable = cached_info.blittable;
5000 class->has_references = cached_info.has_references;
5001 class->has_static_refs = cached_info.has_static_refs;
5002 class->no_special_static_fields = cached_info.no_special_static_fields;
5005 if (!class->size_inited){
5006 mono_class_setup_fields (class);
5007 if (class->exception_type || mono_loader_get_last_error ())
5011 /* Initialize arrays */
5013 class->method.count = 3 + (class->rank > 1? 2: 1);
5015 if (class->interface_count) {
5016 int count_generic = generic_array_methods (class);
5017 class->method.count += class->interface_count * count_generic;
5021 mono_class_setup_supertypes (class);
5024 initialize_object_slots (class);
5027 * Initialize the rest of the data without creating a generic vtable if possible.
5028 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5029 * also avoid computing a generic vtable.
5031 if (has_cached_info) {
5033 class->vtable_size = cached_info.vtable_size;
5034 class->has_finalize = cached_info.has_finalize;
5035 class->has_finalize_inited = TRUE;
5036 class->ghcimpl = cached_info.ghcimpl;
5037 class->has_cctor = cached_info.has_cctor;
5038 } else if (class->rank == 1 && class->byval_arg.type == MONO_TYPE_SZARRAY) {
5039 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5040 * The first slot if for array with.
5042 static int szarray_vtable_size[2] = { 0 };
5044 int slot = MONO_TYPE_IS_REFERENCE (&class->element_class->byval_arg) ? 0 : 1;
5047 if (!szarray_vtable_size [slot]) {
5048 mono_class_setup_vtable (class);
5049 szarray_vtable_size [slot] = class->vtable_size;
5051 class->vtable_size = szarray_vtable_size[slot];
5053 class->has_finalize_inited = TRUE;
5054 } else if (class->generic_class && !MONO_CLASS_IS_INTERFACE (class)) {
5055 MonoClass *gklass = class->generic_class->container_class;
5057 /* Generic instance case */
5058 class->ghcimpl = gklass->ghcimpl;
5059 class->has_finalize = mono_class_has_finalizer (gklass);
5060 class->has_finalize_inited = TRUE;
5061 class->has_cctor = gklass->has_cctor;
5063 mono_class_setup_vtable (gklass);
5064 if (gklass->exception_type) {
5065 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5069 class->vtable_size = gklass->vtable_size;
5073 /* ghcimpl is not currently used
5075 if (class->parent) {
5076 MonoMethod *cmethod = class->vtable [ghc_slot];
5077 if (cmethod->is_inflated)
5078 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5079 if (cmethod == default_ghc) {
5085 /* C# doesn't allow interfaces to have cctors */
5086 if (!MONO_CLASS_IS_INTERFACE (class) || class->image != mono_defaults.corlib) {
5087 MonoMethod *cmethod = NULL;
5089 if (class->type_token) {
5090 cmethod = find_method_in_metadata (class, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5091 /* The find_method function ignores the 'flags' argument */
5092 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5093 class->has_cctor = 1;
5095 mono_class_setup_methods (class);
5096 if (class->exception_type)
5099 for (i = 0; i < class->method.count; ++i) {
5100 MonoMethod *method = class->methods [i];
5101 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5102 (strcmp (".cctor", method->name) == 0)) {
5103 class->has_cctor = 1;
5111 if (class->parent) {
5112 int first_iface_slot;
5113 /* This will compute class->parent->vtable_size for some classes */
5114 mono_class_init (class->parent);
5115 if (class->parent->exception_type) {
5116 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5119 if (mono_loader_get_last_error ())
5121 if (!class->parent->vtable_size) {
5122 /* FIXME: Get rid of this somehow */
5123 mono_class_setup_vtable (class->parent);
5124 if (class->parent->exception_type) {
5125 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5128 if (mono_loader_get_last_error ())
5131 first_iface_slot = class->parent->vtable_size;
5132 if (mono_class_need_stelemref_method (class))
5134 setup_interface_offsets (class, first_iface_slot, TRUE);
5136 setup_interface_offsets (class, 0, TRUE);
5139 if (mono_security_core_clr_enabled ())
5140 mono_security_core_clr_check_inheritance (class);
5142 if (mono_loader_get_last_error ()) {
5143 if (class->exception_type == MONO_EXCEPTION_NONE) {
5144 set_failure_from_loader_error (class, mono_loader_get_last_error ());
5146 mono_loader_clear_error ();
5149 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
5150 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5155 /* Because of the double-checking locking pattern */
5156 mono_memory_barrier ();
5158 class->init_pending = 0;
5160 mono_loader_unlock ();
5162 if (mono_debugger_class_init_func)
5163 mono_debugger_class_init_func (class);
5165 return class->exception_type == MONO_EXCEPTION_NONE;
5169 * mono_class_has_finalizer:
5171 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5175 mono_class_has_finalizer (MonoClass *klass)
5177 if (!klass->has_finalize_inited) {
5178 MonoClass *class = klass;
5180 mono_loader_lock ();
5182 /* Interfaces and valuetypes are not supposed to have finalizers */
5183 if (!(MONO_CLASS_IS_INTERFACE (class) || class->valuetype)) {
5184 MonoMethod *cmethod = NULL;
5186 if (class->parent && class->parent->has_finalize) {
5187 class->has_finalize = 1;
5189 if (class->parent) {
5191 * Can't search in metadata for a method named Finalize, because that
5192 * ignores overrides.
5194 mono_class_setup_vtable (class);
5195 if (class->exception_type || mono_loader_get_last_error ())
5197 cmethod = class->vtable [finalize_slot];
5201 g_assert (class->vtable_size > finalize_slot);
5203 class->has_finalize = 0;
5204 if (class->parent) {
5205 if (cmethod->is_inflated)
5206 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5207 if (cmethod != default_finalize) {
5208 class->has_finalize = 1;
5215 mono_memory_barrier ();
5216 klass->has_finalize_inited = TRUE;
5218 mono_loader_unlock ();
5221 return klass->has_finalize;
5224 mono_loader_unlock ();
5229 mono_is_corlib_image (MonoImage *image)
5231 /* FIXME: allow the dynamic case for our compilers and with full trust */
5233 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5235 return image == mono_defaults.corlib;
5239 * LOCKING: this assumes the loader lock is held
5242 mono_class_setup_mono_type (MonoClass *class)
5244 const char *name = class->name;
5245 const char *nspace = class->name_space;
5246 gboolean is_corlib = mono_is_corlib_image (class->image);
5248 class->this_arg.byref = 1;
5249 class->this_arg.data.klass = class;
5250 class->this_arg.type = MONO_TYPE_CLASS;
5251 class->byval_arg.data.klass = class;
5252 class->byval_arg.type = MONO_TYPE_CLASS;
5254 if (is_corlib && !strcmp (nspace, "System")) {
5255 if (!strcmp (name, "ValueType")) {
5257 * do not set the valuetype bit for System.ValueType.
5258 * class->valuetype = 1;
5260 class->blittable = TRUE;
5261 } else if (!strcmp (name, "Enum")) {
5263 * do not set the valuetype bit for System.Enum.
5264 * class->valuetype = 1;
5266 class->valuetype = 0;
5267 class->enumtype = 0;
5268 } else if (!strcmp (name, "Object")) {
5269 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
5270 } else if (!strcmp (name, "String")) {
5271 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
5272 } else if (!strcmp (name, "TypedReference")) {
5273 class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5277 if (class->valuetype) {
5278 int t = MONO_TYPE_VALUETYPE;
5280 if (is_corlib && !strcmp (nspace, "System")) {
5283 if (!strcmp (name, "Boolean")) {
5284 t = MONO_TYPE_BOOLEAN;
5285 } else if (!strcmp(name, "Byte")) {
5287 class->blittable = TRUE;
5291 if (!strcmp (name, "Char")) {
5296 if (!strcmp (name, "Double")) {
5298 class->blittable = TRUE;
5302 if (!strcmp (name, "Int32")) {
5304 class->blittable = TRUE;
5305 } else if (!strcmp(name, "Int16")) {
5307 class->blittable = TRUE;
5308 } else if (!strcmp(name, "Int64")) {
5310 class->blittable = TRUE;
5311 } else if (!strcmp(name, "IntPtr")) {
5313 class->blittable = TRUE;
5317 if (!strcmp (name, "Single")) {
5319 class->blittable = TRUE;
5320 } else if (!strcmp(name, "SByte")) {
5322 class->blittable = TRUE;
5326 if (!strcmp (name, "UInt32")) {
5328 class->blittable = TRUE;
5329 } else if (!strcmp(name, "UInt16")) {
5331 class->blittable = TRUE;
5332 } else if (!strcmp(name, "UInt64")) {
5334 class->blittable = TRUE;
5335 } else if (!strcmp(name, "UIntPtr")) {
5337 class->blittable = TRUE;
5341 if (!strcmp (name, "TypedReference")) {
5342 t = MONO_TYPE_TYPEDBYREF;
5343 class->blittable = TRUE;
5347 if (!strcmp (name, "Void")) {
5355 class->this_arg.type = class->byval_arg.type = t;
5358 if (MONO_CLASS_IS_INTERFACE (class))
5359 class->interface_id = mono_get_unique_iid (class);
5365 * COM initialization is delayed until needed.
5366 * However when a [ComImport] attribute is present on a type it will trigger
5367 * the initialization. This is not a problem unless the BCL being executed
5368 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5371 init_com_from_comimport (MonoClass *class)
5373 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5374 if (mono_security_core_clr_enabled ()) {
5375 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5376 if (!mono_security_core_clr_determine_platform_image (class->image)) {
5377 /* but it can not be made available for application (i.e. user code) since all COM calls
5378 * are considered native calls. In this case we fail with a TypeLoadException (just like
5379 * Silverlight 2 does */
5380 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5385 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5387 #endif /*DISABLE_COM*/
5390 * LOCKING: this assumes the loader lock is held
5393 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
5395 gboolean system_namespace;
5396 gboolean is_corlib = mono_is_corlib_image (class->image);
5398 system_namespace = !strcmp (class->name_space, "System") && is_corlib;
5400 /* if root of the hierarchy */
5401 if (system_namespace && !strcmp (class->name, "Object")) {
5402 class->parent = NULL;
5403 class->instance_size = sizeof (MonoObject);
5406 if (!strcmp (class->name, "<Module>")) {
5407 class->parent = NULL;
5408 class->instance_size = 0;
5412 if (!MONO_CLASS_IS_INTERFACE (class)) {
5413 /* Imported COM Objects always derive from __ComObject. */
5415 if (MONO_CLASS_IS_IMPORT (class)) {
5416 init_com_from_comimport (class);
5417 if (parent == mono_defaults.object_class)
5418 parent = mono_class_get_com_object_class ();
5422 /* set the parent to something useful and safe, but mark the type as broken */
5423 parent = mono_defaults.object_class;
5424 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
5427 class->parent = parent;
5429 if (parent->generic_class && !parent->name) {
5431 * If the parent is a generic instance, we may get
5432 * called before it is fully initialized, especially
5433 * before it has its name.
5438 #ifndef DISABLE_REMOTING
5439 class->marshalbyref = parent->marshalbyref;
5440 class->contextbound = parent->contextbound;
5443 class->delegate = parent->delegate;
5445 if (MONO_CLASS_IS_IMPORT (class) || mono_class_is_com_object (parent))
5446 mono_class_set_is_com_object (class);
5448 if (system_namespace) {
5449 #ifndef DISABLE_REMOTING
5450 if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
5451 class->marshalbyref = 1;
5453 if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject"))
5454 class->contextbound = 1;
5456 if (*class->name == 'D' && !strcmp (class->name, "Delegate"))
5457 class->delegate = 1;
5460 if (class->parent->enumtype || (mono_is_corlib_image (class->parent->image) && (strcmp (class->parent->name, "ValueType") == 0) &&
5461 (strcmp (class->parent->name_space, "System") == 0)))
5462 class->valuetype = 1;
5463 if (mono_is_corlib_image (class->parent->image) && ((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
5464 class->valuetype = class->enumtype = 1;
5466 /*class->enumtype = class->parent->enumtype; */
5468 /* initialize com types if COM interfaces are present */
5470 if (MONO_CLASS_IS_IMPORT (class))
5471 init_com_from_comimport (class);
5473 class->parent = NULL;
5479 * mono_class_setup_supertypes:
5482 * Build the data structure needed to make fast type checks work.
5483 * This currently sets two fields in @class:
5484 * - idepth: distance between @class and System.Object in the type
5486 * - supertypes: array of classes: each element has a class in the hierarchy
5487 * starting from @class up to System.Object
5489 * LOCKING: This function is atomic, in case of contention we waste memory.
5492 mono_class_setup_supertypes (MonoClass *class)
5495 MonoClass **supertypes;
5497 mono_atomic_load_acquire (supertypes, void*, &class->supertypes);
5501 if (class->parent && !class->parent->supertypes)
5502 mono_class_setup_supertypes (class->parent);
5504 class->idepth = class->parent->idepth + 1;
5508 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
5509 supertypes = mono_class_alloc0 (class, sizeof (MonoClass *) * ms);
5511 if (class->parent) {
5512 supertypes [class->idepth - 1] = class;
5513 memcpy (supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
5515 supertypes [0] = class;
5518 mono_atomic_store_release (&class->supertypes, supertypes);
5522 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5524 MonoClass *gtd = (MonoClass*)user_data;
5525 /* Only try to fix generic instances of @gtd */
5526 if (gclass->generic_class->container_class != gtd)
5529 /* Check if the generic instance has no parent. */
5530 if (gtd->parent && !gclass->parent)
5531 mono_generic_class_setup_parent (gclass, gtd);
5537 mono_class_set_failure_and_error (MonoClass *class, MonoError *error, const char *msg)
5539 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5540 mono_error_set_type_load_class (error, class, msg);
5544 mono_class_set_failure_from_loader_error (MonoClass *class, MonoError *error, char *msg)
5546 MonoLoaderError *lerror = mono_loader_get_last_error ();
5549 set_failure_from_loader_error (class, lerror);
5550 mono_error_set_from_loader_error (error);
5554 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, msg);
5555 mono_error_set_type_load_class (error, class, msg);
5560 * mono_class_create_from_typedef:
5561 * @image: image where the token is valid
5562 * @type_token: typedef token
5563 * @error: used to return any error found while creating the type
5565 * Create the MonoClass* representing the specified type token.
5566 * @type_token must be a TypeDef token.
5568 * FIXME: don't return NULL on failure, just the the caller figure it out.
5571 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5573 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5574 MonoClass *class, *parent = NULL;
5575 guint32 cols [MONO_TYPEDEF_SIZE];
5576 guint32 cols_next [MONO_TYPEDEF_SIZE];
5577 guint tidx = mono_metadata_token_index (type_token);
5578 MonoGenericContext *context = NULL;
5579 const char *name, *nspace;
5581 MonoClass **interfaces;
5582 guint32 field_last, method_last;
5583 guint32 nesting_tokeen;
5585 mono_error_init (error);
5587 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5588 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5589 g_assert (!mono_loader_get_last_error ());
5593 mono_loader_lock ();
5595 if ((class = mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5596 mono_loader_unlock ();
5597 g_assert (!mono_loader_get_last_error ());
5601 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5603 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5604 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5606 class = mono_image_alloc0 (image, sizeof (MonoClass));
5609 class->name_space = nspace;
5611 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
5613 class->image = image;
5614 class->type_token = type_token;
5615 class->flags = cols [MONO_TYPEDEF_FLAGS];
5617 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), class);
5619 classes_size += sizeof (MonoClass);
5622 * Check whether we're a generic type definition.
5624 class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
5625 if (class->generic_container) {
5626 class->is_generic = 1;
5627 class->generic_container->owner.klass = class;
5628 context = &class->generic_container->context;
5631 if (class->generic_container)
5632 enable_gclass_recording ();
5634 if (cols [MONO_TYPEDEF_EXTENDS]) {
5636 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5638 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5639 /*WARNING: this must satisfy mono_metadata_type_hash*/
5640 class->this_arg.byref = 1;
5641 class->this_arg.data.klass = class;
5642 class->this_arg.type = MONO_TYPE_CLASS;
5643 class->byval_arg.data.klass = class;
5644 class->byval_arg.type = MONO_TYPE_CLASS;
5646 parent = mono_class_get_full (image, parent_token, context);
5648 if (parent == NULL) {
5649 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load parent, token is %x", parent_token));
5650 goto parent_failure;
5653 for (tmp = parent; tmp; tmp = tmp->parent) {
5655 mono_class_set_failure_and_error (class, error, "Cycle found while resolving parent");
5656 goto parent_failure;
5658 if (class->generic_container && tmp->generic_class && tmp->generic_class->container_class == class) {
5659 mono_class_set_failure_and_error (class, error, "Parent extends generic instance of this type");
5660 goto parent_failure;
5665 mono_class_setup_parent (class, parent);
5667 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5668 mono_class_setup_mono_type (class);
5670 if (class->generic_container)
5671 disable_gclass_recording (fix_gclass_incomplete_instantiation, class);
5674 * This might access class->byval_arg for recursion generated by generic constraints,
5675 * so it has to come after setup_mono_type ().
5677 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5678 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5679 if (!mono_error_ok (error)) {
5680 /*FIXME implement a mono_class_set_failure_from_mono_error */
5681 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5682 mono_loader_unlock ();
5683 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5684 g_assert (!mono_loader_get_last_error ());
5689 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5693 if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5697 class->cast_class = class->element_class = class;
5699 if (!class->enumtype) {
5700 if (!mono_metadata_interfaces_from_typedef_full (
5701 image, type_token, &interfaces, &icount, FALSE, context)){
5702 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load interfaces"));
5703 mono_loader_unlock ();
5704 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5708 class->interfaces = interfaces;
5709 class->interface_count = icount;
5710 class->interfaces_inited = 1;
5713 /*g_print ("Load class %s\n", name);*/
5716 * Compute the field and method lists
5718 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5719 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5721 if (tt->rows > tidx){
5722 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5723 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5724 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5726 field_last = image->tables [MONO_TABLE_FIELD].rows;
5727 method_last = image->tables [MONO_TABLE_METHOD].rows;
5730 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5731 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5732 class->field.count = field_last - class->field.first;
5734 class->field.count = 0;
5736 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5737 class->method.count = method_last - class->method.first;
5739 class->method.count = 0;
5741 /* reserve space to store vector pointer in arrays */
5742 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5743 class->instance_size += 2 * sizeof (gpointer);
5744 g_assert (class->field.count == 0);
5747 if (class->enumtype) {
5748 MonoType *enum_basetype = mono_class_find_enum_basetype (class);
5749 if (!enum_basetype) {
5750 /*set it to a default value as the whole runtime can't handle this to be null*/
5751 class->cast_class = class->element_class = mono_defaults.int32_class;
5752 mono_class_set_failure_and_error (class, error, "Could not enum basetype");
5753 mono_loader_unlock ();
5754 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5755 g_assert (!mono_loader_get_last_error ());
5758 class->cast_class = class->element_class = mono_class_from_mono_type (enum_basetype);
5762 * If we're a generic type definition, load the constraints.
5763 * We must do this after the class has been constructed to make certain recursive scenarios
5766 if (class->generic_container && !mono_metadata_load_generic_param_constraints_full (image, type_token, class->generic_container)){
5767 mono_class_set_failure_from_loader_error (class, error, g_strdup ("Could not load generic parameter constraints"));
5768 mono_loader_unlock ();
5769 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5770 g_assert (!mono_loader_get_last_error ());
5774 if (class->image->assembly_name && !strcmp (class->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5775 if (!strncmp (name, "Vector", 6))
5776 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");
5779 mono_loader_unlock ();
5781 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
5782 g_assert (!mono_loader_get_last_error ());
5787 mono_class_setup_mono_type (class);
5788 mono_loader_unlock ();
5789 mono_profiler_class_loaded (class, MONO_PROFILE_FAILED);
5790 g_assert (!mono_loader_get_last_error ());
5794 /** is klass Nullable<T>? */
5796 mono_class_is_nullable (MonoClass *klass)
5798 return klass->generic_class != NULL &&
5799 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5803 /** if klass is T? return T */
5805 mono_class_get_nullable_param (MonoClass *klass)
5807 g_assert (mono_class_is_nullable (klass));
5808 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5812 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5816 MonoGenericClass *gclass = klass->generic_class;
5818 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5819 if (!mono_error_ok (&error)) {
5820 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5821 klass->parent = mono_defaults.object_class;
5822 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5823 mono_error_cleanup (&error);
5827 mono_class_setup_parent (klass, klass->parent);
5829 if (klass->enumtype) {
5830 klass->cast_class = gtd->cast_class;
5831 klass->element_class = gtd->element_class;
5837 * Create the `MonoClass' for an instantiation of a generic type.
5838 * We only do this if we actually need it.
5841 mono_generic_class_get_class (MonoGenericClass *gclass)
5843 MonoClass *klass, *gklass;
5845 if (gclass->cached_class)
5846 return gclass->cached_class;
5848 mono_loader_lock ();
5849 if (gclass->cached_class) {
5850 mono_loader_unlock ();
5851 return gclass->cached_class;
5854 klass = mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
5856 gklass = gclass->container_class;
5858 if (record_gclass_instantiation > 0)
5859 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5861 if (gklass->nested_in) {
5862 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5863 klass->nested_in = gklass->nested_in;
5866 klass->name = gklass->name;
5867 klass->name_space = gklass->name_space;
5869 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5871 klass->image = gklass->image;
5872 klass->flags = gklass->flags;
5873 klass->type_token = gklass->type_token;
5874 klass->field.count = gklass->field.count;
5876 klass->is_inflated = 1;
5877 klass->generic_class = gclass;
5879 klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
5880 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5881 klass->this_arg.byref = TRUE;
5882 klass->enumtype = gklass->enumtype;
5883 klass->valuetype = gklass->valuetype;
5885 klass->cast_class = klass->element_class = klass;
5887 if (mono_class_is_nullable (klass))
5888 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5891 * We're not interested in the nested classes of a generic instance.
5892 * We use the generic type definition to look for nested classes.
5895 mono_generic_class_setup_parent (klass, gklass);
5897 if (gclass->is_dynamic) {
5900 mono_class_setup_supertypes (klass);
5902 if (klass->enumtype) {
5904 * For enums, gklass->fields might not been set, but instance_size etc. is
5905 * already set in mono_reflection_create_internal_class (). For non-enums,
5906 * these will be computed normally in mono_class_layout_fields ().
5908 klass->instance_size = gklass->instance_size;
5909 klass->sizes.class_size = gklass->sizes.class_size;
5910 mono_memory_barrier ();
5911 klass->size_inited = 1;
5915 mono_memory_barrier ();
5916 gclass->cached_class = klass;
5918 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5920 inflated_classes ++;
5921 inflated_classes_size += sizeof (MonoClass);
5923 mono_loader_unlock ();
5929 make_generic_param_class (MonoGenericParam *param, MonoImage *image, gboolean is_mvar, MonoGenericParamInfo *pinfo)
5931 MonoClass *klass, **ptr;
5933 MonoGenericContainer *container = mono_generic_param_owner (param);
5937 image = mono_defaults.corlib;
5939 klass = mono_image_alloc0 (image, sizeof (MonoClass));
5940 classes_size += sizeof (MonoClass);
5943 klass->name = pinfo->name;
5945 int n = mono_generic_param_num (param);
5946 klass->name = mono_image_alloc0 (image, 16);
5947 sprintf ((char*)klass->name, "%d", n);
5952 MonoMethod *omethod = container->owner.method;
5953 klass->name_space = (omethod && omethod->klass) ? omethod->klass->name_space : "";
5955 MonoClass *oklass = container->owner.klass;
5956 klass->name_space = oklass ? oklass->name_space : "";
5959 klass->name_space = "";
5962 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5966 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
5970 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
5971 klass->parent = pinfo->constraints [0];
5973 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
5974 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
5976 klass->parent = mono_defaults.object_class;
5979 if (count - pos > 0) {
5980 klass->interface_count = count - pos;
5981 klass->interfaces = mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos));
5982 klass->interfaces_inited = TRUE;
5983 for (i = pos; i < count; i++)
5984 klass->interfaces [i - pos] = pinfo->constraints [i];
5987 klass->image = image;
5989 klass->inited = TRUE;
5990 klass->cast_class = klass->element_class = klass;
5991 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
5993 klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
5994 klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
5995 klass->this_arg.byref = TRUE;
5997 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
5998 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6000 /*Init these fields to sane values*/
6001 klass->min_align = 1;
6002 klass->instance_size = sizeof (gpointer);
6003 mono_memory_barrier ();
6004 klass->size_inited = 1;
6006 mono_class_setup_supertypes (klass);
6008 if (count - pos > 0) {
6009 mono_class_setup_vtable (klass->parent);
6010 if (klass->parent->exception_type)
6011 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6013 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6019 #define FAST_CACHE_SIZE 16
6022 get_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar)
6024 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6025 MonoImage *image = param->image;
6030 if (n < FAST_CACHE_SIZE) {
6032 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6034 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6036 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6037 return ht ? g_hash_table_lookup (ht, GINT_TO_POINTER (n)) : NULL;
6042 * LOCKING: Acquires the loader lock.
6045 set_anon_gparam_class (MonoGenericParam *param, gboolean is_mvar, MonoClass *klass)
6047 int n = mono_generic_param_num (param) | ((guint32)param->serial << 16);
6048 MonoImage *image = param->image;
6053 if (n < FAST_CACHE_SIZE) {
6055 /* No locking needed */
6056 if (!image->mvar_cache_fast)
6057 image->mvar_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6058 image->mvar_cache_fast [n] = klass;
6060 if (!image->var_cache_fast)
6061 image->var_cache_fast = mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6062 image->var_cache_fast [n] = klass;
6066 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6068 mono_loader_lock ();
6069 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6071 ht = g_hash_table_new (NULL, NULL);
6072 mono_memory_barrier ();
6074 image->mvar_cache_slow = ht;
6076 image->var_cache_slow = ht;
6078 mono_loader_unlock ();
6081 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6085 * LOCKING: Acquires the loader lock.
6088 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
6090 MonoGenericContainer *container = mono_generic_param_owner (param);
6091 MonoGenericParamInfo *pinfo;
6094 mono_loader_lock ();
6097 pinfo = mono_generic_param_info (param);
6098 if (pinfo->pklass) {
6099 mono_loader_unlock ();
6100 return pinfo->pklass;
6106 klass = get_anon_gparam_class (param, is_mvar);
6108 mono_loader_unlock ();
6113 if (!image && container) {
6115 MonoMethod *method = container->owner.method;
6116 image = (method && method->klass) ? method->klass->image : NULL;
6118 MonoClass *klass = container->owner.klass;
6119 // FIXME: 'klass' should not be null
6120 // But, monodis creates GenericContainers without associating a owner to it
6121 image = klass ? klass->image : NULL;
6125 klass = make_generic_param_class (param, image, is_mvar, pinfo);
6127 mono_memory_barrier ();
6130 pinfo->pklass = klass;
6132 set_anon_gparam_class (param, is_mvar, klass);
6134 mono_loader_unlock ();
6136 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6137 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6143 mono_ptr_class_get (MonoType *type)
6146 MonoClass *el_class;
6150 el_class = mono_class_from_mono_type (type);
6151 image = el_class->image;
6153 mono_loader_lock ();
6155 if (!image->ptr_cache)
6156 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6158 if ((result = g_hash_table_lookup (image->ptr_cache, el_class))) {
6159 mono_loader_unlock ();
6162 result = mono_image_alloc0 (image, sizeof (MonoClass));
6164 classes_size += sizeof (MonoClass);
6166 result->parent = NULL; /* no parent for PTR types */
6167 result->name_space = el_class->name_space;
6168 name = g_strdup_printf ("%s*", el_class->name);
6169 result->name = mono_image_strdup (image, name);
6172 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6174 result->image = el_class->image;
6175 result->inited = TRUE;
6176 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6177 /* Can pointers get boxed? */
6178 result->instance_size = sizeof (gpointer);
6179 result->cast_class = result->element_class = el_class;
6180 result->blittable = TRUE;
6182 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
6183 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6184 result->this_arg.byref = TRUE;
6186 mono_class_setup_supertypes (result);
6188 g_hash_table_insert (image->ptr_cache, el_class, result);
6190 mono_loader_unlock ();
6192 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6198 mono_fnptr_class_get (MonoMethodSignature *sig)
6201 static GHashTable *ptr_hash = NULL;
6203 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6205 mono_loader_lock ();
6208 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6210 if ((result = g_hash_table_lookup (ptr_hash, sig))) {
6211 mono_loader_unlock ();
6214 result = g_new0 (MonoClass, 1);
6216 result->parent = NULL; /* no parent for PTR types */
6217 result->name_space = "System";
6218 result->name = "MonoFNPtrFakeClass";
6220 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6222 result->image = mono_defaults.corlib; /* need to fix... */
6223 result->inited = TRUE;
6224 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6225 /* Can pointers get boxed? */
6226 result->instance_size = sizeof (gpointer);
6227 result->cast_class = result->element_class = result;
6228 result->blittable = TRUE;
6230 result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
6231 result->this_arg.data.method = result->byval_arg.data.method = sig;
6232 result->this_arg.byref = TRUE;
6233 result->blittable = TRUE;
6235 mono_class_setup_supertypes (result);
6237 g_hash_table_insert (ptr_hash, sig, result);
6239 mono_loader_unlock ();
6241 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6247 mono_class_from_mono_type (MonoType *type)
6249 switch (type->type) {
6250 case MONO_TYPE_OBJECT:
6251 return type->data.klass? type->data.klass: mono_defaults.object_class;
6252 case MONO_TYPE_VOID:
6253 return type->data.klass? type->data.klass: mono_defaults.void_class;
6254 case MONO_TYPE_BOOLEAN:
6255 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6256 case MONO_TYPE_CHAR:
6257 return type->data.klass? type->data.klass: mono_defaults.char_class;
6259 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6261 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6263 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6265 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6267 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6269 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6271 return type->data.klass? type->data.klass: mono_defaults.int_class;
6273 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6275 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6277 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6279 return type->data.klass? type->data.klass: mono_defaults.single_class;
6281 return type->data.klass? type->data.klass: mono_defaults.double_class;
6282 case MONO_TYPE_STRING:
6283 return type->data.klass? type->data.klass: mono_defaults.string_class;
6284 case MONO_TYPE_TYPEDBYREF:
6285 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6286 case MONO_TYPE_ARRAY:
6287 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6289 return mono_ptr_class_get (type->data.type);
6290 case MONO_TYPE_FNPTR:
6291 return mono_fnptr_class_get (type->data.method);
6292 case MONO_TYPE_SZARRAY:
6293 return mono_array_class_get (type->data.klass, 1);
6294 case MONO_TYPE_CLASS:
6295 case MONO_TYPE_VALUETYPE:
6296 return type->data.klass;
6297 case MONO_TYPE_GENERICINST:
6298 return mono_generic_class_get_class (type->data.generic_class);
6300 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
6301 case MONO_TYPE_MVAR:
6302 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
6304 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6305 g_assert_not_reached ();
6312 * mono_type_retrieve_from_typespec
6313 * @image: context where the image is created
6314 * @type_spec: typespec token
6315 * @context: the generic context used to evaluate generic instantiations in
6318 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6320 MonoType *t = mono_type_create_from_typespec (image, type_spec);
6322 mono_error_init (error);
6323 *did_inflate = FALSE;
6326 char *name = mono_class_name_from_token (image, type_spec);
6327 char *assembly = mono_assembly_name_from_token (image, type_spec);
6328 mono_error_set_type_load_name (error, name, assembly, "Could not resolve typespec token %08x", type_spec);
6332 if (context && (context->class_inst || context->method_inst)) {
6333 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6335 if (!mono_error_ok (error))
6340 *did_inflate = TRUE;
6347 * mono_class_create_from_typespec
6348 * @image: context where the image is created
6349 * @type_spec: typespec token
6350 * @context: the generic context used to evaluate generic instantiations in
6353 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6356 gboolean inflated = FALSE;
6357 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6358 if (!mono_error_ok (error))
6360 ret = mono_class_from_mono_type (t);
6362 mono_metadata_free_type (t);
6367 * mono_bounded_array_class_get:
6368 * @element_class: element class
6369 * @rank: the dimension of the array class
6370 * @bounded: whenever the array has non-zero bounds
6372 * Returns: a class object describing the array with element type @element_type and
6376 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6380 MonoClass *parent = NULL;
6381 GSList *list, *rootlist = NULL;
6384 gboolean corlib_type = FALSE;
6386 g_assert (rank <= 255);
6389 /* bounded only matters for one-dimensional arrays */
6392 image = eclass->image;
6394 if (rank == 1 && !bounded) {
6396 * This case is very frequent not just during compilation because of calls
6397 * from mono_class_from_mono_type (), mono_array_new (),
6398 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6400 EnterCriticalSection (&image->szarray_cache_lock);
6401 if (!image->szarray_cache)
6402 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6403 class = g_hash_table_lookup (image->szarray_cache, eclass);
6404 LeaveCriticalSection (&image->szarray_cache_lock);
6408 mono_loader_lock ();
6410 mono_loader_lock ();
6412 if (!image->array_cache)
6413 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6415 if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
6416 for (; list; list = list->next) {
6418 if ((class->rank == rank) && (class->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6419 mono_loader_unlock ();
6426 /* for the building corlib use System.Array from it */
6427 if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6428 parent = mono_class_from_name (image, "System", "Array");
6431 parent = mono_defaults.array_class;
6432 if (!parent->inited)
6433 mono_class_init (parent);
6436 class = mono_image_alloc0 (image, sizeof (MonoClass));
6438 class->image = image;
6439 class->name_space = eclass->name_space;
6440 nsize = strlen (eclass->name);
6441 name = g_malloc (nsize + 2 + rank + 1);
6442 memcpy (name, eclass->name, nsize);
6445 memset (name + nsize + 1, ',', rank - 1);
6447 name [nsize + rank] = '*';
6448 name [nsize + rank + bounded] = ']';
6449 name [nsize + rank + bounded + 1] = 0;
6450 class->name = mono_image_strdup (image, name);
6453 mono_profiler_class_event (class, MONO_PROFILE_START_LOAD);
6455 classes_size += sizeof (MonoClass);
6457 class->type_token = 0;
6458 /* all arrays are marked serializable and sealed, bug #42779 */
6459 class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6460 class->parent = parent;
6461 class->instance_size = mono_class_instance_size (class->parent);
6463 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6464 /*Arrays of those two types are invalid.*/
6465 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6466 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6467 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6468 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6469 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6471 /* element_size -1 is ok as this is not an instantitable type*/
6472 class->sizes.element_size = -1;
6474 class->sizes.element_size = mono_class_array_element_size (eclass);
6476 mono_class_setup_supertypes (class);
6478 if (eclass->generic_class)
6479 mono_class_init (eclass);
6480 if (!eclass->size_inited)
6481 mono_class_setup_fields (eclass);
6482 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6483 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
6485 class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6489 if (eclass->enumtype)
6490 class->cast_class = eclass->element_class;
6492 class->cast_class = eclass;
6494 switch (class->cast_class->byval_arg.type) {
6496 class->cast_class = mono_defaults.byte_class;
6499 class->cast_class = mono_defaults.int16_class;
6502 #if SIZEOF_VOID_P == 4
6506 class->cast_class = mono_defaults.int32_class;
6509 #if SIZEOF_VOID_P == 8
6513 class->cast_class = mono_defaults.int64_class;
6517 class->element_class = eclass;
6519 if ((rank > 1) || bounded) {
6520 MonoArrayType *at = mono_image_alloc0 (image, sizeof (MonoArrayType));
6521 class->byval_arg.type = MONO_TYPE_ARRAY;
6522 class->byval_arg.data.array = at;
6523 at->eklass = eclass;
6525 /* FIXME: complete.... */
6527 class->byval_arg.type = MONO_TYPE_SZARRAY;
6528 class->byval_arg.data.klass = eclass;
6530 class->this_arg = class->byval_arg;
6531 class->this_arg.byref = 1;
6536 class->generic_container = eclass->generic_container;
6538 if (rank == 1 && !bounded) {
6539 MonoClass *prev_class;
6541 EnterCriticalSection (&image->szarray_cache_lock);
6542 prev_class = g_hash_table_lookup (image->szarray_cache, eclass);
6544 /* Someone got in before us */
6547 g_hash_table_insert (image->szarray_cache, eclass, class);
6548 LeaveCriticalSection (&image->szarray_cache_lock);
6550 list = g_slist_append (rootlist, class);
6551 g_hash_table_insert (image->array_cache, eclass, list);
6554 mono_loader_unlock ();
6556 mono_profiler_class_loaded (class, MONO_PROFILE_OK);
6562 * mono_array_class_get:
6563 * @element_class: element class
6564 * @rank: the dimension of the array class
6566 * Returns: a class object describing the array with element type @element_type and
6570 mono_array_class_get (MonoClass *eclass, guint32 rank)
6572 return mono_bounded_array_class_get (eclass, rank, FALSE);
6576 * mono_class_instance_size:
6579 * Returns: the size of an object instance
6582 mono_class_instance_size (MonoClass *klass)
6584 if (!klass->size_inited)
6585 mono_class_init (klass);
6587 return klass->instance_size;
6591 * mono_class_min_align:
6594 * Returns: minimm alignment requirements
6597 mono_class_min_align (MonoClass *klass)
6599 if (!klass->size_inited)
6600 mono_class_init (klass);
6602 return klass->min_align;
6606 * mono_class_value_size:
6609 * This function is used for value types, and return the
6610 * space and the alignment to store that kind of value object.
6612 * Returns: the size of a value of kind @klass
6615 mono_class_value_size (MonoClass *klass, guint32 *align)
6619 /* fixme: check disable, because we still have external revereces to
6620 * mscorlib and Dummy Objects
6622 /*g_assert (klass->valuetype);*/
6624 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6627 *align = klass->min_align;
6633 * mono_class_data_size:
6636 * Returns: the size of the static class data
6639 mono_class_data_size (MonoClass *klass)
6642 mono_class_init (klass);
6644 /* in arrays, sizes.class_size is unioned with element_size
6645 * and arrays have no static fields
6649 return klass->sizes.class_size;
6653 * Auxiliary routine to mono_class_get_field
6655 * Takes a field index instead of a field token.
6657 static MonoClassField *
6658 mono_class_get_field_idx (MonoClass *class, int idx)
6660 mono_class_setup_fields_locking (class);
6661 if (class->exception_type)
6665 if (class->image->uncompressed_metadata) {
6667 * class->field.first points to the FieldPtr table, while idx points into the
6668 * Field table, so we have to do a search.
6670 /*FIXME this is broken for types with multiple fields with the same name.*/
6671 const char *name = mono_metadata_string_heap (class->image, mono_metadata_decode_row_col (&class->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6674 for (i = 0; i < class->field.count; ++i)
6675 if (mono_field_get_name (&class->fields [i]) == name)
6676 return &class->fields [i];
6677 g_assert_not_reached ();
6679 if (class->field.count) {
6680 if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
6681 return &class->fields [idx - class->field.first];
6685 class = class->parent;
6691 * mono_class_get_field:
6692 * @class: the class to lookup the field.
6693 * @field_token: the field token
6695 * Returns: A MonoClassField representing the type and offset of
6696 * the field, or a NULL value if the field does not belong to this
6700 mono_class_get_field (MonoClass *class, guint32 field_token)
6702 int idx = mono_metadata_token_index (field_token);
6704 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6706 return mono_class_get_field_idx (class, idx - 1);
6710 * mono_class_get_field_from_name:
6711 * @klass: the class to lookup the field.
6712 * @name: the field name
6714 * Search the class @klass and it's parents for a field with the name @name.
6716 * Returns: the MonoClassField pointer of the named field or NULL
6719 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6721 return mono_class_get_field_from_name_full (klass, name, NULL);
6725 * mono_class_get_field_from_name_full:
6726 * @klass: the class to lookup the field.
6727 * @name: the field name
6728 * @type: the type of the fields. This optional.
6730 * Search the class @klass and it's parents for a field with the name @name and type @type.
6732 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6733 * of its generic type definition.
6735 * Returns: the MonoClassField pointer of the named field or NULL
6738 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6742 mono_class_setup_fields_locking (klass);
6743 if (klass->exception_type)
6747 for (i = 0; i < klass->field.count; ++i) {
6748 MonoClassField *field = &klass->fields [i];
6750 if (strcmp (name, mono_field_get_name (field)) != 0)
6754 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6755 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6760 klass = klass->parent;
6766 * mono_class_get_field_token:
6767 * @field: the field we need the token of
6769 * Get the token of a field. Note that the tokesn is only valid for the image
6770 * the field was loaded from. Don't use this function for fields in dynamic types.
6772 * Returns: the token representing the field in the image it was loaded from.
6775 mono_class_get_field_token (MonoClassField *field)
6777 MonoClass *klass = field->parent;
6780 mono_class_setup_fields_locking (klass);
6785 for (i = 0; i < klass->field.count; ++i) {
6786 if (&klass->fields [i] == field) {
6787 int idx = klass->field.first + i + 1;
6789 if (klass->image->uncompressed_metadata)
6790 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6791 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6794 klass = klass->parent;
6797 g_assert_not_reached ();
6802 mono_field_get_index (MonoClassField *field)
6804 int index = field - field->parent->fields;
6806 g_assert (index >= 0 && index < field->parent->field.count);
6812 * mono_class_get_field_default_value:
6814 * Return the default value of the field as a pointer into the metadata blob.
6817 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6820 guint32 constant_cols [MONO_CONSTANT_SIZE];
6822 MonoClass *klass = field->parent;
6824 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6826 if (!klass->ext || !klass->ext->field_def_values) {
6827 mono_loader_lock ();
6828 mono_class_alloc_ext (klass);
6829 if (!klass->ext->field_def_values)
6830 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
6831 mono_loader_unlock ();
6834 field_index = mono_field_get_index (field);
6836 if (!klass->ext->field_def_values [field_index].data) {
6837 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6841 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6843 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6844 klass->ext->field_def_values [field_index].def_type = constant_cols [MONO_CONSTANT_TYPE];
6845 klass->ext->field_def_values [field_index].data = (gpointer)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6848 *def_type = klass->ext->field_def_values [field_index].def_type;
6849 return klass->ext->field_def_values [field_index].data;
6853 mono_property_get_index (MonoProperty *prop)
6855 int index = prop - prop->parent->ext->properties;
6857 g_assert (index >= 0 && index < prop->parent->ext->property.count);
6863 * mono_class_get_property_default_value:
6865 * Return the default value of the field as a pointer into the metadata blob.
6868 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
6871 guint32 constant_cols [MONO_CONSTANT_SIZE];
6872 MonoClass *klass = property->parent;
6874 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
6876 * We don't cache here because it is not used by C# so it's quite rare, but
6877 * we still do the lookup in klass->ext because that is where the data
6878 * is stored for dynamic assemblies.
6881 if (klass->image->dynamic) {
6882 int prop_index = mono_property_get_index (property);
6883 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
6884 *def_type = klass->ext->prop_def_values [prop_index].def_type;
6885 return klass->ext->prop_def_values [prop_index].data;
6889 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
6893 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6894 *def_type = constant_cols [MONO_CONSTANT_TYPE];
6895 return (gpointer)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
6899 mono_class_get_event_token (MonoEvent *event)
6901 MonoClass *klass = event->parent;
6906 for (i = 0; i < klass->ext->event.count; ++i) {
6907 if (&klass->ext->events [i] == event)
6908 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
6911 klass = klass->parent;
6914 g_assert_not_reached ();
6919 mono_class_get_property_from_name (MonoClass *klass, const char *name)
6923 gpointer iter = NULL;
6924 while ((p = mono_class_get_properties (klass, &iter))) {
6925 if (! strcmp (name, p->name))
6928 klass = klass->parent;
6934 mono_class_get_property_token (MonoProperty *prop)
6936 MonoClass *klass = prop->parent;
6940 gpointer iter = NULL;
6941 while ((p = mono_class_get_properties (klass, &iter))) {
6942 if (&klass->ext->properties [i] == prop)
6943 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
6947 klass = klass->parent;
6950 g_assert_not_reached ();
6955 mono_class_name_from_token (MonoImage *image, guint32 type_token)
6957 const char *name, *nspace;
6959 return g_strdup_printf ("DynamicType 0x%08x", type_token);
6961 switch (type_token & 0xff000000){
6962 case MONO_TOKEN_TYPE_DEF: {
6963 guint32 cols [MONO_TYPEDEF_SIZE];
6964 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
6965 guint tidx = mono_metadata_token_index (type_token);
6967 if (tidx > tt->rows)
6968 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6970 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
6971 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
6972 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
6973 if (strlen (nspace) == 0)
6974 return g_strdup_printf ("%s", name);
6976 return g_strdup_printf ("%s.%s", nspace, name);
6979 case MONO_TOKEN_TYPE_REF: {
6981 guint32 cols [MONO_TYPEREF_SIZE];
6982 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
6983 guint tidx = mono_metadata_token_index (type_token);
6986 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
6988 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
6989 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
6990 mono_error_cleanup (&error);
6994 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
6995 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
6996 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
6997 if (strlen (nspace) == 0)
6998 return g_strdup_printf ("%s", name);
7000 return g_strdup_printf ("%s.%s", nspace, name);
7003 case MONO_TOKEN_TYPE_SPEC:
7004 return g_strdup_printf ("Typespec 0x%08x", type_token);
7006 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7011 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7014 return g_strdup_printf ("DynamicAssembly %s", image->name);
7016 switch (type_token & 0xff000000){
7017 case MONO_TOKEN_TYPE_DEF:
7018 if (image->assembly)
7019 return mono_stringify_assembly_name (&image->assembly->aname);
7020 else if (image->assembly_name)
7021 return g_strdup (image->assembly_name);
7022 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7023 case MONO_TOKEN_TYPE_REF: {
7025 MonoAssemblyName aname;
7026 guint32 cols [MONO_TYPEREF_SIZE];
7027 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7028 guint32 idx = mono_metadata_token_index (type_token);
7031 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7033 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7034 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7035 mono_error_cleanup (&error);
7038 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7040 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
7041 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
7042 case MONO_RESOLTION_SCOPE_MODULE:
7044 return g_strdup ("");
7045 case MONO_RESOLTION_SCOPE_MODULEREF:
7047 return g_strdup ("");
7048 case MONO_RESOLTION_SCOPE_TYPEREF:
7050 return g_strdup ("");
7051 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
7052 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7053 return mono_stringify_assembly_name (&aname);
7055 g_assert_not_reached ();
7059 case MONO_TOKEN_TYPE_SPEC:
7061 return g_strdup ("");
7063 g_assert_not_reached ();
7070 * mono_class_get_full:
7071 * @image: the image where the class resides
7072 * @type_token: the token for the class
7073 * @context: the generic context used to evaluate generic instantiations in
7075 * Returns: the MonoClass that represents @type_token in @image
7078 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7081 MonoClass *class = NULL;
7083 if (image->dynamic) {
7084 int table = mono_metadata_token_table (type_token);
7086 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7087 mono_loader_set_error_bad_image (g_strdup ("Bad type token."));
7090 return mono_lookup_dynamic_token (image, type_token, context);
7093 switch (type_token & 0xff000000){
7094 case MONO_TOKEN_TYPE_DEF:
7095 class = mono_class_create_from_typedef (image, type_token, &error);
7096 if (!mono_error_ok (&error)) {
7097 mono_loader_set_error_from_mono_error (&error);
7098 /*FIXME don't swallow the error message*/
7099 mono_error_cleanup (&error);
7103 case MONO_TOKEN_TYPE_REF:
7104 class = mono_class_from_typeref (image, type_token);
7106 case MONO_TOKEN_TYPE_SPEC:
7107 class = mono_class_create_from_typespec (image, type_token, context, &error);
7108 if (!mono_error_ok (&error)) {
7109 /*FIXME don't swallow the error message*/
7110 mono_error_cleanup (&error);
7114 g_warning ("unknown token type %x", type_token & 0xff000000);
7115 g_assert_not_reached ();
7119 char *name = mono_class_name_from_token (image, type_token);
7120 char *assembly = mono_assembly_name_from_token (image, type_token);
7121 mono_loader_set_error_type_load (name, assembly);
7131 * mono_type_get_full:
7132 * @image: the image where the type resides
7133 * @type_token: the token for the type
7134 * @context: the generic context used to evaluate generic instantiations in
7136 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7138 * Returns: the MonoType that represents @type_token in @image
7141 mono_type_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7144 MonoType *type = NULL;
7145 gboolean inflated = FALSE;
7147 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7149 return mono_class_get_type (mono_lookup_dynamic_token (image, type_token, context));
7151 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7152 MonoClass *class = mono_class_get_full (image, type_token, context);
7153 return class ? mono_class_get_type (class) : NULL;
7156 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, &error);
7158 if (!mono_error_ok (&error)) {
7159 /*FIXME don't swalloc the error message.*/
7160 char *name = mono_class_name_from_token (image, type_token);
7161 char *assembly = mono_assembly_name_from_token (image, type_token);
7163 g_warning ("Error loading type %s from %s due to %s", name, assembly, mono_error_get_message (&error));
7165 mono_error_cleanup (&error);
7166 mono_loader_set_error_type_load (name, assembly);
7171 MonoType *tmp = type;
7172 type = mono_class_get_type (mono_class_from_mono_type (type));
7173 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7174 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7175 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7177 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7179 if (type->type != tmp->type)
7182 mono_metadata_free_type (tmp);
7189 mono_class_get (MonoImage *image, guint32 type_token)
7191 return mono_class_get_full (image, type_token, NULL);
7195 * mono_image_init_name_cache:
7197 * Initializes the class name cache stored in image->name_cache.
7199 * LOCKING: Acquires the corresponding image lock.
7202 mono_image_init_name_cache (MonoImage *image)
7204 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7205 guint32 cols [MONO_TYPEDEF_SIZE];
7208 guint32 i, visib, nspace_index;
7209 GHashTable *name_cache2, *nspace_table;
7211 mono_image_lock (image);
7213 if (image->name_cache) {
7214 mono_image_unlock (image);
7218 image->name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7220 if (image->dynamic) {
7221 mono_image_unlock (image);
7225 /* Temporary hash table to avoid lookups in the nspace_table */
7226 name_cache2 = g_hash_table_new (NULL, NULL);
7228 for (i = 1; i <= t->rows; ++i) {
7229 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7230 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7232 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7233 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7235 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7237 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7238 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7240 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7241 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7242 if (!nspace_table) {
7243 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7244 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7245 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7248 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7251 /* Load type names from EXPORTEDTYPES table */
7253 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7254 guint32 cols [MONO_EXP_TYPE_SIZE];
7257 for (i = 0; i < t->rows; ++i) {
7258 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7259 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7260 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7262 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7263 nspace_table = g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7264 if (!nspace_table) {
7265 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7266 g_hash_table_insert (image->name_cache, (char*)nspace, nspace_table);
7267 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7270 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7274 g_hash_table_destroy (name_cache2);
7275 mono_image_unlock (image);
7278 /*FIXME Only dynamic assemblies should allow this operation.*/
7280 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7281 const char *name, guint32 index)
7283 GHashTable *nspace_table;
7284 GHashTable *name_cache;
7287 mono_image_lock (image);
7289 if (!image->name_cache)
7290 mono_image_init_name_cache (image);
7292 name_cache = image->name_cache;
7293 if (!(nspace_table = g_hash_table_lookup (name_cache, nspace))) {
7294 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7295 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7298 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7299 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7301 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7303 mono_image_unlock (image);
7312 find_nocase (gpointer key, gpointer value, gpointer user_data)
7314 char *name = (char*)key;
7315 FindUserData *data = (FindUserData*)user_data;
7317 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7318 data->value = value;
7322 * mono_class_from_name_case:
7323 * @image: The MonoImage where the type is looked up in
7324 * @name_space: the type namespace
7325 * @name: the type short name.
7327 * Obtains a MonoClass with a given namespace and a given name which
7328 * is located in the given MonoImage. The namespace and name
7329 * lookups are case insensitive.
7332 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7334 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7335 guint32 cols [MONO_TYPEDEF_SIZE];
7340 if (image->dynamic) {
7342 FindUserData user_data;
7344 mono_image_lock (image);
7346 if (!image->name_cache)
7347 mono_image_init_name_cache (image);
7349 user_data.key = name_space;
7350 user_data.value = NULL;
7351 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7353 if (user_data.value) {
7354 GHashTable *nspace_table = (GHashTable*)user_data.value;
7356 user_data.key = name;
7357 user_data.value = NULL;
7359 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7361 if (user_data.value)
7362 token = GPOINTER_TO_UINT (user_data.value);
7365 mono_image_unlock (image);
7368 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
7374 /* add a cache if needed */
7375 for (i = 1; i <= t->rows; ++i) {
7376 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7377 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7379 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7380 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7382 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7384 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7385 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7386 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7387 return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
7393 return_nested_in (MonoClass *class, char *nested)
7396 char *s = strchr (nested, '/');
7397 gpointer iter = NULL;
7404 while ((found = mono_class_get_nested_types (class, &iter))) {
7405 if (strcmp (found->name, nested) == 0) {
7407 return return_nested_in (found, s);
7415 search_modules (MonoImage *image, const char *name_space, const char *name)
7417 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7418 MonoImage *file_image;
7423 * The EXPORTEDTYPES table only contains public types, so have to search the
7425 * Note: image->modules contains the contents of the MODULEREF table, while
7426 * the real module list is in the FILE table.
7428 for (i = 0; i < file_table->rows; i++) {
7429 guint32 cols [MONO_FILE_SIZE];
7430 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7431 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7434 file_image = mono_image_load_file_for_image (image, i + 1);
7436 class = mono_class_from_name (file_image, name_space, name);
7446 * mono_class_from_name:
7447 * @image: The MonoImage where the type is looked up in
7448 * @name_space: the type namespace
7449 * @name: the type short name.
7451 * Obtains a MonoClass with a given namespace and a given name which
7452 * is located in the given MonoImage.
7454 * To reference nested classes, use the "/" character as a separator.
7455 * For example use "Foo/Bar" to reference the class Bar that is nested
7456 * inside Foo, like this: "class Foo { class Bar {} }".
7459 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7461 GHashTable *nspace_table;
7462 MonoImage *loaded_image;
7469 if ((nested = strchr (name, '/'))) {
7470 int pos = nested - name;
7471 int len = strlen (name);
7474 memcpy (buf, name, len + 1);
7476 nested = buf + pos + 1;
7480 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7481 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7482 gboolean res = get_class_from_name (image, name_space, name, &class);
7485 class = search_modules (image, name_space, name);
7487 return class ? return_nested_in (class, nested) : NULL;
7493 mono_image_lock (image);
7495 if (!image->name_cache)
7496 mono_image_init_name_cache (image);
7498 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
7501 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7503 mono_image_unlock (image);
7505 if (!token && image->dynamic && image->modules) {
7506 /* Search modules as well */
7507 for (i = 0; i < image->module_count; ++i) {
7508 MonoImage *module = image->modules [i];
7510 class = mono_class_from_name (module, name_space, name);
7517 class = search_modules (image, name_space, name);
7525 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7526 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7527 guint32 cols [MONO_EXP_TYPE_SIZE];
7530 idx = mono_metadata_token_index (token);
7532 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7534 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7535 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7536 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7539 class = mono_class_from_name (loaded_image, name_space, name);
7541 return return_nested_in (class, nested);
7543 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7544 guint32 assembly_idx;
7546 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7548 mono_assembly_load_reference (image, assembly_idx - 1);
7549 g_assert (image->references [assembly_idx - 1]);
7550 if (image->references [assembly_idx - 1] == (gpointer)-1)
7553 /* FIXME: Cycle detection */
7554 return mono_class_from_name (image->references [assembly_idx - 1]->image, name_space, name);
7556 g_error ("not yet implemented");
7560 token = MONO_TOKEN_TYPE_DEF | token;
7562 class = mono_class_get (image, token);
7564 return return_nested_in (class, nested);
7569 * mono_class_is_subclass_of:
7570 * @klass: class to probe if it is a subclass of another one
7571 * @klassc: the class we suspect is the base class
7572 * @check_interfaces: whether we should perform interface checks
7574 * This method determines whether @klass is a subclass of @klassc.
7576 * If the @check_interfaces flag is set, then if @klassc is an interface
7577 * this method return true if the @klass implements the interface or
7578 * if @klass is an interface, if one of its base classes is @klass.
7580 * If @check_interfaces is false then, then if @klass is not an interface
7581 * then it returns true if the @klass is a subclass of @klassc.
7583 * if @klass is an interface and @klassc is System.Object, then this function
7588 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
7589 gboolean check_interfaces)
7591 /*FIXME test for interfaces with variant generic arguments*/
7593 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7594 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7596 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7599 for (i = 0; i < klass->interface_count; i ++) {
7600 MonoClass *ic = klass->interfaces [i];
7605 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7610 * MS.NET thinks interfaces are a subclass of Object, so we think it as
7613 if (klassc == mono_defaults.object_class)
7620 mono_type_is_generic_argument (MonoType *type)
7622 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7626 mono_class_has_variant_generic_params (MonoClass *klass)
7629 MonoGenericContainer *container;
7631 if (!klass->generic_class)
7634 container = klass->generic_class->container_class->generic_container;
7636 for (i = 0; i < container->type_argc; ++i)
7637 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7644 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7646 if (target == candidate)
7649 if (check_for_reference_conv &&
7650 mono_type_is_generic_argument (&target->byval_arg) &&
7651 mono_type_is_generic_argument (&candidate->byval_arg)) {
7652 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7653 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7655 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7658 if (!mono_class_is_assignable_from (target, candidate))
7664 * @container the generic container from the GTD
7665 * @klass: the class to be assigned to
7666 * @oklass: the source class
7668 * Both klass and oklass must be instances of the same generic interface.
7669 * Return true if @klass can be assigned to a @klass variable
7672 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
7675 MonoType **klass_argv, **oklass_argv;
7676 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7677 MonoGenericContainer *container = klass_gtd->generic_container;
7679 if (klass == oklass)
7682 /*Viable candidates are instances of the same generic interface*/
7683 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7686 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7687 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7689 for (j = 0; j < container->type_argc; ++j) {
7690 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7691 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7693 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
7697 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7698 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7700 if (param1_class != param2_class) {
7701 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7702 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
7704 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7705 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
7715 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
7717 MonoGenericParam *gparam, *ogparam;
7718 MonoGenericParamInfo *tinfo, *cinfo;
7719 MonoClass **candidate_class;
7720 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
7723 if (target == candidate)
7725 if (target->byval_arg.type != candidate->byval_arg.type)
7728 gparam = target->byval_arg.data.generic_param;
7729 ogparam = candidate->byval_arg.data.generic_param;
7730 tinfo = mono_generic_param_info (gparam);
7731 cinfo = mono_generic_param_info (ogparam);
7733 class_constraint_satisfied = FALSE;
7734 valuetype_constraint_satisfied = FALSE;
7736 /*candidate must have a super set of target's special constraints*/
7737 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7738 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
7740 if (cinfo->constraints) {
7741 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7742 MonoClass *cc = *candidate_class;
7744 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7745 class_constraint_satisfied = TRUE;
7746 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
7747 valuetype_constraint_satisfied = TRUE;
7750 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
7751 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
7753 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
7755 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
7757 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
7758 valuetype_constraint_satisfied)) {
7763 /*candidate type constraints must be a superset of target's*/
7764 if (tinfo->constraints) {
7765 MonoClass **target_class;
7766 for (target_class = tinfo->constraints; *target_class; ++target_class) {
7767 MonoClass *tc = *target_class;
7770 * A constraint from @target might inflate into @candidate itself and in that case we don't need
7771 * check it's constraints since it satisfy the constraint by itself.
7773 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
7776 if (!cinfo->constraints)
7779 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7780 MonoClass *cc = *candidate_class;
7782 if (mono_class_is_assignable_from (tc, cc))
7786 * This happens when we have the following:
7788 * Bar<K> where K : IFace
7789 * Foo<T, U> where T : U where U : IFace
7791 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
7794 if (mono_type_is_generic_argument (&cc->byval_arg)) {
7795 if (mono_gparam_is_assignable_from (target, cc))
7799 if (!*candidate_class)
7804 /*candidate itself must have a constraint that satisfy target*/
7805 if (cinfo->constraints) {
7806 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
7807 MonoClass *cc = *candidate_class;
7808 if (mono_class_is_assignable_from (target, cc))
7816 * mono_class_is_assignable_from:
7817 * @klass: the class to be assigned to
7818 * @oklass: the source class
7820 * Return: true if an instance of object oklass can be assigned to an
7821 * instance of object @klass
7824 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
7826 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
7828 mono_class_init (klass);
7830 if (!oklass->inited)
7831 mono_class_init (oklass);
7833 if (klass->exception_type || oklass->exception_type)
7836 if (mono_type_is_generic_argument (&klass->byval_arg)) {
7837 if (!mono_type_is_generic_argument (&oklass->byval_arg))
7839 return mono_gparam_is_assignable_from (klass, oklass);
7842 if (MONO_CLASS_IS_INTERFACE (klass)) {
7843 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
7844 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
7845 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
7849 for (i = 0; constraints [i]; ++i) {
7850 if (mono_class_is_assignable_from (klass, constraints [i]))
7858 /* interface_offsets might not be set for dynamic classes */
7859 if (oklass->ref_info_handle && !oklass->interface_bitmap)
7861 * oklass might be a generic type parameter but they have
7862 * interface_offsets set.
7864 return mono_reflection_call_is_assignable_to (oklass, klass);
7865 if (!oklass->interface_bitmap)
7866 /* Happens with generic instances of not-yet created dynamic types */
7868 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
7871 if (mono_class_has_variant_generic_params (klass)) {
7874 mono_class_setup_interfaces (oklass, &error);
7875 if (!mono_error_ok (&error)) {
7876 mono_error_cleanup (&error);
7880 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
7881 for (i = 0; i < oklass->interface_offsets_count; ++i) {
7882 MonoClass *iface = oklass->interfaces_packed [i];
7884 if (mono_class_is_variant_compatible (klass, iface, FALSE))
7889 } else if (klass->delegate) {
7890 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
7892 }else if (klass->rank) {
7893 MonoClass *eclass, *eoclass;
7895 if (oklass->rank != klass->rank)
7898 /* vectors vs. one dimensional arrays */
7899 if (oklass->byval_arg.type != klass->byval_arg.type)
7902 eclass = klass->cast_class;
7903 eoclass = oklass->cast_class;
7906 * a is b does not imply a[] is b[] when a is a valuetype, and
7907 * b is a reference type.
7910 if (eoclass->valuetype) {
7911 if ((eclass == mono_defaults.enum_class) ||
7912 (eclass == mono_defaults.enum_class->parent) ||
7913 (eclass == mono_defaults.object_class))
7917 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7918 } else if (mono_class_is_nullable (klass)) {
7919 if (mono_class_is_nullable (oklass))
7920 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
7922 return mono_class_is_assignable_from (klass->cast_class, oklass);
7923 } else if (klass == mono_defaults.object_class)
7926 return mono_class_has_parent (oklass, klass);
7929 /*Check if @oklass is variant compatible with @klass.*/
7931 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
7934 MonoType **klass_argv, **oklass_argv;
7935 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
7936 MonoGenericContainer *container = klass_gtd->generic_container;
7938 /*Viable candidates are instances of the same generic interface*/
7939 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
7942 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
7943 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
7945 for (j = 0; j < container->type_argc; ++j) {
7946 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
7947 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
7949 if (param1_class->valuetype != param2_class->valuetype)
7953 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
7954 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
7956 if (param1_class != param2_class) {
7957 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
7958 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
7960 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
7961 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
7969 /*Check if @candidate implements the interface @target*/
7971 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
7975 gboolean is_variant = mono_class_has_variant_generic_params (target);
7977 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
7978 if (mono_class_is_variant_compatible_slow (target, candidate))
7983 if (candidate == target)
7986 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
7987 if (candidate->image->dynamic && !candidate->wastypebuilder) {
7988 MonoReflectionTypeBuilder *tb = mono_class_get_ref_info (candidate);
7990 if (tb && tb->interfaces) {
7991 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
7992 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
7993 MonoClass *iface_class;
7995 /* we can't realize the type here since it can do pretty much anything. */
7998 iface_class = mono_class_from_mono_type (iface->type);
7999 if (iface_class == target)
8001 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8003 if (mono_class_implement_interface_slow (target, iface_class))
8008 /*setup_interfaces don't mono_class_init anything*/
8009 mono_class_setup_interfaces (candidate, &error);
8010 if (!mono_error_ok (&error)) {
8011 mono_error_cleanup (&error);
8015 for (i = 0; i < candidate->interface_count; ++i) {
8016 if (candidate->interfaces [i] == target)
8019 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8022 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8026 candidate = candidate->parent;
8027 } while (candidate);
8033 * Check if @oklass can be assigned to @klass.
8034 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8037 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8039 if (candidate == target)
8041 if (target == mono_defaults.object_class)
8044 if (mono_class_has_parent (candidate, target))
8047 /*If target is not an interface there is no need to check them.*/
8048 if (MONO_CLASS_IS_INTERFACE (target))
8049 return mono_class_implement_interface_slow (target, candidate);
8051 if (target->delegate && mono_class_has_variant_generic_params (target))
8052 return mono_class_is_variant_compatible (target, candidate, FALSE);
8054 /*FIXME properly handle nullables and arrays */
8055 /*FIXME properly handle (M)VAR */
8060 * mono_class_get_cctor:
8061 * @klass: A MonoClass pointer
8063 * Returns: the static constructor of @klass if it exists, NULL otherwise.
8066 mono_class_get_cctor (MonoClass *klass)
8068 MonoCachedClassInfo cached_info;
8070 if (klass->image->dynamic) {
8072 * has_cctor is not set for these classes because mono_class_init () is
8075 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8078 if (!klass->has_cctor)
8081 if (mono_class_get_cached_class_info (klass, &cached_info))
8082 return mono_get_method (klass->image, cached_info.cctor_token, klass);
8084 if (klass->generic_class && !klass->methods)
8085 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8087 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8091 * mono_class_get_finalizer:
8092 * @klass: The MonoClass pointer
8094 * Returns: the finalizer method of @klass if it exists, NULL otherwise.
8097 mono_class_get_finalizer (MonoClass *klass)
8099 MonoCachedClassInfo cached_info;
8102 mono_class_init (klass);
8103 if (!mono_class_has_finalizer (klass))
8106 if (mono_class_get_cached_class_info (klass, &cached_info))
8107 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
8109 mono_class_setup_vtable (klass);
8110 return klass->vtable [finalize_slot];
8115 * mono_class_needs_cctor_run:
8116 * @klass: the MonoClass pointer
8117 * @caller: a MonoMethod describing the caller
8119 * Determines whenever the class has a static constructor and whenever it
8120 * needs to be called when executing CALLER.
8123 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8127 method = mono_class_get_cctor (klass);
8129 return (method == caller) ? FALSE : TRUE;
8135 * mono_class_array_element_size:
8138 * Returns: the number of bytes an element of type @klass
8139 * uses when stored into an array.
8142 mono_class_array_element_size (MonoClass *klass)
8144 MonoType *type = &klass->byval_arg;
8147 switch (type->type) {
8150 case MONO_TYPE_BOOLEAN:
8154 case MONO_TYPE_CHAR:
8163 case MONO_TYPE_CLASS:
8164 case MONO_TYPE_STRING:
8165 case MONO_TYPE_OBJECT:
8166 case MONO_TYPE_SZARRAY:
8167 case MONO_TYPE_ARRAY:
8169 case MONO_TYPE_MVAR:
8170 return sizeof (gpointer);
8175 case MONO_TYPE_VALUETYPE:
8176 if (type->data.klass->enumtype) {
8177 type = mono_class_enum_basetype (type->data.klass);
8178 klass = klass->element_class;
8181 return mono_class_instance_size (klass) - sizeof (MonoObject);
8182 case MONO_TYPE_GENERICINST:
8183 type = &type->data.generic_class->container_class->byval_arg;
8186 case MONO_TYPE_VOID:
8190 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8196 * mono_array_element_size:
8197 * @ac: pointer to a #MonoArrayClass
8199 * Returns: the size of single array element.
8202 mono_array_element_size (MonoClass *ac)
8204 g_assert (ac->rank);
8205 return ac->sizes.element_size;
8209 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8210 MonoGenericContext *context)
8212 if (image->dynamic) {
8213 MonoClass *tmp_handle_class;
8214 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8216 g_assert (tmp_handle_class);
8218 *handle_class = tmp_handle_class;
8220 if (tmp_handle_class == mono_defaults.typehandle_class)
8221 return &((MonoClass*)obj)->byval_arg;
8226 switch (token & 0xff000000) {
8227 case MONO_TOKEN_TYPE_DEF:
8228 case MONO_TOKEN_TYPE_REF:
8229 case MONO_TOKEN_TYPE_SPEC: {
8232 *handle_class = mono_defaults.typehandle_class;
8233 type = mono_type_get_full (image, token, context);
8236 mono_class_init (mono_class_from_mono_type (type));
8237 /* We return a MonoType* as handle */
8240 case MONO_TOKEN_FIELD_DEF: {
8242 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8246 *handle_class = mono_defaults.fieldhandle_class;
8247 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
8250 mono_class_init (class);
8251 return mono_class_get_field (class, token);
8253 case MONO_TOKEN_METHOD_DEF:
8254 case MONO_TOKEN_METHOD_SPEC: {
8256 meth = mono_get_method_full (image, token, NULL, context);
8258 *handle_class = mono_defaults.methodhandle_class;
8261 case MONO_TOKEN_MEMBER_REF: {
8262 guint32 cols [MONO_MEMBERREF_SIZE];
8264 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8265 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8266 mono_metadata_decode_blob_size (sig, &sig);
8267 if (*sig == 0x6) { /* it's a field */
8269 MonoClassField *field;
8270 field = mono_field_from_token (image, token, &klass, context);
8272 *handle_class = mono_defaults.fieldhandle_class;
8276 meth = mono_get_method_full (image, token, NULL, context);
8278 *handle_class = mono_defaults.methodhandle_class;
8283 g_warning ("Unknown token 0x%08x in ldtoken", token);
8290 * This function might need to call runtime functions so it can't be part
8291 * of the metadata library.
8293 static MonoLookupDynamicToken lookup_dynamic = NULL;
8296 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8298 lookup_dynamic = func;
8302 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8304 MonoClass *handle_class;
8306 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8310 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8312 return lookup_dynamic (image, token, valid_token, handle_class, context);
8315 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8318 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8320 get_cached_class_info = func;
8324 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8326 if (!get_cached_class_info)
8329 return get_cached_class_info (klass, res);
8333 mono_install_get_class_from_name (MonoGetClassFromName func)
8335 get_class_from_name = func;
8339 mono_class_get_image (MonoClass *klass)
8341 return klass->image;
8345 * mono_class_get_element_class:
8346 * @klass: the MonoClass to act on
8348 * Returns: the element class of an array or an enumeration.
8351 mono_class_get_element_class (MonoClass *klass)
8353 return klass->element_class;
8357 * mono_class_is_valuetype:
8358 * @klass: the MonoClass to act on
8360 * Returns: true if the MonoClass represents a ValueType.
8363 mono_class_is_valuetype (MonoClass *klass)
8365 return klass->valuetype;
8369 * mono_class_is_enum:
8370 * @klass: the MonoClass to act on
8372 * Returns: true if the MonoClass represents an enumeration.
8375 mono_class_is_enum (MonoClass *klass)
8377 return klass->enumtype;
8381 * mono_class_enum_basetype:
8382 * @klass: the MonoClass to act on
8384 * Returns: the underlying type representation for an enumeration.
8387 mono_class_enum_basetype (MonoClass *klass)
8389 if (klass->element_class == klass)
8390 /* SRE or broken types */
8393 return &klass->element_class->byval_arg;
8397 * mono_class_get_parent
8398 * @klass: the MonoClass to act on
8400 * Returns: the parent class for this class.
8403 mono_class_get_parent (MonoClass *klass)
8405 return klass->parent;
8409 * mono_class_get_nesting_type;
8410 * @klass: the MonoClass to act on
8412 * Returns: the container type where this type is nested or NULL if this type is not a nested type.
8415 mono_class_get_nesting_type (MonoClass *klass)
8417 return klass->nested_in;
8421 * mono_class_get_rank:
8422 * @klass: the MonoClass to act on
8424 * Returns: the rank for the array (the number of dimensions).
8427 mono_class_get_rank (MonoClass *klass)
8433 * mono_class_get_flags:
8434 * @klass: the MonoClass to act on
8436 * The type flags from the TypeDef table from the metadata.
8437 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8440 * Returns: the flags from the TypeDef table.
8443 mono_class_get_flags (MonoClass *klass)
8445 return klass->flags;
8449 * mono_class_get_name
8450 * @klass: the MonoClass to act on
8452 * Returns: the name of the class.
8455 mono_class_get_name (MonoClass *klass)
8461 * mono_class_get_namespace:
8462 * @klass: the MonoClass to act on
8464 * Returns: the namespace of the class.
8467 mono_class_get_namespace (MonoClass *klass)
8469 return klass->name_space;
8473 * mono_class_get_type:
8474 * @klass: the MonoClass to act on
8476 * This method returns the internal Type representation for the class.
8478 * Returns: the MonoType from the class.
8481 mono_class_get_type (MonoClass *klass)
8483 return &klass->byval_arg;
8487 * mono_class_get_type_token
8488 * @klass: the MonoClass to act on
8490 * This method returns type token for the class.
8492 * Returns: the type token for the class.
8495 mono_class_get_type_token (MonoClass *klass)
8497 return klass->type_token;
8501 * mono_class_get_byref_type:
8502 * @klass: the MonoClass to act on
8507 mono_class_get_byref_type (MonoClass *klass)
8509 return &klass->this_arg;
8513 * mono_class_num_fields:
8514 * @klass: the MonoClass to act on
8516 * Returns: the number of static and instance fields in the class.
8519 mono_class_num_fields (MonoClass *klass)
8521 return klass->field.count;
8525 * mono_class_num_methods:
8526 * @klass: the MonoClass to act on
8528 * Returns: the number of methods in the class.
8531 mono_class_num_methods (MonoClass *klass)
8533 return klass->method.count;
8537 * mono_class_num_properties
8538 * @klass: the MonoClass to act on
8540 * Returns: the number of properties in the class.
8543 mono_class_num_properties (MonoClass *klass)
8545 mono_class_setup_properties (klass);
8547 return klass->ext->property.count;
8551 * mono_class_num_events:
8552 * @klass: the MonoClass to act on
8554 * Returns: the number of events in the class.
8557 mono_class_num_events (MonoClass *klass)
8559 mono_class_setup_events (klass);
8561 return klass->ext->event.count;
8565 * mono_class_get_fields:
8566 * @klass: the MonoClass to act on
8568 * This routine is an iterator routine for retrieving the fields in a class.
8570 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8571 * iterate over all of the elements. When no more values are
8572 * available, the return value is NULL.
8574 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8577 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8579 MonoClassField* field;
8583 mono_class_setup_fields_locking (klass);
8584 if (klass->exception_type)
8586 /* start from the first */
8587 if (klass->field.count) {
8588 return *iter = &klass->fields [0];
8596 if (field < &klass->fields [klass->field.count]) {
8597 return *iter = field;
8603 * mono_class_get_methods
8604 * @klass: the MonoClass to act on
8606 * This routine is an iterator routine for retrieving the fields in a class.
8608 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8609 * iterate over all of the elements. When no more values are
8610 * available, the return value is NULL.
8612 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
8615 mono_class_get_methods (MonoClass* klass, gpointer *iter)
8617 MonoMethod** method;
8621 mono_class_setup_methods (klass);
8624 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8625 * FIXME we should better report this error to the caller
8627 if (!klass->methods)
8629 /* start from the first */
8630 if (klass->method.count) {
8631 *iter = &klass->methods [0];
8632 return klass->methods [0];
8640 if (method < &klass->methods [klass->method.count]) {
8648 * mono_class_get_virtual_methods:
8650 * Iterate over the virtual methods of KLASS.
8652 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
8655 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
8657 MonoMethod** method;
8660 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
8662 mono_class_setup_methods (klass);
8664 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
8665 * FIXME we should better report this error to the caller
8667 if (!klass->methods)
8669 /* start from the first */
8670 method = &klass->methods [0];
8675 while (method < &klass->methods [klass->method.count]) {
8676 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
8680 if (method < &klass->methods [klass->method.count]) {
8687 /* Search directly in metadata to avoid calling setup_methods () */
8688 MonoMethod *res = NULL;
8694 start_index = GPOINTER_TO_UINT (*iter);
8697 for (i = start_index; i < klass->method.count; ++i) {
8700 /* class->method.first points into the methodptr table */
8701 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
8703 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
8707 if (i < klass->method.count) {
8708 res = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
8709 /* Add 1 here so the if (*iter) check fails */
8710 *iter = GUINT_TO_POINTER (i + 1);
8719 * mono_class_get_properties:
8720 * @klass: the MonoClass to act on
8722 * This routine is an iterator routine for retrieving the properties in a class.
8724 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8725 * iterate over all of the elements. When no more values are
8726 * available, the return value is NULL.
8728 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
8731 mono_class_get_properties (MonoClass* klass, gpointer *iter)
8733 MonoProperty* property;
8737 mono_class_setup_properties (klass);
8738 /* start from the first */
8739 if (klass->ext->property.count) {
8740 return *iter = &klass->ext->properties [0];
8748 if (property < &klass->ext->properties [klass->ext->property.count]) {
8749 return *iter = property;
8755 * mono_class_get_events:
8756 * @klass: the MonoClass to act on
8758 * This routine is an iterator routine for retrieving the properties in a class.
8760 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8761 * iterate over all of the elements. When no more values are
8762 * available, the return value is NULL.
8764 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
8767 mono_class_get_events (MonoClass* klass, gpointer *iter)
8773 mono_class_setup_events (klass);
8774 /* start from the first */
8775 if (klass->ext->event.count) {
8776 return *iter = &klass->ext->events [0];
8784 if (event < &klass->ext->events [klass->ext->event.count]) {
8785 return *iter = event;
8791 * mono_class_get_interfaces
8792 * @klass: the MonoClass to act on
8794 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
8796 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8797 * iterate over all of the elements. When no more values are
8798 * available, the return value is NULL.
8800 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8803 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
8811 mono_class_init (klass);
8812 if (!klass->interfaces_inited) {
8813 mono_class_setup_interfaces (klass, &error);
8814 if (!mono_error_ok (&error)) {
8815 mono_error_cleanup (&error);
8819 /* start from the first */
8820 if (klass->interface_count) {
8821 *iter = &klass->interfaces [0];
8822 return klass->interfaces [0];
8830 if (iface < &klass->interfaces [klass->interface_count]) {
8838 * mono_class_get_nested_types
8839 * @klass: the MonoClass to act on
8841 * This routine is an iterator routine for retrieving the nested types of a class.
8842 * This works only if @klass is non-generic, or a generic type definition.
8844 * You must pass a gpointer that points to zero and is treated as an opaque handle to
8845 * iterate over all of the elements. When no more values are
8846 * available, the return value is NULL.
8848 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
8851 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
8859 if (!klass->nested_classes_inited) {
8860 if (!klass->type_token)
8861 klass->nested_classes_inited = TRUE;
8862 mono_loader_lock ();
8863 if (!klass->nested_classes_inited) {
8864 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
8867 guint32 cols [MONO_NESTED_CLASS_SIZE];
8868 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
8869 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
8870 if (!mono_error_ok (&error)) {
8871 /*FIXME don't swallow the error message*/
8872 mono_error_cleanup (&error);
8874 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8877 mono_class_alloc_ext (klass);
8878 klass->ext->nested_classes = g_list_prepend_image (klass->image, klass->ext->nested_classes, nclass);
8880 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
8883 mono_memory_barrier ();
8884 klass->nested_classes_inited = TRUE;
8885 mono_loader_unlock ();
8889 /* start from the first */
8890 if (klass->ext && klass->ext->nested_classes) {
8891 *iter = klass->ext->nested_classes;
8892 return klass->ext->nested_classes->data;
8894 /* no nested types */
8909 * mono_class_is_delegate
8910 * @klass: the MonoClass to act on
8912 * Returns: true if the MonoClass represents a System.Delegate.
8915 mono_class_is_delegate (MonoClass *klass)
8917 return klass->delegate;
8921 * mono_class_implements_interface
8922 * @klass: The MonoClass to act on
8923 * @interface: The interface to check if @klass implements.
8925 * Returns: true if @klass implements @interface.
8928 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
8930 return mono_class_is_assignable_from (iface, klass);
8934 * mono_field_get_name:
8935 * @field: the MonoClassField to act on
8937 * Returns: the name of the field.
8940 mono_field_get_name (MonoClassField *field)
8946 * mono_field_get_type:
8947 * @field: the MonoClassField to act on
8949 * Returns: MonoType of the field.
8952 mono_field_get_type (MonoClassField *field)
8955 MonoType *type = mono_field_get_type_checked (field, &error);
8956 if (!mono_error_ok (&error)) {
8957 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
8958 mono_error_cleanup (&error);
8965 * mono_field_get_type_checked:
8966 * @field: the MonoClassField to act on
8967 * @error: used to return any erro found while retrieving @field type
8969 * Returns: MonoType of the field.
8972 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
8974 mono_error_init (error);
8976 mono_field_resolve_type (field, error);
8981 * mono_field_get_parent:
8982 * @field: the MonoClassField to act on
8984 * Returns: MonoClass where the field was defined.
8987 mono_field_get_parent (MonoClassField *field)
8989 return field->parent;
8993 * mono_field_get_flags;
8994 * @field: the MonoClassField to act on
8996 * The metadata flags for a field are encoded using the
8997 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
8999 * Returns: the flags for the field.
9002 mono_field_get_flags (MonoClassField *field)
9005 return mono_field_resolve_flags (field);
9006 return field->type->attrs;
9010 * mono_field_get_offset;
9011 * @field: the MonoClassField to act on
9013 * Returns: the field offset.
9016 mono_field_get_offset (MonoClassField *field)
9018 return field->offset;
9022 mono_field_get_rva (MonoClassField *field)
9026 MonoClass *klass = field->parent;
9028 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9030 if (!klass->ext || !klass->ext->field_def_values) {
9031 mono_loader_lock ();
9032 mono_class_alloc_ext (klass);
9033 if (!klass->ext->field_def_values)
9034 klass->ext->field_def_values = mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9035 mono_loader_unlock ();
9038 field_index = mono_field_get_index (field);
9040 if (!klass->ext->field_def_values [field_index].data && !klass->image->dynamic) {
9041 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9043 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9044 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9047 return klass->ext->field_def_values [field_index].data;
9051 * mono_field_get_data;
9052 * @field: the MonoClassField to act on
9054 * Returns: pointer to the metadata constant value or to the field
9055 * data if it has an RVA flag.
9058 mono_field_get_data (MonoClassField *field)
9060 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9061 MonoTypeEnum def_type;
9063 return mono_class_get_field_default_value (field, &def_type);
9064 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9065 return mono_field_get_rva (field);
9072 * mono_property_get_name:
9073 * @prop: the MonoProperty to act on
9075 * Returns: the name of the property
9078 mono_property_get_name (MonoProperty *prop)
9084 * mono_property_get_set_method
9085 * @prop: the MonoProperty to act on.
9087 * Returns: the setter method of the property (A MonoMethod)
9090 mono_property_get_set_method (MonoProperty *prop)
9096 * mono_property_get_get_method
9097 * @prop: the MonoProperty to act on.
9099 * Returns: the setter method of the property (A MonoMethod)
9102 mono_property_get_get_method (MonoProperty *prop)
9108 * mono_property_get_parent:
9109 * @prop: the MonoProperty to act on.
9111 * Returns: the MonoClass where the property was defined.
9114 mono_property_get_parent (MonoProperty *prop)
9116 return prop->parent;
9120 * mono_property_get_flags:
9121 * @prop: the MonoProperty to act on.
9123 * The metadata flags for a property are encoded using the
9124 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9126 * Returns: the flags for the property.
9129 mono_property_get_flags (MonoProperty *prop)
9135 * mono_event_get_name:
9136 * @event: the MonoEvent to act on
9138 * Returns: the name of the event.
9141 mono_event_get_name (MonoEvent *event)
9147 * mono_event_get_add_method:
9148 * @event: The MonoEvent to act on.
9150 * Returns: the @add' method for the event (a MonoMethod).
9153 mono_event_get_add_method (MonoEvent *event)
9159 * mono_event_get_remove_method:
9160 * @event: The MonoEvent to act on.
9162 * Returns: the @remove method for the event (a MonoMethod).
9165 mono_event_get_remove_method (MonoEvent *event)
9167 return event->remove;
9171 * mono_event_get_raise_method:
9172 * @event: The MonoEvent to act on.
9174 * Returns: the @raise method for the event (a MonoMethod).
9177 mono_event_get_raise_method (MonoEvent *event)
9179 return event->raise;
9183 * mono_event_get_parent:
9184 * @event: the MonoEvent to act on.
9186 * Returns: the MonoClass where the event is defined.
9189 mono_event_get_parent (MonoEvent *event)
9191 return event->parent;
9195 * mono_event_get_flags
9196 * @event: the MonoEvent to act on.
9198 * The metadata flags for an event are encoded using the
9199 * EVENT_* constants. See the tabledefs.h file for details.
9201 * Returns: the flags for the event.
9204 mono_event_get_flags (MonoEvent *event)
9206 return event->attrs;
9210 * mono_class_get_method_from_name:
9211 * @klass: where to look for the method
9212 * @name_space: name of the method
9213 * @param_count: number of parameters. -1 for any number.
9215 * Obtains a MonoMethod with a given name and number of parameters.
9216 * It only works if there are no multiple signatures for any given method name.
9219 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9221 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9225 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9227 MonoMethod *res = NULL;
9230 /* Search directly in the metadata to avoid calling setup_methods () */
9231 for (i = 0; i < klass->method.count; ++i) {
9232 guint32 cols [MONO_METHOD_SIZE];
9234 MonoMethodSignature *sig;
9236 /* class->method.first points into the methodptr table */
9237 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9239 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9240 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
9241 if (param_count == -1) {
9245 sig = mono_method_signature (method);
9246 if (sig && sig->param_count == param_count) {
9257 * mono_class_get_method_from_name_flags:
9258 * @klass: where to look for the method
9259 * @name_space: name of the method
9260 * @param_count: number of parameters. -1 for any number.
9261 * @flags: flags which must be set in the method
9263 * Obtains a MonoMethod with a given name and number of parameters.
9264 * It only works if there are no multiple signatures for any given method name.
9267 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9269 MonoMethod *res = NULL;
9272 mono_class_init (klass);
9274 if (klass->generic_class && !klass->methods) {
9275 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9277 res = mono_class_inflate_generic_method_full (res, klass, mono_class_get_context (klass));
9281 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9282 mono_class_setup_methods (klass);
9284 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9285 See mono/tests/array_load_exception.il
9286 FIXME we should better report this error to the caller
9288 if (!klass->methods)
9290 for (i = 0; i < klass->method.count; ++i) {
9291 MonoMethod *method = klass->methods [i];
9293 if (method->name[0] == name [0] &&
9294 !strcmp (name, method->name) &&
9295 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9296 ((method->flags & flags) == flags)) {
9303 res = find_method_in_metadata (klass, name, param_count, flags);
9310 * mono_class_set_failure:
9311 * @klass: class in which the failure was detected
9312 * @ex_type: the kind of exception/error to be thrown (later)
9313 * @ex_data: exception data (specific to each type of exception/error)
9315 * Keep a detected failure informations in the class for later processing.
9316 * Note that only the first failure is kept.
9318 * LOCKING: Acquires the loader lock.
9321 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9323 if (klass->exception_type)
9326 mono_loader_lock ();
9327 klass->exception_type = ex_type;
9329 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9330 mono_loader_unlock ();
9336 * mono_class_get_exception_data:
9338 * Return the exception_data property of KLASS.
9340 * LOCKING: Acquires the loader lock.
9343 mono_class_get_exception_data (MonoClass *klass)
9345 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9349 * mono_classes_init:
9351 * Initialize the resources used by this module.
9354 mono_classes_init (void)
9356 mono_counters_register ("Inflated methods size",
9357 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9358 mono_counters_register ("Inflated classes",
9359 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9360 mono_counters_register ("Inflated classes size",
9361 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9362 mono_counters_register ("MonoClass size",
9363 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9364 mono_counters_register ("MonoClassExt size",
9365 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9369 * mono_classes_cleanup:
9371 * Free the resources used by this module.
9374 mono_classes_cleanup (void)
9376 if (global_interface_bitset)
9377 mono_bitset_free (global_interface_bitset);
9378 global_interface_bitset = NULL;
9382 * mono_class_get_exception_for_failure:
9383 * @klass: class in which the failure was detected
9385 * Return a constructed MonoException than the caller can then throw
9386 * using mono_raise_exception - or NULL if no failure is present (or
9387 * doesn't result in an exception).
9390 mono_class_get_exception_for_failure (MonoClass *klass)
9392 gpointer exception_data = mono_class_get_exception_data (klass);
9394 switch (klass->exception_type) {
9395 #ifndef DISABLE_SECURITY
9396 case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
9397 MonoDomain *domain = mono_domain_get ();
9398 MonoSecurityManager* secman = mono_security_manager_get_methods ();
9399 MonoMethod *method = exception_data;
9400 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
9401 MonoObject *exc = NULL;
9405 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
9406 args [2] = mono_type_get_object (domain, &klass->byval_arg);
9407 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
9409 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
9410 return (MonoException*) exc;
9413 case MONO_EXCEPTION_TYPE_LOAD: {
9416 char *str = mono_type_get_full_name (klass);
9417 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9418 name = mono_string_new (mono_domain_get (), str);
9420 ex = mono_get_exception_type_load (name, astr);
9424 case MONO_EXCEPTION_MISSING_METHOD: {
9425 char *class_name = exception_data;
9426 char *assembly_name = class_name + strlen (class_name) + 1;
9428 return mono_get_exception_missing_method (class_name, assembly_name);
9430 case MONO_EXCEPTION_MISSING_FIELD: {
9431 char *class_name = exception_data;
9432 char *member_name = class_name + strlen (class_name) + 1;
9434 return mono_get_exception_missing_field (class_name, member_name);
9436 case MONO_EXCEPTION_FILE_NOT_FOUND: {
9437 char *msg_format = exception_data;
9438 char *assembly_name = msg_format + strlen (msg_format) + 1;
9439 char *msg = g_strdup_printf (msg_format, assembly_name);
9442 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
9448 case MONO_EXCEPTION_BAD_IMAGE: {
9449 return mono_get_exception_bad_image_format (exception_data);
9452 MonoLoaderError *error;
9455 error = mono_loader_get_last_error ();
9457 ex = mono_loader_error_prepare_exception (error);
9461 /* TODO - handle other class related failures */
9468 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9470 outer_klass = mono_class_get_generic_type_definition (outer_klass);
9471 inner_klass = mono_class_get_generic_type_definition (inner_klass);
9473 if (outer_klass == inner_klass)
9475 inner_klass = inner_klass->nested_in;
9476 } while (inner_klass);
9481 mono_class_get_generic_type_definition (MonoClass *klass)
9483 return klass->generic_class ? klass->generic_class->container_class : klass;
9487 * Check if @klass is a subtype of @parent ignoring generic instantiations.
9489 * Generic instantiations are ignored for all super types of @klass.
9491 * Visibility checks ignoring generic instantiations.
9494 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9497 klass = mono_class_get_generic_type_definition (klass);
9498 parent = mono_class_get_generic_type_definition (parent);
9499 mono_class_setup_supertypes (klass);
9501 for (i = 0; i < klass->idepth; ++i) {
9502 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9508 * Subtype can only access parent members with family protection if the site object
9509 * is subclass of Subtype. For example:
9510 * class A { protected int x; }
9512 * void valid_access () {
9516 * void invalid_access () {
9523 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9525 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9528 if (context_klass == NULL)
9530 /*if access_klass is not member_klass context_klass must be type compat*/
9531 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9537 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9540 if (accessing == accessed)
9542 if (!accessed || !accessing)
9545 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9546 * anywhere so untrusted friends are not safe to access platform's code internals */
9547 if (mono_security_core_clr_enabled ()) {
9548 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
9552 mono_assembly_load_friends (accessed);
9553 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
9554 MonoAssemblyName *friend = tmp->data;
9555 /* Be conservative with checks */
9558 if (strcmp (accessing->aname.name, friend->name))
9560 if (friend->public_key_token [0]) {
9561 if (!accessing->aname.public_key_token [0])
9563 if (!mono_public_tokens_are_equal (friend->public_key_token, accessing->aname.public_key_token))
9572 * If klass is a generic type or if it is derived from a generic type, return the
9573 * MonoClass of the generic definition
9574 * Returns NULL if not found
9577 get_generic_definition_class (MonoClass *klass)
9580 if (klass->generic_class && klass->generic_class->container_class)
9581 return klass->generic_class->container_class;
9582 klass = klass->parent;
9588 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
9591 for (i = 0; i < ginst->type_argc; ++i) {
9592 MonoType *type = ginst->type_argv[i];
9593 switch (type->type) {
9594 case MONO_TYPE_SZARRAY:
9595 if (!can_access_type (access_klass, type->data.klass))
9598 case MONO_TYPE_ARRAY:
9599 if (!can_access_type (access_klass, type->data.array->eklass))
9603 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
9606 case MONO_TYPE_CLASS:
9607 case MONO_TYPE_VALUETYPE:
9608 case MONO_TYPE_GENERICINST:
9609 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
9617 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
9621 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9624 if (access_klass->element_class && !access_klass->enumtype)
9625 access_klass = access_klass->element_class;
9627 if (member_klass->element_class && !member_klass->enumtype)
9628 member_klass = member_klass->element_class;
9630 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
9632 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
9635 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
9638 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
9641 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
9644 /*Non nested type with nested visibility. We just fail it.*/
9645 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
9648 switch (access_level) {
9649 case TYPE_ATTRIBUTE_NOT_PUBLIC:
9650 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9652 case TYPE_ATTRIBUTE_PUBLIC:
9655 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
9658 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
9659 return is_nesting_type (member_klass, access_klass);
9661 case TYPE_ATTRIBUTE_NESTED_FAMILY:
9662 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9664 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
9665 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9667 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
9668 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
9669 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9671 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
9672 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
9673 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
9678 /* FIXME: check visibility of type, too */
9680 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
9682 MonoClass *member_generic_def;
9683 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
9686 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
9687 access_klass->generic_container) &&
9688 (member_generic_def = get_generic_definition_class (member_klass))) {
9689 MonoClass *access_container;
9691 if (access_klass->generic_container)
9692 access_container = access_klass;
9694 access_container = access_klass->generic_class->container_class;
9696 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
9700 /* Partition I 8.5.3.2 */
9701 /* the access level values are the same for fields and methods */
9702 switch (access_level) {
9703 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
9704 /* same compilation unit */
9705 return access_klass->image == member_klass->image;
9706 case FIELD_ATTRIBUTE_PRIVATE:
9707 return access_klass == member_klass;
9708 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
9709 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
9710 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
9713 case FIELD_ATTRIBUTE_ASSEMBLY:
9714 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9715 case FIELD_ATTRIBUTE_FAMILY:
9716 if (is_valid_family_access (access_klass, member_klass, context_klass))
9719 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
9720 if (is_valid_family_access (access_klass, member_klass, context_klass))
9722 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
9723 case FIELD_ATTRIBUTE_PUBLIC:
9730 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
9732 /* FIXME: check all overlapping fields */
9733 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9735 MonoClass *nested = method->klass->nested_in;
9737 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9740 nested = nested->nested_in;
9747 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
9749 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9751 MonoClass *nested = method->klass->nested_in;
9753 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9756 nested = nested->nested_in;
9761 * with generics calls to explicit interface implementations can be expressed
9762 * directly: the method is private, but we must allow it. This may be opening
9763 * a hole or the generics code should handle this differently.
9764 * Maybe just ensure the interface type is public.
9766 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
9772 * mono_method_can_access_method_full:
9773 * @method: The caller method
9774 * @called: The called method
9775 * @context_klass: The static type on stack of the owner @called object used
9777 * This function must be used with instance calls, as they have more strict family accessibility.
9778 * It can be used with static methods, but context_klass should be NULL.
9780 * Returns: TRUE if caller have proper visibility and acessibility to @called
9783 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
9785 MonoClass *access_class = method->klass;
9786 MonoClass *member_class = called->klass;
9787 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9789 MonoClass *nested = access_class->nested_in;
9791 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
9794 nested = nested->nested_in;
9801 can = can_access_type (access_class, member_class);
9803 MonoClass *nested = access_class->nested_in;
9805 can = can_access_type (nested, member_class);
9808 nested = nested->nested_in;
9815 if (called->is_inflated) {
9816 MonoMethodInflated * infl = (MonoMethodInflated*)called;
9817 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
9826 * mono_method_can_access_field_full:
9827 * @method: The caller method
9828 * @field: The accessed field
9829 * @context_klass: The static type on stack of the owner @field object used
9831 * This function must be used with instance fields, as they have more strict family accessibility.
9832 * It can be used with static fields, but context_klass should be NULL.
9834 * Returns: TRUE if caller have proper visibility and acessibility to @field
9837 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
9839 MonoClass *access_class = method->klass;
9840 MonoClass *member_class = field->parent;
9841 /* FIXME: check all overlapping fields */
9842 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9844 MonoClass *nested = access_class->nested_in;
9846 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
9849 nested = nested->nested_in;
9856 can = can_access_type (access_class, member_class);
9858 MonoClass *nested = access_class->nested_in;
9860 can = can_access_type (nested, member_class);
9863 nested = nested->nested_in;
9873 * mono_class_can_access_class:
9874 * @source_class: The source class
9875 * @target_class: The accessed class
9877 * This function returns is @target_class is visible to @source_class
9879 * Returns: TRUE if source have proper visibility and acessibility to target
9882 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
9884 return can_access_type (source_class, target_class);
9888 * mono_type_is_valid_enum_basetype:
9889 * @type: The MonoType to check
9891 * Returns: TRUE if the type can be used as the basetype of an enum
9893 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
9894 switch (type->type) {
9897 case MONO_TYPE_BOOLEAN:
9900 case MONO_TYPE_CHAR:
9913 * mono_class_is_valid_enum:
9914 * @klass: An enum class to be validated
9916 * This method verify the required properties an enum should have.
9918 * Returns: TRUE if the informed enum class is valid
9920 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
9921 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
9922 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
9924 gboolean mono_class_is_valid_enum (MonoClass *klass) {
9925 MonoClassField * field;
9926 gpointer iter = NULL;
9927 gboolean found_base_field = FALSE;
9929 g_assert (klass->enumtype);
9930 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
9931 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
9935 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
9938 while ((field = mono_class_get_fields (klass, &iter))) {
9939 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
9940 if (found_base_field)
9942 found_base_field = TRUE;
9943 if (!mono_type_is_valid_enum_basetype (field->type))
9948 if (!found_base_field)
9951 if (klass->method.count > 0)
9958 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
9960 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
9964 * mono_class_setup_interface_id:
9966 * Initializes MonoClass::interface_id if required.
9968 * LOCKING: Acquires the loader lock.
9971 mono_class_setup_interface_id (MonoClass *class)
9973 mono_loader_lock ();
9974 if (MONO_CLASS_IS_INTERFACE (class) && !class->interface_id)
9975 class->interface_id = mono_get_unique_iid (class);
9976 mono_loader_unlock ();
9980 * mono_class_alloc_ext:
9982 * Allocate klass->ext if not already done.
9983 * LOCKING: Assumes the loader lock is held.
9986 mono_class_alloc_ext (MonoClass *klass)
9989 klass->ext = mono_class_alloc0 (klass, sizeof (MonoClassExt));
9990 class_ext_size += sizeof (MonoClassExt);
9995 * mono_class_setup_interfaces:
9997 * Initialize class->interfaces/interfaces_count.
9998 * LOCKING: Acquires the loader lock.
9999 * This function can fail the type.
10002 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10006 mono_error_init (error);
10008 if (klass->interfaces_inited)
10011 mono_loader_lock ();
10013 if (klass->interfaces_inited) {
10014 mono_loader_unlock ();
10018 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10019 MonoType *args [1];
10021 /* generic IList, ICollection, IEnumerable */
10022 klass->interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10023 klass->interfaces = mono_image_alloc0 (klass->image, sizeof (MonoClass*) * klass->interface_count);
10025 args [0] = &klass->element_class->byval_arg;
10026 klass->interfaces [0] = mono_class_bind_generic_parameters (
10027 mono_defaults.generic_ilist_class, 1, args, FALSE);
10028 if (klass->interface_count > 1)
10029 klass->interfaces [1] = mono_class_bind_generic_parameters (
10030 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10031 } else if (klass->generic_class) {
10032 MonoClass *gklass = klass->generic_class->container_class;
10034 klass->interface_count = gklass->interface_count;
10035 klass->interfaces = mono_class_new0 (klass, MonoClass *, klass->interface_count);
10036 for (i = 0; i < klass->interface_count; i++) {
10037 klass->interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10038 if (!mono_error_ok (error)) {
10039 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10040 klass->interfaces = NULL;
10046 mono_memory_barrier ();
10048 klass->interfaces_inited = TRUE;
10050 mono_loader_unlock ();
10054 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10056 MonoClass *class = field->parent;
10057 MonoImage *image = class->image;
10058 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10059 int field_idx = field - class->fields;
10061 mono_error_init (error);
10064 MonoClassField *gfield = >d->fields [field_idx];
10065 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10066 if (!mono_error_ok (error)) {
10067 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10068 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10072 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (class), error);
10073 if (!mono_error_ok (error)) {
10074 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10075 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10080 guint32 cols [MONO_FIELD_SIZE];
10081 MonoGenericContainer *container = NULL;
10082 int idx = class->field.first + field_idx;
10084 /*FIXME, in theory we do not lazy load SRE fields*/
10085 g_assert (!image->dynamic);
10087 if (class->generic_container) {
10088 container = class->generic_container;
10090 container = gtd->generic_container;
10091 g_assert (container);
10094 /* class->field.first and idx points into the fieldptr table */
10095 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10097 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10098 mono_error_set_type_load_class (error, class, "Could not verify field %s signature", field->name);
10099 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
10103 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10105 mono_metadata_decode_value (sig, &sig);
10106 /* FIELD signature == 0x06 */
10107 g_assert (*sig == 0x06);
10108 field->type = mono_metadata_parse_type_full (image, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10110 mono_class_set_failure_from_loader_error (class, error, g_strdup_printf ("Could not load field %s type", field->name));
10115 mono_field_resolve_flags (MonoClassField *field)
10117 MonoClass *class = field->parent;
10118 MonoImage *image = class->image;
10119 MonoClass *gtd = class->generic_class ? mono_class_get_generic_type_definition (class) : NULL;
10120 int field_idx = field - class->fields;
10124 MonoClassField *gfield = >d->fields [field_idx];
10125 return mono_field_get_flags (gfield);
10127 int idx = class->field.first + field_idx;
10129 /*FIXME, in theory we do not lazy load SRE fields*/
10130 g_assert (!image->dynamic);
10132 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10137 * mono_class_setup_basic_field_info:
10138 * @class: The class to initialize
10140 * Initializes the class->fields array of fields.
10141 * Aquires the loader lock.
10144 mono_class_setup_basic_field_info_locking (MonoClass *class)
10146 mono_loader_lock ();
10147 mono_class_setup_basic_field_info (class);
10148 mono_loader_unlock ();
10152 * mono_class_get_fields_lazy:
10153 * @klass: the MonoClass to act on
10155 * This routine is an iterator routine for retrieving the fields in a class.
10156 * Only minimal information about fields are loaded. Accessors must be used
10157 * for all MonoClassField returned.
10159 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10160 * iterate over all of the elements. When no more values are
10161 * available, the return value is NULL.
10163 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10166 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10168 MonoClassField* field;
10172 mono_class_setup_basic_field_info_locking (klass);
10173 if (!klass->fields)
10175 /* start from the first */
10176 if (klass->field.count) {
10177 return *iter = &klass->fields [0];
10185 if (field < &klass->fields [klass->field.count]) {
10186 return *iter = field;
10192 mono_class_full_name (MonoClass *klass)
10194 return mono_type_full_name (&klass->byval_arg);