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-internals.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-internals.h>
43 #include <mono/utils/mono-memory-model.h>
44 #include <mono/utils/atomic.h>
45 #include <mono/utils/bsearch.h>
46 #include <mono/utils/checked-build.h>
50 gboolean mono_print_vtable = FALSE;
51 gboolean mono_align_small_structs = FALSE;
54 guint32 inflated_classes, inflated_classes_size, inflated_methods_size;
55 guint32 classes_size, class_ext_size;
57 /* Low level lock which protects data structures in this module */
58 static mono_mutex_t classes_mutex;
60 /* Function supplied by the runtime to find classes by name using information from the AOT file */
61 static MonoGetClassFromName get_class_from_name = NULL;
63 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error);
64 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
65 static gboolean can_access_type (MonoClass *access_klass, MonoClass *member_klass);
66 static MonoMethod* find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags);
67 static int generic_array_methods (MonoClass *klass);
68 static void setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos);
70 static MonoMethod* mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter);
71 static char* mono_assembly_name_from_token (MonoImage *image, guint32 type_token);
72 static void mono_field_resolve_type (MonoClassField *field, MonoError *error);
73 static guint32 mono_field_resolve_flags (MonoClassField *field);
74 static void mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup);
75 static void mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gklass);
78 We use gclass recording to allow recursive system f types to be referenced by a parent.
80 Given the following type hierarchy:
82 class TextBox : TextBoxBase<TextBox> {}
83 class TextBoxBase<T> : TextInput<TextBox> where T : TextBoxBase<T> {}
84 class TextInput<T> : Input<T> where T: TextInput<T> {}
87 The runtime tries to load TextBoxBase<>.
88 To load TextBoxBase<> to do so it must resolve the parent which is TextInput<TextBox>.
89 To instantiate TextInput<TextBox> it must resolve TextInput<> and TextBox.
90 To load TextBox it must resolve the parent which is TextBoxBase<TextBox>.
92 At this point the runtime must instantiate TextBoxBase<TextBox>. Both types are partially loaded
93 at this point, iow, both are registered in the type map and both and a NULL parent. This means
94 that the resulting generic instance will have a NULL parent, which is wrong and will cause breakage.
96 To fix that what we do is to record all generic instantes created while resolving the parent of
97 any generic type definition and, after resolved, correct the parent field if needed.
100 static int record_gclass_instantiation;
101 static GSList *gclass_recorded_list;
102 typedef gboolean (*gclass_record_func) (MonoClass*, void*);
107 mono_locks_os_acquire (&classes_mutex, ClassesLock);
111 classes_unlock (void)
113 mono_locks_os_release (&classes_mutex, ClassesLock);
117 * LOCKING: loader lock must be held until pairing disable_gclass_recording is called.
120 enable_gclass_recording (void)
122 ++record_gclass_instantiation;
126 * LOCKING: loader lock must be held since pairing enable_gclass_recording was called.
129 disable_gclass_recording (gclass_record_func func, void *user_data)
131 GSList **head = &gclass_recorded_list;
133 g_assert (record_gclass_instantiation > 0);
134 --record_gclass_instantiation;
137 GSList *node = *head;
138 if (func ((MonoClass*)node->data, user_data)) {
140 g_slist_free_1 (node);
146 /* We automatically discard all recorded gclasses when disabled. */
147 if (!record_gclass_instantiation && gclass_recorded_list) {
148 g_slist_free (gclass_recorded_list);
149 gclass_recorded_list = NULL;
154 * mono_class_from_typeref:
155 * @image: a MonoImage
156 * @type_token: a TypeRef token
158 * Creates the MonoClass* structure representing the type defined by
159 * the typeref token valid inside @image.
160 * Returns: The MonoClass* representing the typeref token, NULL ifcould
164 mono_class_from_typeref (MonoImage *image, guint32 type_token)
167 MonoClass *klass = mono_class_from_typeref_checked (image, type_token, &error);
168 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
173 * mono_class_from_typeref_checked:
174 * @image: a MonoImage
175 * @type_token: a TypeRef token
176 * @error: error return code, if any.
178 * Creates the MonoClass* structure representing the type defined by
179 * the typeref token valid inside @image.
181 * Returns: The MonoClass* representing the typeref token, NULL if it could
182 * not be loaded with the @error value filled with the information about the
186 mono_class_from_typeref_checked (MonoImage *image, guint32 type_token, MonoError *error)
188 guint32 cols [MONO_TYPEREF_SIZE];
189 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
191 const char *name, *nspace;
192 MonoClass *res = NULL;
195 mono_error_init (error);
197 if (!mono_verifier_verify_typeref_row (image, (type_token & 0xffffff) - 1, error))
200 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
202 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
203 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
205 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
206 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
207 case MONO_RESOLUTION_SCOPE_MODULE:
209 LAMESPEC The spec says that a null module resolution scope should go through the exported type table.
210 This is not the observed behavior of existing implementations.
211 The defacto behavior is that it's just a typedef in disguise.
213 /* a typedef in disguise */
214 res = mono_class_from_name_checked (image, nspace, name, error);
217 case MONO_RESOLUTION_SCOPE_MODULEREF:
218 module = mono_image_load_module (image, idx);
220 res = mono_class_from_name_checked (module, nspace, name, error);
223 case MONO_RESOLUTION_SCOPE_TYPEREF: {
224 MonoClass *enclosing;
227 if (idx == mono_metadata_token_index (type_token)) {
228 mono_error_set_bad_image (error, image, "Image with self-referencing typeref token %08x.", type_token);
232 enclosing = mono_class_from_typeref_checked (image, MONO_TOKEN_TYPE_REF | idx, error);
233 return_val_if_nok (error, NULL);
235 if (enclosing->nested_classes_inited && enclosing->ext) {
236 /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
237 for (tmp = enclosing->ext->nested_classes; tmp; tmp = tmp->next) {
238 res = (MonoClass *)tmp->data;
239 if (strcmp (res->name, name) == 0)
243 /* Don't call mono_class_init as we might've been called by it recursively */
244 int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
246 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
247 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
248 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
250 if (strcmp (nname, name) == 0)
251 return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested, error);
253 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
256 g_warning ("TypeRef ResolutionScope not yet handled (%d) for %s.%s in image %s", idx, nspace, name, image->name);
259 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
263 if (idx > image->tables [MONO_TABLE_ASSEMBLYREF].rows) {
264 mono_error_set_bad_image (error, image, "Image with invalid assemblyref token %08x.", idx);
268 if (!image->references || !image->references [idx - 1])
269 mono_assembly_load_reference (image, idx - 1);
270 g_assert (image->references [idx - 1]);
272 /* If the assembly did not load, register this as a type load exception */
273 if (image->references [idx - 1] == REFERENCE_MISSING){
274 MonoAssemblyName aname;
277 mono_assembly_get_assemblyref (image, idx - 1, &aname);
278 human_name = mono_stringify_assembly_name (&aname);
279 mono_error_set_assembly_load_simple (error, human_name, image->assembly ? image->assembly->ref_only : FALSE);
283 res = mono_class_from_name_checked (image->references [idx - 1]->image, nspace, name, error);
286 /* Generic case, should be avoided for when a better error is possible. */
287 if (!res && mono_error_ok (error)) {
288 if (mono_loader_get_last_error ()) { /*FIXME plug the above to not leak errors*/
289 mono_error_set_from_loader_error (error);
291 char *name = mono_class_name_from_token (image, type_token);
292 char *assembly = mono_assembly_name_from_token (image, type_token);
293 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
296 mono_loader_assert_no_error ();
302 mono_image_memdup (MonoImage *image, void *data, guint size)
304 void *res = mono_image_alloc (image, size);
305 memcpy (res, data, size);
309 /* Copy everything mono_metadata_free_array free. */
311 mono_dup_array_type (MonoImage *image, MonoArrayType *a)
314 a = (MonoArrayType *)mono_image_memdup (image, a, sizeof (MonoArrayType));
316 a->sizes = (int *)mono_image_memdup (image, a->sizes, a->numsizes * sizeof (int));
318 a->lobounds = (int *)mono_image_memdup (image, a->lobounds, a->numlobounds * sizeof (int));
320 a = (MonoArrayType *)g_memdup (a, sizeof (MonoArrayType));
322 a->sizes = (int *)g_memdup (a->sizes, a->numsizes * sizeof (int));
324 a->lobounds = (int *)g_memdup (a->lobounds, a->numlobounds * sizeof (int));
329 /* Copy everything mono_metadata_free_method_signature free. */
331 mono_metadata_signature_deep_dup (MonoImage *image, MonoMethodSignature *sig)
335 sig = mono_metadata_signature_dup_full (image, sig);
337 sig->ret = mono_metadata_type_dup (image, sig->ret);
338 for (i = 0; i < sig->param_count; ++i)
339 sig->params [i] = mono_metadata_type_dup (image, sig->params [i]);
345 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
347 MonoAssembly *ta = klass->image->assembly;
350 name = mono_stringify_assembly_name (&ta->aname);
351 g_string_append_printf (str, ", %s", name);
356 mono_type_name_check_byref (MonoType *type, GString *str)
359 g_string_append_c (str, '&');
363 * mono_identifier_escape_type_name_chars:
364 * @str: a destination string
365 * @identifier: an IDENTIFIER in internal form
369 * The displayed form of the identifier is appended to str.
371 * The displayed form of an identifier has the characters ,+&*[]\
372 * that have special meaning in type names escaped with a preceeding
373 * backslash (\) character.
376 mono_identifier_escape_type_name_chars (GString* str, const char* identifier)
382 // reserve space for common case: there will be no escaped characters.
383 g_string_set_size(str, n + strlen(identifier));
384 g_string_set_size(str, n);
386 for (const char* s = identifier; *s != 0 ; s++) {
395 g_string_append_c (str, '\\');
396 g_string_append_c (str, *s);
399 g_string_append_c (str, *s);
407 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
408 MonoTypeNameFormat format)
412 switch (type->type) {
413 case MONO_TYPE_ARRAY: {
414 int i, rank = type->data.array->rank;
415 MonoTypeNameFormat nested_format;
417 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
418 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
420 mono_type_get_name_recurse (
421 &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
422 g_string_append_c (str, '[');
424 g_string_append_c (str, '*');
425 for (i = 1; i < rank; i++)
426 g_string_append_c (str, ',');
427 g_string_append_c (str, ']');
429 mono_type_name_check_byref (type, str);
431 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
432 _mono_type_get_assembly_name (type->data.array->eklass, str);
435 case MONO_TYPE_SZARRAY: {
436 MonoTypeNameFormat nested_format;
438 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
439 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
441 mono_type_get_name_recurse (
442 &type->data.klass->byval_arg, str, FALSE, nested_format);
443 g_string_append (str, "[]");
445 mono_type_name_check_byref (type, str);
447 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
448 _mono_type_get_assembly_name (type->data.klass, str);
451 case MONO_TYPE_PTR: {
452 MonoTypeNameFormat nested_format;
454 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
455 MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
457 mono_type_get_name_recurse (
458 type->data.type, str, FALSE, nested_format);
459 g_string_append_c (str, '*');
461 mono_type_name_check_byref (type, str);
463 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
464 _mono_type_get_assembly_name (mono_class_from_mono_type (type->data.type), str);
469 if (!mono_generic_param_info (type->data.generic_param))
470 g_string_append_printf (str, "%s%d", type->type == MONO_TYPE_VAR ? "!" : "!!", type->data.generic_param->num);
472 g_string_append (str, mono_generic_param_info (type->data.generic_param)->name);
474 mono_type_name_check_byref (type, str);
478 klass = mono_class_from_mono_type (type);
479 if (klass->nested_in) {
480 mono_type_get_name_recurse (
481 &klass->nested_in->byval_arg, str, TRUE, format);
482 if (format == MONO_TYPE_NAME_FORMAT_IL)
483 g_string_append_c (str, '.');
485 g_string_append_c (str, '+');
486 } else if (*klass->name_space) {
487 if (format == MONO_TYPE_NAME_FORMAT_IL)
488 g_string_append (str, klass->name_space);
490 mono_identifier_escape_type_name_chars (str, klass->name_space);
491 g_string_append_c (str, '.');
493 if (format == MONO_TYPE_NAME_FORMAT_IL) {
494 char *s = strchr (klass->name, '`');
495 int len = s ? s - klass->name : strlen (klass->name);
496 g_string_append_len (str, klass->name, len);
498 mono_identifier_escape_type_name_chars (str, klass->name);
502 if (klass->generic_class) {
503 MonoGenericClass *gclass = klass->generic_class;
504 MonoGenericInst *inst = gclass->context.class_inst;
505 MonoTypeNameFormat nested_format;
508 nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
509 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
511 if (format == MONO_TYPE_NAME_FORMAT_IL)
512 g_string_append_c (str, '<');
514 g_string_append_c (str, '[');
515 for (i = 0; i < inst->type_argc; i++) {
516 MonoType *t = inst->type_argv [i];
519 g_string_append_c (str, ',');
520 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
521 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
522 g_string_append_c (str, '[');
523 mono_type_get_name_recurse (inst->type_argv [i], str, FALSE, nested_format);
524 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
525 (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
526 g_string_append_c (str, ']');
528 if (format == MONO_TYPE_NAME_FORMAT_IL)
529 g_string_append_c (str, '>');
531 g_string_append_c (str, ']');
532 } else if (klass->generic_container &&
533 (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
534 (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
537 if (format == MONO_TYPE_NAME_FORMAT_IL)
538 g_string_append_c (str, '<');
540 g_string_append_c (str, '[');
541 for (i = 0; i < klass->generic_container->type_argc; i++) {
543 g_string_append_c (str, ',');
544 g_string_append (str, mono_generic_container_get_param_info (klass->generic_container, i)->name);
546 if (format == MONO_TYPE_NAME_FORMAT_IL)
547 g_string_append_c (str, '>');
549 g_string_append_c (str, ']');
552 mono_type_name_check_byref (type, str);
554 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
555 (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
556 _mono_type_get_assembly_name (klass, str);
562 * mono_type_get_name_full:
564 * @format: the format for the return string.
567 * Returns: The string representation in a number of formats:
569 * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
570 * returned in the formatrequired by System.Reflection, this is the
571 * inverse of mono_reflection_parse_type ().
573 * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
574 * be used by the IL assembler.
576 * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
578 * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
581 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
585 result = g_string_new ("");
587 mono_type_get_name_recurse (type, result, FALSE, format);
589 return g_string_free (result, FALSE);
593 * mono_type_get_full_name:
596 * Returns: The string representation for type as required by System.Reflection.
597 * The inverse of mono_reflection_parse_type ().
600 mono_type_get_full_name (MonoClass *klass)
602 return mono_type_get_name_full (mono_class_get_type (klass), MONO_TYPE_NAME_FORMAT_REFLECTION);
606 * mono_type_get_name:
609 * Returns: The string representation for type as it would be represented in IL code.
612 mono_type_get_name (MonoType *type)
614 return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
618 * mono_type_get_underlying_type:
621 * Returns: The MonoType for the underlying integer type if @type
622 * is an enum and byref is false, otherwise the type itself.
625 mono_type_get_underlying_type (MonoType *type)
627 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype && !type->byref)
628 return mono_class_enum_basetype (type->data.klass);
629 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype && !type->byref)
630 return mono_class_enum_basetype (type->data.generic_class->container_class);
635 * mono_class_is_open_constructed_type:
638 * Returns: TRUE if type represents a generics open constructed type.
639 * IOW, not all type parameters required for the instantiation have
640 * been provided or it's a generic type definition.
642 * An open constructed type means it's a non realizable type. Not to
643 * be mixed up with an abstract type - we can't cast or dispatch to
644 * an open type, for example.
647 mono_class_is_open_constructed_type (MonoType *t)
653 case MONO_TYPE_SZARRAY:
654 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
655 case MONO_TYPE_ARRAY:
656 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
658 return mono_class_is_open_constructed_type (t->data.type);
659 case MONO_TYPE_GENERICINST:
660 return t->data.generic_class->context.class_inst->is_open;
661 case MONO_TYPE_CLASS:
662 case MONO_TYPE_VALUETYPE:
663 return t->data.klass->generic_container != NULL;
670 This is a simple function to catch the most common bad instances of generic types.
671 Specially those that might lead to further failures in the runtime.
674 is_valid_generic_argument (MonoType *type)
676 switch (type->type) {
678 //case MONO_TYPE_TYPEDBYREF:
686 inflate_generic_type (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
688 mono_error_init (error);
690 switch (type->type) {
691 case MONO_TYPE_MVAR: {
693 int num = mono_type_get_generic_param_num (type);
694 MonoGenericInst *inst = context->method_inst;
697 if (num >= inst->type_argc) {
698 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
699 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded in this context with %d instantiations",
700 num, info ? info->name : "", inst->type_argc);
704 if (!is_valid_generic_argument (inst->type_argv [num])) {
705 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
706 mono_error_set_bad_image (error, image, "MVAR %d (%s) cannot be expanded with type 0x%x",
707 num, info ? info->name : "", inst->type_argv [num]->type);
711 * Note that the VAR/MVAR cases are different from the rest. The other cases duplicate @type,
712 * while the VAR/MVAR duplicates a type from the context. So, we need to ensure that the
713 * ->byref and ->attrs from @type are propagated to the returned type.
715 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
716 nt->byref = type->byref;
717 nt->attrs = type->attrs;
720 case MONO_TYPE_VAR: {
722 int num = mono_type_get_generic_param_num (type);
723 MonoGenericInst *inst = context->class_inst;
726 if (num >= inst->type_argc) {
727 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
728 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded in this context with %d instantiations",
729 num, info ? info->name : "", inst->type_argc);
732 if (!is_valid_generic_argument (inst->type_argv [num])) {
733 MonoGenericParamInfo *info = mono_generic_param_info (type->data.generic_param);
734 mono_error_set_bad_image (error, image, "VAR %d (%s) cannot be expanded with type 0x%x",
735 num, info ? info->name : "", inst->type_argv [num]->type);
738 nt = mono_metadata_type_dup (image, inst->type_argv [num]);
739 nt->byref = type->byref;
740 nt->attrs = type->attrs;
743 case MONO_TYPE_SZARRAY: {
744 MonoClass *eclass = type->data.klass;
745 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
746 if (!inflated || !mono_error_ok (error))
748 nt = mono_metadata_type_dup (image, type);
749 nt->data.klass = mono_class_from_mono_type (inflated);
750 mono_metadata_free_type (inflated);
753 case MONO_TYPE_ARRAY: {
754 MonoClass *eclass = type->data.array->eklass;
755 MonoType *nt, *inflated = inflate_generic_type (NULL, &eclass->byval_arg, context, error);
756 if (!inflated || !mono_error_ok (error))
758 nt = mono_metadata_type_dup (image, type);
759 nt->data.array->eklass = mono_class_from_mono_type (inflated);
760 mono_metadata_free_type (inflated);
763 case MONO_TYPE_GENERICINST: {
764 MonoGenericClass *gclass = type->data.generic_class;
765 MonoGenericInst *inst;
767 if (!gclass->context.class_inst->is_open)
770 inst = mono_metadata_inflate_generic_inst (gclass->context.class_inst, context, error);
771 return_val_if_nok (error, NULL);
773 if (inst != gclass->context.class_inst)
774 gclass = mono_metadata_lookup_generic_class (gclass->container_class, inst, gclass->is_dynamic);
776 if (gclass == type->data.generic_class)
779 nt = mono_metadata_type_dup (image, type);
780 nt->data.generic_class = gclass;
783 case MONO_TYPE_CLASS:
784 case MONO_TYPE_VALUETYPE: {
785 MonoClass *klass = type->data.klass;
786 MonoGenericContainer *container = klass->generic_container;
787 MonoGenericInst *inst;
788 MonoGenericClass *gclass = NULL;
794 /* We can't use context->class_inst directly, since it can have more elements */
795 inst = mono_metadata_inflate_generic_inst (container->context.class_inst, context, error);
796 return_val_if_nok (error, NULL);
798 if (inst == container->context.class_inst)
801 gclass = mono_metadata_lookup_generic_class (klass, inst, image_is_dynamic (klass->image));
803 nt = mono_metadata_type_dup (image, type);
804 nt->type = MONO_TYPE_GENERICINST;
805 nt->data.generic_class = gclass;
815 mono_generic_class_get_context (MonoGenericClass *gclass)
817 return &gclass->context;
821 mono_class_get_context (MonoClass *klass)
823 return klass->generic_class ? mono_generic_class_get_context (klass->generic_class) : NULL;
827 * mono_class_get_generic_container:
829 * Return the generic container of KLASS which should be a generic type definition.
831 MonoGenericContainer*
832 mono_class_get_generic_container (MonoClass *klass)
834 g_assert (klass->is_generic);
836 return klass->generic_container;
840 * mono_class_get_generic_class:
842 * Return the MonoGenericClass of KLASS, which should be a generic instance.
845 mono_class_get_generic_class (MonoClass *klass)
847 g_assert (klass->is_inflated);
849 return klass->generic_class;
853 * mono_class_inflate_generic_type_with_mempool:
854 * @mempool: a mempool
856 * @context: a generics context
857 * @error: error context
859 * The same as mono_class_inflate_generic_type, but allocates the MonoType
860 * from mempool if it is non-NULL. If it is NULL, the MonoType is
861 * allocated on the heap and is owned by the caller.
862 * The returned type can potentially be the same as TYPE, so it should not be
863 * modified by the caller, and it should be freed using mono_metadata_free_type ().
866 mono_class_inflate_generic_type_with_mempool (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
868 MonoType *inflated = NULL;
869 mono_error_init (error);
872 inflated = inflate_generic_type (image, type, context, error);
873 return_val_if_nok (error, NULL);
876 MonoType *shared = mono_metadata_get_shared_type (type);
881 return mono_metadata_type_dup (image, type);
885 mono_stats.inflated_type_count++;
890 * mono_class_inflate_generic_type:
892 * @context: a generics context
894 * If @type is a generic type and @context is not NULL, instantiate it using the
895 * generics context @context.
897 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
898 * on the heap and is owned by the caller. Returns NULL on error.
900 * @deprecated Please use mono_class_inflate_generic_type_checked instead
903 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
907 result = mono_class_inflate_generic_type_checked (type, context, &error);
909 if (!mono_error_ok (&error)) {
910 mono_error_cleanup (&error);
917 * mono_class_inflate_generic_type:
919 * @context: a generics context
920 * @error: error context to use
922 * If @type is a generic type and @context is not NULL, instantiate it using the
923 * generics context @context.
925 * Returns: The instantiated type or a copy of @type. The returned MonoType is allocated
926 * on the heap and is owned by the caller.
929 mono_class_inflate_generic_type_checked (MonoType *type, MonoGenericContext *context, MonoError *error)
931 return mono_class_inflate_generic_type_with_mempool (NULL, type, context, error);
935 * mono_class_inflate_generic_type_no_copy:
937 * Same as inflate_generic_type_with_mempool, but return TYPE if no inflation
941 mono_class_inflate_generic_type_no_copy (MonoImage *image, MonoType *type, MonoGenericContext *context, MonoError *error)
943 MonoType *inflated = NULL;
945 mono_error_init (error);
947 inflated = inflate_generic_type (image, type, context, error);
948 return_val_if_nok (error, NULL);
954 mono_stats.inflated_type_count++;
959 mono_class_inflate_generic_class_checked (MonoClass *gklass, MonoGenericContext *context, MonoError *error)
964 inflated = mono_class_inflate_generic_type_checked (&gklass->byval_arg, context, error);
965 return_val_if_nok (error, NULL);
967 res = mono_class_from_mono_type (inflated);
968 mono_metadata_free_type (inflated);
973 * mono_class_inflate_generic_class:
975 * Inflate the class GKLASS with CONTEXT.
978 mono_class_inflate_generic_class (MonoClass *gklass, MonoGenericContext *context)
983 res = mono_class_inflate_generic_class_checked (gklass, context, &error);
984 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
991 static MonoGenericContext
992 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with, MonoError *error)
994 MonoGenericInst *class_inst = NULL;
995 MonoGenericInst *method_inst = NULL;
996 MonoGenericContext res = { NULL, NULL };
998 mono_error_init (error);
1000 if (context->class_inst) {
1001 class_inst = mono_metadata_inflate_generic_inst (context->class_inst, inflate_with, error);
1002 if (!mono_error_ok (error))
1006 if (context->method_inst) {
1007 method_inst = mono_metadata_inflate_generic_inst (context->method_inst, inflate_with, error);
1008 if (!mono_error_ok (error))
1012 res.class_inst = class_inst;
1013 res.method_inst = method_inst;
1019 * mono_class_inflate_generic_method:
1020 * @method: a generic method
1021 * @context: a generics context
1023 * Instantiate the generic method @method using the generics context @context.
1025 * Returns: The new instantiated method
1028 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
1030 return mono_class_inflate_generic_method_full (method, NULL, context);
1034 mono_class_inflate_generic_method_checked (MonoMethod *method, MonoGenericContext *context, MonoError *error)
1036 return mono_class_inflate_generic_method_full_checked (method, NULL, context, error);
1040 * mono_class_inflate_generic_method_full:
1042 * Instantiate method @method with the generic context @context.
1043 * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
1044 * Use mono_method_signature () and mono_method_get_header () to get the correct values.
1047 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
1050 MonoMethod *res = mono_class_inflate_generic_method_full_checked (method, klass_hint, context, &error);
1051 if (!mono_error_ok (&error))
1052 /*FIXME do proper error handling - on this case, kill this function. */
1053 g_error ("Could not inflate generic method due to %s", mono_error_get_message (&error));
1059 * mono_class_inflate_generic_method_full_checked:
1060 * Same as mono_class_inflate_generic_method_full but return failure using @error.
1063 mono_class_inflate_generic_method_full_checked (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context, MonoError *error)
1066 MonoMethodInflated *iresult, *cached;
1067 MonoMethodSignature *sig;
1068 MonoGenericContext tmp_context;
1070 mono_error_init (error);
1072 /* The `method' has already been instantiated before => we need to peel out the instantiation and create a new context */
1073 while (method->is_inflated) {
1074 MonoGenericContext *method_context = mono_method_get_context (method);
1075 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1077 tmp_context = inflate_generic_context (method_context, context, error);
1078 return_val_if_nok (error, NULL);
1080 context = &tmp_context;
1082 if (mono_metadata_generic_context_equal (method_context, context))
1085 method = imethod->declaring;
1089 * A method only needs to be inflated if the context has argument for which it is
1092 * class Foo<T> { void Bar(); } - doesn't need to be inflated if only mvars' are supplied
1093 * class Foo { void Bar<T> (); } - doesn't need to be if only vars' are supplied
1096 if (!((method->is_generic && context->method_inst) ||
1097 (method->klass->generic_container && context->class_inst)))
1100 iresult = g_new0 (MonoMethodInflated, 1);
1101 iresult->context = *context;
1102 iresult->declaring = method;
1104 if (!context->method_inst && method->is_generic)
1105 iresult->context.method_inst = mono_method_get_generic_container (method)->context.method_inst;
1107 if (!context->class_inst) {
1108 g_assert (!iresult->declaring->klass->generic_class);
1109 if (iresult->declaring->klass->generic_container)
1110 iresult->context.class_inst = iresult->declaring->klass->generic_container->context.class_inst;
1111 else if (iresult->declaring->klass->generic_class)
1112 iresult->context.class_inst = iresult->declaring->klass->generic_class->context.class_inst;
1114 /* This can happen with some callers like mono_object_get_virtual_method () */
1115 if (!iresult->declaring->klass->generic_container && !iresult->declaring->klass->generic_class)
1116 iresult->context.class_inst = NULL;
1118 MonoImageSet *set = mono_metadata_get_image_set_for_method (iresult);
1121 mono_image_set_lock (set);
1122 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1123 mono_image_set_unlock (set);
1127 return (MonoMethod*)cached;
1130 mono_stats.inflated_method_count++;
1132 inflated_methods_size += sizeof (MonoMethodInflated);
1134 sig = mono_method_signature (method);
1136 char *name = mono_type_get_full_name (method->klass);
1137 mono_error_set_bad_image (error, method->klass->image, "Could not resolve signature of method %s:%s", name, method->name);
1143 memcpy (&iresult->method.pinvoke, method, sizeof (MonoMethodPInvoke));
1145 memcpy (&iresult->method.method, method, sizeof (MonoMethod));
1148 result = (MonoMethod *) iresult;
1149 result->is_inflated = TRUE;
1150 result->is_generic = FALSE;
1151 result->sre_method = FALSE;
1152 result->signature = NULL;
1154 if (!context->method_inst) {
1155 /* Set the generic_container of the result to the generic_container of method */
1156 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
1158 if (generic_container) {
1159 result->is_generic = 1;
1160 mono_method_set_generic_container (result, generic_container);
1164 if (!klass_hint || !klass_hint->generic_class ||
1165 klass_hint->generic_class->container_class != method->klass ||
1166 klass_hint->generic_class->context.class_inst != context->class_inst)
1169 if (method->klass->generic_container)
1170 result->klass = klass_hint;
1172 if (!result->klass) {
1173 MonoType *inflated = inflate_generic_type (NULL, &method->klass->byval_arg, context, error);
1174 if (!mono_error_ok (error))
1177 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
1179 mono_metadata_free_type (inflated);
1183 * FIXME: This should hold, but it doesn't:
1185 * if (result->is_inflated && mono_method_get_context (result)->method_inst &&
1186 * mono_method_get_context (result)->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)result)->declaring)->context.method_inst) {
1187 * g_assert (result->is_generic);
1190 * Fixing this here causes other things to break, hence a very
1191 * ugly hack in mini-trampolines.c - see
1192 * is_generic_method_definition().
1196 mono_image_set_lock (set);
1197 cached = (MonoMethodInflated *)g_hash_table_lookup (set->gmethod_cache, iresult);
1199 g_hash_table_insert (set->gmethod_cache, iresult, iresult);
1200 iresult->owner = set;
1203 mono_image_set_unlock (set);
1205 return (MonoMethod*)cached;
1213 * mono_get_inflated_method:
1215 * Obsolete. We keep it around since it's mentioned in the public API.
1218 mono_get_inflated_method (MonoMethod *method)
1224 * mono_method_get_context_general:
1226 * @uninflated: handle uninflated methods?
1228 * Returns the generic context of a method or NULL if it doesn't have
1229 * one. For an inflated method that's the context stored in the
1230 * method. Otherwise it's in the method's generic container or in the
1231 * generic container of the method's class.
1234 mono_method_get_context_general (MonoMethod *method, gboolean uninflated)
1236 if (method->is_inflated) {
1237 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
1238 return &imethod->context;
1242 if (method->is_generic)
1243 return &(mono_method_get_generic_container (method)->context);
1244 if (method->klass->generic_container)
1245 return &method->klass->generic_container->context;
1250 * mono_method_get_context:
1253 * Returns the generic context for method if it's inflated, otherwise
1257 mono_method_get_context (MonoMethod *method)
1259 return mono_method_get_context_general (method, FALSE);
1263 * mono_method_get_generic_container:
1265 * Returns the generic container of METHOD, which should be a generic method definition.
1266 * Returns NULL if METHOD is not a generic method definition.
1267 * LOCKING: Acquires the loader lock.
1269 MonoGenericContainer*
1270 mono_method_get_generic_container (MonoMethod *method)
1272 MonoGenericContainer *container;
1274 if (!method->is_generic)
1277 container = (MonoGenericContainer *)mono_image_property_lookup (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER);
1278 g_assert (container);
1284 * mono_method_set_generic_container:
1286 * Sets the generic container of METHOD to CONTAINER.
1287 * LOCKING: Acquires the image lock.
1290 mono_method_set_generic_container (MonoMethod *method, MonoGenericContainer* container)
1292 g_assert (method->is_generic);
1294 mono_image_property_insert (method->klass->image, method, MONO_METHOD_PROP_GENERIC_CONTAINER, container);
1298 * mono_class_find_enum_basetype:
1299 * @class: The enum class
1301 * Determine the basetype of an enum by iterating through its fields. We do this
1302 * in a separate function since it is cheaper than calling mono_class_setup_fields.
1305 mono_class_find_enum_basetype (MonoClass *klass, MonoError *error)
1307 MonoGenericContainer *container = NULL;
1308 MonoImage *m = klass->image;
1309 const int top = klass->field.count;
1312 g_assert (klass->enumtype);
1314 mono_error_init (error);
1316 if (klass->generic_container)
1317 container = klass->generic_container;
1318 else if (klass->generic_class) {
1319 MonoClass *gklass = klass->generic_class->container_class;
1321 container = gklass->generic_container;
1322 g_assert (container);
1326 * Fetch all the field information.
1328 for (i = 0; i < top; i++){
1330 guint32 cols [MONO_FIELD_SIZE];
1331 int idx = klass->field.first + i;
1334 /* klass->field.first and idx points into the fieldptr table */
1335 mono_metadata_decode_table_row (m, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
1337 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC) //no need to decode static fields
1340 if (!mono_verifier_verify_field_signature (klass->image, cols [MONO_FIELD_SIGNATURE], NULL)) {
1341 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x", cols [MONO_FIELD_SIGNATURE]);
1345 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
1346 mono_metadata_decode_value (sig, &sig);
1347 /* FIELD signature == 0x06 */
1349 mono_error_set_bad_image (error, klass->image, "Invalid field signature %x, expected 0x6 but got %x", cols [MONO_FIELD_SIGNATURE], *sig);
1353 ftype = mono_metadata_parse_type_full (m, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
1355 if (mono_loader_get_last_error ()) /*FIXME plug the above to not leak errors*/
1356 mono_error_set_from_loader_error (error);
1358 mono_error_set_bad_image (error, klass->image, "Could not parse type for field signature %x", cols [MONO_FIELD_SIGNATURE]);
1361 if (klass->generic_class) {
1362 //FIXME do we leak here?
1363 ftype = mono_class_inflate_generic_type_checked (ftype, mono_class_get_context (klass), error);
1364 if (!mono_error_ok (error))
1366 ftype->attrs = cols [MONO_FIELD_FLAGS];
1371 mono_error_set_type_load_class (error, klass, "Could not find base type");
1374 mono_loader_assert_no_error ();
1379 * Checks for MonoClass::exception_type without resolving all MonoType's into MonoClass'es
1382 mono_type_has_exceptions (MonoType *type)
1384 switch (type->type) {
1385 case MONO_TYPE_CLASS:
1386 case MONO_TYPE_VALUETYPE:
1387 case MONO_TYPE_SZARRAY:
1388 return type->data.klass->exception_type;
1389 case MONO_TYPE_ARRAY:
1390 return type->data.array->eklass->exception_type;
1391 case MONO_TYPE_GENERICINST:
1392 return mono_generic_class_get_class (type->data.generic_class)->exception_type;
1401 * Allocate memory for some data belonging to CLASS, either from its image's mempool,
1405 mono_class_alloc (MonoClass *klass, int size)
1407 if (klass->generic_class)
1408 return mono_image_set_alloc (klass->generic_class->owner, size);
1410 return mono_image_alloc (klass->image, size);
1414 mono_class_alloc0 (MonoClass *klass, int size)
1418 res = mono_class_alloc (klass, size);
1419 memset (res, 0, size);
1423 #define mono_class_new0(klass,struct_type, n_structs) \
1424 ((struct_type *) mono_class_alloc0 ((klass), ((gsize) sizeof (struct_type)) * ((gsize) (n_structs))))
1427 * mono_class_setup_basic_field_info:
1428 * @class: The class to initialize
1430 * Initializes the klass->fields.
1431 * LOCKING: Assumes the loader lock is held.
1434 mono_class_setup_basic_field_info (MonoClass *klass)
1436 MonoClassField *field;
1444 gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1445 image = klass->image;
1446 top = klass->field.count;
1448 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1450 * This happens when a generic instance of an unfinished generic typebuilder
1451 * is used as an element type for creating an array type. We can't initialize
1452 * the fields of this class using the fields of gklass, since gklass is not
1453 * finished yet, fields could be added to it later.
1459 mono_class_setup_basic_field_info (gtd);
1461 top = gtd->field.count;
1462 klass->field.first = gtd->field.first;
1463 klass->field.count = gtd->field.count;
1466 klass->fields = (MonoClassField *)mono_class_alloc0 (klass, sizeof (MonoClassField) * top);
1469 * Fetch all the field information.
1471 for (i = 0; i < top; i++){
1472 field = &klass->fields [i];
1473 field->parent = klass;
1476 field->name = mono_field_get_name (>d->fields [i]);
1478 int idx = klass->field.first + i;
1479 /* klass->field.first and idx points into the fieldptr table */
1480 guint32 name_idx = mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_NAME);
1481 /* The name is needed for fieldrefs */
1482 field->name = mono_metadata_string_heap (image, name_idx);
1488 * mono_class_setup_fields:
1489 * @class: The class to initialize
1491 * Initializes the klass->fields.
1492 * LOCKING: Assumes the loader lock is held.
1495 mono_class_setup_fields (MonoClass *klass)
1498 MonoImage *m = klass->image;
1500 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1501 int i, blittable = TRUE;
1502 guint32 real_size = 0;
1503 guint32 packing_size = 0;
1504 gboolean explicit_size;
1505 MonoClassField *field;
1506 MonoGenericContainer *container = NULL;
1507 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
1510 * FIXME: We have a race condition here. It's possible that this function returns
1511 * to its caller with `instance_size` set to `0` instead of the actual size. This
1512 * is not a problem when the function is called recursively on the same class,
1513 * because the size will be initialized by the outer invocation. What follows is a
1514 * description of how it can occur in other cases, too. There it is a problem,
1515 * because it can lead to the GC being asked to allocate an object of size `0`,
1516 * which SGen chokes on. The race condition is triggered infrequently by
1517 * `tests/sgen-suspend.cs`.
1519 * This function is called for a class whenever one of its subclasses is inited.
1520 * For example, it's called for every subclass of Object. What it does is this:
1522 * if (klass->setup_fields_called)
1525 * klass->instance_size = 0;
1527 * klass->setup_fields_called = 1;
1528 * ... critical point
1529 * klass->instance_size = actual_instance_size;
1531 * The last two steps are sometimes reversed, but that only changes the way in which
1532 * the race condition works.
1534 * Assume thread A goes through this function and makes it to the critical point.
1535 * Now thread B runs the function and, since `setup_fields_called` is set, returns
1536 * immediately, but `instance_size` is incorrect.
1538 * The other case looks like this:
1540 * if (klass->setup_fields_called)
1542 * ... critical point X
1543 * klass->instance_size = 0;
1544 * ... critical point Y
1545 * klass->instance_size = actual_instance_size;
1547 * klass->setup_fields_called = 1;
1549 * Assume thread A goes through the function and makes it to critical point X. Now
1550 * thread B runs through the whole of the function, returning, assuming
1551 * `instance_size` is set. At that point thread A gets to run and makes it to
1552 * critical point Y, at which time `instance_size` is `0` again, invalidating thread
1555 if (klass->setup_fields_called)
1558 if (klass->generic_class && image_is_dynamic (klass->generic_class->container_class->image) && !klass->generic_class->container_class->wastypebuilder) {
1560 * This happens when a generic instance of an unfinished generic typebuilder
1561 * is used as an element type for creating an array type. We can't initialize
1562 * the fields of this class using the fields of gklass, since gklass is not
1563 * finished yet, fields could be added to it later.
1568 mono_class_setup_basic_field_info (klass);
1569 top = klass->field.count;
1572 mono_class_setup_fields (gtd);
1573 if (gtd->exception_type) {
1574 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1579 klass->instance_size = 0;
1581 klass->sizes.class_size = 0;
1583 if (klass->parent) {
1584 /* For generic instances, klass->parent might not have been initialized */
1585 mono_class_init (klass->parent);
1586 if (!klass->parent->size_inited) {
1587 mono_class_setup_fields (klass->parent);
1588 if (klass->parent->exception_type) {
1589 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1593 klass->instance_size += klass->parent->instance_size;
1594 klass->min_align = klass->parent->min_align;
1595 /* we use |= since it may have been set already */
1596 klass->has_references |= klass->parent->has_references;
1597 blittable = klass->parent->blittable;
1599 klass->instance_size = sizeof (MonoObject);
1600 klass->min_align = 1;
1603 /* We can't really enable 16 bytes alignment until the GC supports it.
1604 The whole layout/instance size code must be reviewed because we do alignment calculation in terms of the
1605 boxed instance, which leads to unexplainable holes at the beginning of an object embedding a simd type.
1606 Bug #506144 is an example of this issue.
1608 if (klass->simd_type)
1609 klass->min_align = 16;
1611 /* Get the real size */
1612 explicit_size = mono_metadata_packing_from_typedef (klass->image, klass->type_token, &packing_size, &real_size);
1614 if (explicit_size) {
1615 if ((packing_size & 0xffffff00) != 0) {
1616 char *err_msg = g_strdup_printf ("Could not load struct '%s' with packing size %d >= 256", klass->name, packing_size);
1617 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
1620 klass->packing_size = packing_size;
1621 real_size += klass->instance_size;
1625 if (explicit_size && real_size) {
1626 klass->instance_size = MAX (real_size, klass->instance_size);
1628 klass->blittable = blittable;
1629 mono_memory_barrier ();
1630 klass->size_inited = 1;
1631 klass->fields_inited = 1;
1632 klass->setup_fields_called = 1;
1636 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT && !(mono_is_corlib_image (klass->image) && !strcmp (klass->name_space, "System") && !strcmp (klass->name, "ValueType")))
1639 /* Prevent infinite loops if the class references itself */
1640 klass->setup_fields_called = 1;
1642 if (klass->generic_container) {
1643 container = klass->generic_container;
1645 container = gtd->generic_container;
1646 g_assert (container);
1650 * Fetch all the field information.
1652 for (i = 0; i < top; i++){
1653 int idx = klass->field.first + i;
1654 field = &klass->fields [i];
1656 field->parent = klass;
1659 mono_field_resolve_type (field, &error);
1660 if (!mono_error_ok (&error)) {
1661 /*mono_field_resolve_type already failed class*/
1662 mono_error_cleanup (&error);
1666 g_error ("could not resolve %s:%s\n", mono_type_get_full_name(klass), field->name);
1667 g_assert (field->type);
1670 if (mono_field_is_deleted (field))
1673 MonoClassField *gfield = >d->fields [i];
1674 field->offset = gfield->offset;
1676 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
1678 mono_metadata_field_info (m, idx, &offset, NULL, NULL);
1679 field->offset = offset;
1681 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1682 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Missing field layout info for %s", field->name));
1685 if (field->offset < -1) { /*-1 is used to encode special static fields */
1686 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Invalid negative field offset %d for %s", field->offset, field->name));
1689 if (klass->generic_container) {
1690 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic class cannot have explicit layout."));
1696 /* Only do these checks if we still think this type is blittable */
1697 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1698 if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
1701 MonoClass *field_class = mono_class_from_mono_type (field->type);
1703 mono_class_setup_fields (field_class);
1704 if (field_class->exception_type) {
1705 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1709 if (!field_class || !field_class->blittable)
1714 if (klass->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1715 klass->cast_class = klass->element_class = mono_class_from_mono_type (field->type);
1716 blittable = klass->element_class->blittable;
1719 if (mono_type_has_exceptions (field->type)) {
1720 char *class_name = mono_type_get_full_name (klass);
1721 char *type_name = mono_type_full_name (field->type);
1723 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1724 g_warning ("Invalid type %s for instance field %s:%s", type_name, class_name, field->name);
1725 g_free (class_name);
1729 /* The def_value of fields is compute lazily during vtable creation */
1732 if (klass == mono_defaults.string_class)
1735 klass->blittable = blittable;
1737 if (klass->enumtype && !mono_class_enum_basetype (klass)) {
1738 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1741 if (explicit_size && real_size) {
1742 klass->instance_size = MAX (real_size, klass->instance_size);
1745 if (klass->exception_type)
1747 mono_class_layout_fields (klass);
1749 /*valuetypes can't be neither bigger than 1Mb or empty. */
1750 if (klass->valuetype && (klass->instance_size <= 0 || klass->instance_size > (0x100000 + sizeof (MonoObject))))
1751 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1753 mono_memory_barrier ();
1754 klass->fields_inited = 1;
1758 * mono_class_setup_fields_locking:
1759 * @class: The class to initialize
1761 * Initializes the klass->fields array of fields.
1762 * Aquires the loader lock.
1765 mono_class_setup_fields_locking (MonoClass *klass)
1767 /* This can be checked without locks */
1768 if (klass->fields_inited)
1770 mono_loader_lock ();
1771 mono_class_setup_fields (klass);
1772 mono_loader_unlock ();
1776 * mono_class_has_references:
1778 * Returns whenever @klass->has_references is set, initializing it if needed.
1779 * Aquires the loader lock.
1782 mono_class_has_references (MonoClass *klass)
1784 if (klass->init_pending) {
1785 /* Be conservative */
1788 mono_class_init (klass);
1790 return klass->has_references;
1795 * mono_type_get_basic_type_from_generic:
1798 * Returns a closed type corresponding to the possibly open type
1802 mono_type_get_basic_type_from_generic (MonoType *type)
1804 /* When we do generic sharing we let type variables stand for reference/primitive types. */
1805 if (!type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR) &&
1806 (!type->data.generic_param->gshared_constraint || type->data.generic_param->gshared_constraint->type == MONO_TYPE_OBJECT))
1807 return &mono_defaults.object_class->byval_arg;
1812 type_has_references (MonoClass *klass, MonoType *ftype)
1814 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (klass, ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
1816 if (!ftype->byref && (ftype->type == MONO_TYPE_VAR || ftype->type == MONO_TYPE_MVAR)) {
1817 MonoGenericParam *gparam = ftype->data.generic_param;
1819 if (gparam->gshared_constraint)
1820 return mono_class_has_references (mono_class_from_mono_type (gparam->gshared_constraint));
1826 * mono_class_layout_fields:
1829 * Compute the placement of fields inside an object or struct, according to
1830 * the layout rules and set the following fields in @class:
1831 * - has_references (if the class contains instance references firled or structs that contain references)
1832 * - has_static_refs (same, but for static fields)
1833 * - instance_size (size of the object in memory)
1834 * - class_size (size needed for the static fields)
1835 * - size_inited (flag set when the instance_size is set)
1837 * LOCKING: this is supposed to be called with the loader lock held.
1840 mono_class_layout_fields (MonoClass *klass)
1843 const int top = klass->field.count;
1844 guint32 layout = klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
1845 guint32 pass, passes, real_size;
1846 gboolean gc_aware_layout = FALSE;
1847 gboolean has_static_fields = FALSE;
1848 MonoClassField *field;
1851 * When we do generic sharing we need to have layout
1852 * information for open generic classes (either with a generic
1853 * context containing type variables or with a generic
1854 * container), so we don't return in that case anymore.
1858 * Enable GC aware auto layout: in this mode, reference
1859 * fields are grouped together inside objects, increasing collector
1861 * Requires that all classes whose layout is known to native code be annotated
1862 * with [StructLayout (LayoutKind.Sequential)]
1863 * Value types have gc_aware_layout disabled by default, as per
1864 * what the default is for other runtimes.
1866 /* corlib is missing [StructLayout] directives in many places */
1867 if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
1868 if (!klass->valuetype)
1869 gc_aware_layout = TRUE;
1872 /* Compute klass->has_references */
1874 * Process non-static fields first, since static fields might recursively
1875 * refer to the class itself.
1877 for (i = 0; i < top; i++) {
1880 field = &klass->fields [i];
1882 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
1883 ftype = mono_type_get_underlying_type (field->type);
1884 ftype = mono_type_get_basic_type_from_generic (ftype);
1885 if (type_has_references (klass, ftype))
1886 klass->has_references = TRUE;
1890 for (i = 0; i < top; i++) {
1893 field = &klass->fields [i];
1895 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1896 ftype = mono_type_get_underlying_type (field->type);
1897 ftype = mono_type_get_basic_type_from_generic (ftype);
1898 if (type_has_references (klass, ftype))
1899 klass->has_static_refs = TRUE;
1903 for (i = 0; i < top; i++) {
1906 field = &klass->fields [i];
1908 ftype = mono_type_get_underlying_type (field->type);
1909 ftype = mono_type_get_basic_type_from_generic (ftype);
1910 if (type_has_references (klass, ftype)) {
1911 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1912 klass->has_static_refs = TRUE;
1914 klass->has_references = TRUE;
1919 * Compute field layout and total size (not considering static fields)
1923 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1924 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1926 if (gc_aware_layout)
1931 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1934 if (klass->parent) {
1935 mono_class_setup_fields (klass->parent);
1936 if (klass->parent->exception_type) {
1937 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
1940 real_size = klass->parent->instance_size;
1942 real_size = sizeof (MonoObject);
1945 for (pass = 0; pass < passes; ++pass) {
1946 for (i = 0; i < top; i++){
1951 field = &klass->fields [i];
1953 if (mono_field_is_deleted (field))
1955 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1958 ftype = mono_type_get_underlying_type (field->type);
1959 ftype = mono_type_get_basic_type_from_generic (ftype);
1960 if (gc_aware_layout) {
1961 if (type_has_references (klass, ftype)) {
1970 if ((top == 1) && (klass->instance_size == sizeof (MonoObject)) &&
1971 (strcmp (mono_field_get_name (field), "$PRIVATE$") == 0)) {
1972 /* This field is a hack inserted by MCS to empty structures */
1976 size = mono_type_size (field->type, &align);
1978 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1979 align = klass->packing_size ? MIN (klass->packing_size, align): align;
1980 /* if the field has managed references, we need to force-align it
1983 if (type_has_references (klass, ftype))
1984 align = MAX (align, sizeof (gpointer));
1986 klass->min_align = MAX (align, klass->min_align);
1987 field->offset = real_size;
1989 field->offset += align - 1;
1990 field->offset &= ~(align - 1);
1992 /*TypeBuilders produce all sort of weird things*/
1993 g_assert (image_is_dynamic (klass->image) || field->offset > 0);
1994 real_size = field->offset + size;
1997 klass->instance_size = MAX (real_size, klass->instance_size);
1999 if (klass->instance_size & (klass->min_align - 1)) {
2000 klass->instance_size += klass->min_align - 1;
2001 klass->instance_size &= ~(klass->min_align - 1);
2005 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT: {
2009 for (i = 0; i < top; i++) {
2014 field = &klass->fields [i];
2017 * There must be info about all the fields in a type if it
2018 * uses explicit layout.
2020 if (mono_field_is_deleted (field))
2022 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2025 size = mono_type_size (field->type, &align);
2026 align = klass->packing_size ? MIN (klass->packing_size, align): align;
2027 klass->min_align = MAX (align, klass->min_align);
2030 * When we get here, field->offset is already set by the
2031 * loader (for either runtime fields or fields loaded from metadata).
2032 * The offset is from the start of the object: this works for both
2033 * classes and valuetypes.
2035 field->offset += sizeof (MonoObject);
2036 ftype = mono_type_get_underlying_type (field->type);
2037 ftype = mono_type_get_basic_type_from_generic (ftype);
2038 if (type_has_references (klass, ftype)) {
2039 if (field->offset % sizeof (gpointer)) {
2040 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2047 real_size = MAX (real_size, size + field->offset);
2050 if (klass->has_references) {
2051 ref_bitmap = g_new0 (guint8, real_size / sizeof (gpointer));
2053 /* Check for overlapping reference and non-reference fields */
2054 for (i = 0; i < top; i++) {
2057 field = &klass->fields [i];
2059 if (mono_field_is_deleted (field))
2061 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2063 ftype = mono_type_get_underlying_type (field->type);
2064 if (MONO_TYPE_IS_REFERENCE (ftype))
2065 ref_bitmap [field->offset / sizeof (gpointer)] = 1;
2067 for (i = 0; i < top; i++) {
2068 field = &klass->fields [i];
2070 if (mono_field_is_deleted (field))
2072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
2075 // FIXME: Too much code does this
2077 if (!MONO_TYPE_IS_REFERENCE (field->type) && ref_bitmap [field->offset / sizeof (gpointer)]) {
2078 char *err_msg = g_strdup_printf ("Could not load type '%s' because it contains an object field at offset %d that is incorrectly aligned or overlapped by a non-object field.", klass->name, field->offset);
2079 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
2083 g_free (ref_bitmap);
2086 klass->instance_size = MAX (real_size, klass->instance_size);
2087 if (klass->instance_size & (klass->min_align - 1)) {
2088 klass->instance_size += klass->min_align - 1;
2089 klass->instance_size &= ~(klass->min_align - 1);
2095 if (layout != TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
2097 * This leads to all kinds of problems with nested structs, so only
2098 * enable it when a MONO_DEBUG property is set.
2100 * For small structs, set min_align to at least the struct size to improve
2101 * performance, and since the JIT memset/memcpy code assumes this and generates
2102 * unaligned accesses otherwise. See #78990 for a testcase.
2104 if (mono_align_small_structs) {
2105 if (klass->instance_size <= sizeof (MonoObject) + sizeof (gpointer))
2106 klass->min_align = MAX (klass->min_align, klass->instance_size - sizeof (MonoObject));
2110 mono_memory_barrier ();
2111 klass->size_inited = 1;
2114 * Compute static field layout and size
2116 for (i = 0; i < top; i++){
2120 field = &klass->fields [i];
2122 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
2124 if (mono_field_is_deleted (field))
2127 if (mono_type_has_exceptions (field->type)) {
2128 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
2132 has_static_fields = TRUE;
2134 size = mono_type_size (field->type, &align);
2135 field->offset = klass->sizes.class_size;
2136 /*align is always non-zero here*/
2137 field->offset += align - 1;
2138 field->offset &= ~(align - 1);
2139 klass->sizes.class_size = field->offset + size;
2142 if (has_static_fields && klass->sizes.class_size == 0)
2143 /* Simplify code which depends on class_size != 0 if the class has static fields */
2144 klass->sizes.class_size = 8;
2148 create_array_method (MonoClass *klass, const char *name, MonoMethodSignature *sig)
2152 method = (MonoMethod *) mono_image_alloc0 (klass->image, sizeof (MonoMethodPInvoke));
2153 method->klass = klass;
2154 method->flags = METHOD_ATTRIBUTE_PUBLIC;
2155 method->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2156 method->signature = sig;
2157 method->name = name;
2160 if (name [0] == '.') {
2161 method->flags |= METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2163 method->iflags |= METHOD_IMPL_ATTRIBUTE_RUNTIME;
2169 * mono_class_setup_methods:
2172 * Initializes the 'methods' array in CLASS.
2173 * Calling this method should be avoided if possible since it allocates a lot
2174 * of long-living MonoMethod structures.
2175 * Methods belonging to an interface are assigned a sequential slot starting
2178 * On failure this function sets klass->exception_type
2181 mono_class_setup_methods (MonoClass *klass)
2184 MonoMethod **methods;
2189 if (klass->generic_class) {
2191 MonoClass *gklass = klass->generic_class->container_class;
2193 mono_class_init (gklass);
2194 if (!gklass->exception_type)
2195 mono_class_setup_methods (gklass);
2196 if (gklass->exception_type) {
2197 /* FIXME make exception_data less opaque so it's possible to dup it here */
2198 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2202 /* The + 1 makes this always non-NULL to pass the check in mono_class_setup_methods () */
2203 count = gklass->method.count;
2204 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * (count + 1));
2206 for (i = 0; i < count; i++) {
2207 methods [i] = mono_class_inflate_generic_method_full_checked (
2208 gklass->methods [i], klass, mono_class_get_context (klass), &error);
2209 if (!mono_error_ok (&error)) {
2210 char *method = mono_method_full_name (gklass->methods [i], TRUE);
2211 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not inflate method %s due to %s", method, mono_error_get_message (&error)));
2214 mono_error_cleanup (&error);
2218 } else if (klass->rank) {
2220 MonoMethod *amethod;
2221 MonoMethodSignature *sig;
2222 int count_generic = 0, first_generic = 0;
2224 gboolean jagged_ctor = FALSE;
2226 count = 3 + (klass->rank > 1? 2: 1);
2228 mono_class_setup_interfaces (klass, &error);
2229 g_assert (mono_error_ok (&error)); /*FIXME can this fail for array types?*/
2231 if (klass->rank == 1 && klass->element_class->rank) {
2233 klass->method.count ++;
2236 if (klass->interface_count) {
2237 count_generic = generic_array_methods (klass);
2238 first_generic = count;
2239 count += klass->interface_count * count_generic;
2242 methods = (MonoMethod **)mono_class_alloc0 (klass, sizeof (MonoMethod*) * count);
2244 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2245 sig->ret = &mono_defaults.void_class->byval_arg;
2246 sig->pinvoke = TRUE;
2247 sig->hasthis = TRUE;
2248 for (i = 0; i < klass->rank; ++i)
2249 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2251 amethod = create_array_method (klass, ".ctor", sig);
2252 methods [method_num++] = amethod;
2253 if (klass->rank > 1) {
2254 sig = mono_metadata_signature_alloc (klass->image, klass->rank * 2);
2255 sig->ret = &mono_defaults.void_class->byval_arg;
2256 sig->pinvoke = TRUE;
2257 sig->hasthis = TRUE;
2258 for (i = 0; i < klass->rank * 2; ++i)
2259 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2261 amethod = create_array_method (klass, ".ctor", sig);
2262 methods [method_num++] = amethod;
2266 /* Jagged arrays have an extra ctor in .net which creates an array of arrays */
2267 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2268 sig->ret = &mono_defaults.void_class->byval_arg;
2269 sig->pinvoke = TRUE;
2270 sig->hasthis = TRUE;
2271 for (i = 0; i < klass->rank + 1; ++i)
2272 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2273 amethod = create_array_method (klass, ".ctor", sig);
2274 methods [method_num++] = amethod;
2277 /* element Get (idx11, [idx2, ...]) */
2278 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2279 sig->ret = &klass->element_class->byval_arg;
2280 sig->pinvoke = TRUE;
2281 sig->hasthis = TRUE;
2282 for (i = 0; i < klass->rank; ++i)
2283 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2284 amethod = create_array_method (klass, "Get", sig);
2285 methods [method_num++] = amethod;
2286 /* element& Address (idx11, [idx2, ...]) */
2287 sig = mono_metadata_signature_alloc (klass->image, klass->rank);
2288 sig->ret = &klass->element_class->this_arg;
2289 sig->pinvoke = TRUE;
2290 sig->hasthis = TRUE;
2291 for (i = 0; i < klass->rank; ++i)
2292 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2293 amethod = create_array_method (klass, "Address", sig);
2294 methods [method_num++] = amethod;
2295 /* void Set (idx11, [idx2, ...], element) */
2296 sig = mono_metadata_signature_alloc (klass->image, klass->rank + 1);
2297 sig->ret = &mono_defaults.void_class->byval_arg;
2298 sig->pinvoke = TRUE;
2299 sig->hasthis = TRUE;
2300 for (i = 0; i < klass->rank; ++i)
2301 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2302 sig->params [i] = &klass->element_class->byval_arg;
2303 amethod = create_array_method (klass, "Set", sig);
2304 methods [method_num++] = amethod;
2306 for (i = 0; i < klass->interface_count; i++)
2307 setup_generic_array_ifaces (klass, klass->interfaces [i], methods, first_generic + i * count_generic);
2311 count = klass->method.count;
2312 methods = (MonoMethod **)mono_class_alloc (klass, sizeof (MonoMethod*) * count);
2313 for (i = 0; i < count; ++i) {
2314 int idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_METHOD, klass->method.first + i + 1);
2315 methods [i] = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | idx, klass, NULL, &error);
2317 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load method %d due to %s", i, mono_error_get_message (&error)));
2318 mono_error_cleanup (&error);
2323 if (MONO_CLASS_IS_INTERFACE (klass)) {
2325 /*Only assign slots to virtual methods as interfaces are allowed to have static methods.*/
2326 for (i = 0; i < count; ++i) {
2327 if (methods [i]->flags & METHOD_ATTRIBUTE_VIRTUAL)
2328 methods [i]->slot = slot++;
2332 mono_image_lock (klass->image);
2334 if (!klass->methods) {
2335 klass->method.count = count;
2337 /* Needed because of the double-checking locking pattern */
2338 mono_memory_barrier ();
2340 klass->methods = methods;
2343 mono_image_unlock (klass->image);
2347 * mono_class_get_method_by_index:
2349 * Returns klass->methods [index], initializing klass->methods if neccesary.
2351 * LOCKING: Acquires the loader lock.
2354 mono_class_get_method_by_index (MonoClass *klass, int index)
2357 /* Avoid calling setup_methods () if possible */
2358 if (klass->generic_class && !klass->methods) {
2359 MonoClass *gklass = klass->generic_class->container_class;
2362 m = mono_class_inflate_generic_method_full_checked (
2363 gklass->methods [index], klass, mono_class_get_context (klass), &error);
2364 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
2366 * If setup_methods () is called later for this class, no duplicates are created,
2367 * since inflate_generic_method guarantees that only one instance of a method
2368 * is created for each context.
2371 mono_class_setup_methods (klass);
2372 g_assert (m == klass->methods [index]);
2376 mono_class_setup_methods (klass);
2377 if (klass->exception_type) /*FIXME do proper error handling*/
2379 g_assert (index >= 0 && index < klass->method.count);
2380 return klass->methods [index];
2385 * mono_class_get_inflated_method:
2387 * Given an inflated class CLASS and a method METHOD which should be a method of
2388 * CLASS's generic definition, return the inflated method corresponding to METHOD.
2391 mono_class_get_inflated_method (MonoClass *klass, MonoMethod *method)
2393 MonoClass *gklass = klass->generic_class->container_class;
2396 g_assert (method->klass == gklass);
2398 mono_class_setup_methods (gklass);
2399 g_assert (!gklass->exception_type); /*FIXME do proper error handling*/
2401 for (i = 0; i < gklass->method.count; ++i) {
2402 if (gklass->methods [i] == method) {
2403 if (klass->methods) {
2404 return klass->methods [i];
2407 MonoMethod *result = mono_class_inflate_generic_method_full_checked (gklass->methods [i], klass, mono_class_get_context (klass), &error);
2408 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2418 * mono_class_get_vtable_entry:
2420 * Returns klass->vtable [offset], computing it if neccesary. Returns NULL on failure.
2421 * LOCKING: Acquires the loader lock.
2424 mono_class_get_vtable_entry (MonoClass *klass, int offset)
2428 if (klass->rank == 1) {
2430 * szarrays do not overwrite any methods of Array, so we can avoid
2431 * initializing their vtables in some cases.
2433 mono_class_setup_vtable (klass->parent);
2434 if (offset < klass->parent->vtable_size)
2435 return klass->parent->vtable [offset];
2438 if (klass->generic_class) {
2440 MonoClass *gklass = klass->generic_class->container_class;
2441 mono_class_setup_vtable (gklass);
2442 m = gklass->vtable [offset];
2444 m = mono_class_inflate_generic_method_full_checked (m, klass, mono_class_get_context (klass), &error);
2445 g_assert (mono_error_ok (&error)); /* FIXME don't swallow this error */
2447 mono_class_setup_vtable (klass);
2448 if (klass->exception_type)
2450 m = klass->vtable [offset];
2457 * mono_class_get_vtable_size:
2459 * Return the vtable size for KLASS.
2462 mono_class_get_vtable_size (MonoClass *klass)
2464 mono_class_setup_vtable (klass);
2466 return klass->vtable_size;
2470 * mono_class_setup_properties:
2472 * Initialize klass->ext.property and klass->ext.properties.
2474 * This method can fail the class.
2477 mono_class_setup_properties (MonoClass *klass)
2479 guint startm, endm, i, j;
2480 guint32 cols [MONO_PROPERTY_SIZE];
2481 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2482 MonoProperty *properties;
2486 if (klass->ext && klass->ext->properties)
2489 if (klass->generic_class) {
2490 MonoClass *gklass = klass->generic_class->container_class;
2492 mono_class_init (gklass);
2493 mono_class_setup_properties (gklass);
2494 if (gklass->exception_type) {
2495 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2499 properties = mono_class_new0 (klass, MonoProperty, gklass->ext->property.count + 1);
2501 for (i = 0; i < gklass->ext->property.count; i++) {
2503 MonoProperty *prop = &properties [i];
2505 *prop = gklass->ext->properties [i];
2508 prop->get = mono_class_inflate_generic_method_full_checked (
2509 prop->get, klass, mono_class_get_context (klass), &error);
2511 prop->set = mono_class_inflate_generic_method_full_checked (
2512 prop->set, klass, mono_class_get_context (klass), &error);
2514 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2515 prop->parent = klass;
2518 first = gklass->ext->property.first;
2519 count = gklass->ext->property.count;
2521 first = mono_metadata_properties_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2522 count = last - first;
2525 mono_class_setup_methods (klass);
2526 if (klass->exception_type)
2530 properties = (MonoProperty *)mono_class_alloc0 (klass, sizeof (MonoProperty) * count);
2531 for (i = first; i < last; ++i) {
2532 mono_metadata_decode_table_row (klass->image, MONO_TABLE_PROPERTY, i, cols, MONO_PROPERTY_SIZE);
2533 properties [i - first].parent = klass;
2534 properties [i - first].attrs = cols [MONO_PROPERTY_FLAGS];
2535 properties [i - first].name = mono_metadata_string_heap (klass->image, cols [MONO_PROPERTY_NAME]);
2537 startm = mono_metadata_methods_from_property (klass->image, i, &endm);
2538 for (j = startm; j < endm; ++j) {
2541 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2543 if (klass->image->uncompressed_metadata) {
2545 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2546 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2547 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2549 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2552 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2553 case METHOD_SEMANTIC_SETTER:
2554 properties [i - first].set = method;
2556 case METHOD_SEMANTIC_GETTER:
2557 properties [i - first].get = method;
2566 mono_class_alloc_ext (klass);
2568 mono_image_lock (klass->image);
2570 if (klass->ext->properties) {
2571 /* We leak 'properties' which was allocated from the image mempool */
2572 mono_image_unlock (klass->image);
2576 klass->ext->property.first = first;
2577 klass->ext->property.count = count;
2579 /* Flush any pending writes as we do double checked locking on klass->ext->properties */
2580 mono_memory_barrier ();
2582 /* Leave this assignment as the last op in the function */
2583 klass->ext->properties = properties;
2585 mono_image_unlock (klass->image);
2589 inflate_method_listz (MonoMethod **methods, MonoClass *klass, MonoGenericContext *context)
2591 MonoMethod **om, **retval;
2594 for (om = methods, count = 0; *om; ++om, ++count)
2597 retval = g_new0 (MonoMethod*, count + 1);
2599 for (om = methods, count = 0; *om; ++om, ++count) {
2601 retval [count] = mono_class_inflate_generic_method_full_checked (*om, klass, context, &error);
2602 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2608 /*This method can fail the class.*/
2610 mono_class_setup_events (MonoClass *klass)
2613 guint startm, endm, i, j;
2614 guint32 cols [MONO_EVENT_SIZE];
2615 MonoTableInfo *msemt = &klass->image->tables [MONO_TABLE_METHODSEMANTICS];
2619 if (klass->ext && klass->ext->events)
2622 if (klass->generic_class) {
2623 MonoClass *gklass = klass->generic_class->container_class;
2624 MonoGenericContext *context = NULL;
2626 mono_class_setup_events (gklass);
2627 if (gklass->exception_type) {
2628 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2632 first = gklass->ext->event.first;
2633 count = gklass->ext->event.count;
2635 events = mono_class_new0 (klass, MonoEvent, count);
2638 context = mono_class_get_context (klass);
2640 for (i = 0; i < count; i++) {
2642 MonoEvent *event = &events [i];
2643 MonoEvent *gevent = &gklass->ext->events [i];
2645 mono_error_init (&error); //since we do conditional calls, we must ensure the default value is ok
2647 event->parent = klass;
2648 event->name = gevent->name;
2649 event->add = gevent->add ? mono_class_inflate_generic_method_full_checked (gevent->add, klass, context, &error) : NULL;
2650 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2651 event->remove = gevent->remove ? mono_class_inflate_generic_method_full_checked (gevent->remove, klass, context, &error) : NULL;
2652 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2653 event->raise = gevent->raise ? mono_class_inflate_generic_method_full_checked (gevent->raise, klass, context, &error) : NULL;
2654 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
2656 #ifndef MONO_SMALL_CONFIG
2657 event->other = gevent->other ? inflate_method_listz (gevent->other, klass, context) : NULL;
2659 event->attrs = gevent->attrs;
2662 first = mono_metadata_events_from_typedef (klass->image, mono_metadata_token_index (klass->type_token) - 1, &last);
2663 count = last - first;
2666 mono_class_setup_methods (klass);
2667 if (klass->exception_type) {
2668 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Generic type definition failed to load"));
2673 events = (MonoEvent *)mono_class_alloc0 (klass, sizeof (MonoEvent) * count);
2674 for (i = first; i < last; ++i) {
2675 MonoEvent *event = &events [i - first];
2677 mono_metadata_decode_table_row (klass->image, MONO_TABLE_EVENT, i, cols, MONO_EVENT_SIZE);
2678 event->parent = klass;
2679 event->attrs = cols [MONO_EVENT_FLAGS];
2680 event->name = mono_metadata_string_heap (klass->image, cols [MONO_EVENT_NAME]);
2682 startm = mono_metadata_methods_from_event (klass->image, i, &endm);
2683 for (j = startm; j < endm; ++j) {
2686 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
2688 if (klass->image->uncompressed_metadata) {
2690 /* It seems like the MONO_METHOD_SEMA_METHOD column needs no remapping */
2691 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | cols [MONO_METHOD_SEMA_METHOD], klass, NULL, &error);
2692 mono_error_cleanup (&error); /* FIXME don't swallow this error */
2694 method = klass->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - klass->method.first];
2697 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
2698 case METHOD_SEMANTIC_ADD_ON:
2699 event->add = method;
2701 case METHOD_SEMANTIC_REMOVE_ON:
2702 event->remove = method;
2704 case METHOD_SEMANTIC_FIRE:
2705 event->raise = method;
2707 case METHOD_SEMANTIC_OTHER: {
2708 #ifndef MONO_SMALL_CONFIG
2711 if (event->other == NULL) {
2712 event->other = g_new0 (MonoMethod*, 2);
2714 while (event->other [n])
2716 event->other = (MonoMethod **)g_realloc (event->other, (n + 2) * sizeof (MonoMethod*));
2718 event->other [n] = method;
2719 /* NULL terminated */
2720 event->other [n + 1] = NULL;
2731 mono_class_alloc_ext (klass);
2733 mono_image_lock (klass->image);
2735 if (klass->ext->events) {
2736 mono_image_unlock (klass->image);
2740 klass->ext->event.first = first;
2741 klass->ext->event.count = count;
2743 /* Flush any pending writes as we do double checked locking on klass->ext.events */
2744 mono_memory_barrier ();
2746 /* Leave this assignment as the last op in the function */
2747 klass->ext->events = events;
2749 mono_image_unlock (klass->image);
2753 * Global pool of interface IDs, represented as a bitset.
2754 * LOCKING: Protected by the classes lock.
2756 static MonoBitSet *global_interface_bitset = NULL;
2759 * mono_unload_interface_ids:
2760 * @bitset: bit set of interface IDs
2762 * When an image is unloaded, the interface IDs associated with
2763 * the image are put back in the global pool of IDs so the numbers
2767 mono_unload_interface_ids (MonoBitSet *bitset)
2770 mono_bitset_sub (global_interface_bitset, bitset);
2775 mono_unload_interface_id (MonoClass *klass)
2777 if (global_interface_bitset && klass->interface_id) {
2779 mono_bitset_clear (global_interface_bitset, klass->interface_id);
2785 * mono_get_unique_iid:
2788 * Assign a unique integer ID to the interface represented by @class.
2789 * The ID will positive and as small as possible.
2790 * LOCKING: Acquires the classes lock.
2791 * Returns: The new ID.
2794 mono_get_unique_iid (MonoClass *klass)
2798 g_assert (MONO_CLASS_IS_INTERFACE (klass));
2802 if (!global_interface_bitset) {
2803 global_interface_bitset = mono_bitset_new (128, 0);
2806 iid = mono_bitset_find_first_unset (global_interface_bitset, -1);
2808 int old_size = mono_bitset_size (global_interface_bitset);
2809 MonoBitSet *new_set = mono_bitset_clone (global_interface_bitset, old_size * 2);
2810 mono_bitset_free (global_interface_bitset);
2811 global_interface_bitset = new_set;
2814 mono_bitset_set (global_interface_bitset, iid);
2815 /* set the bit also in the per-image set */
2816 if (!klass->generic_class) {
2817 if (klass->image->interface_bitset) {
2818 if (iid >= mono_bitset_size (klass->image->interface_bitset)) {
2819 MonoBitSet *new_set = mono_bitset_clone (klass->image->interface_bitset, iid + 1);
2820 mono_bitset_free (klass->image->interface_bitset);
2821 klass->image->interface_bitset = new_set;
2824 klass->image->interface_bitset = mono_bitset_new (iid + 1, 0);
2826 mono_bitset_set (klass->image->interface_bitset, iid);
2831 #ifndef MONO_SMALL_CONFIG
2832 if (mono_print_vtable) {
2834 char *type_name = mono_type_full_name (&klass->byval_arg);
2835 if (klass->generic_class && !klass->generic_class->context.class_inst->is_open) {
2836 generic_id = klass->generic_class->context.class_inst->id;
2837 g_assert (generic_id != 0);
2841 printf ("Interface: assigned id %d to %s|%s|%d\n", iid, klass->image->name, type_name, generic_id);
2846 g_assert (iid <= 65535);
2851 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res, MonoError *error)
2856 mono_class_setup_interfaces (klass, error);
2857 return_if_nok (error);
2859 for (i = 0; i < klass->interface_count; i++) {
2860 ic = klass->interfaces [i];
2863 *res = g_ptr_array_new ();
2864 g_ptr_array_add (*res, ic);
2865 mono_class_init (ic);
2866 if (ic->exception_type) {
2867 mono_error_set_type_load_class (error, ic, "Error Loading class");
2871 collect_implemented_interfaces_aux (ic, res, error);
2872 return_if_nok (error);
2877 mono_class_get_implemented_interfaces (MonoClass *klass, MonoError *error)
2879 GPtrArray *res = NULL;
2881 collect_implemented_interfaces_aux (klass, &res, error);
2882 if (!mono_error_ok (error)) {
2884 g_ptr_array_free (res, TRUE);
2891 compare_interface_ids (const void *p_key, const void *p_element) {
2892 const MonoClass *key = (const MonoClass *)p_key;
2893 const MonoClass *element = *(const MonoClass **)p_element;
2895 return (key->interface_id - element->interface_id);
2898 /*FIXME verify all callers if they should switch to mono_class_interface_offset_with_variance*/
2900 mono_class_interface_offset (MonoClass *klass, MonoClass *itf) {
2901 MonoClass **result = (MonoClass **)mono_binary_search (
2903 klass->interfaces_packed,
2904 klass->interface_offsets_count,
2905 sizeof (MonoClass *),
2906 compare_interface_ids);
2908 return klass->interface_offsets_packed [result - (klass->interfaces_packed)];
2915 * mono_class_interface_offset_with_variance:
2917 * Return the interface offset of @itf in @klass. Sets @non_exact_match to TRUE if the match required variance check
2918 * If @itf is an interface with generic variant arguments, try to find the compatible one.
2920 * Note that this function is responsible for resolving ambiguities. Right now we use whatever ordering interfaces_packed gives us.
2922 * FIXME figure out MS disambiguation rules and fix this function.
2925 mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gboolean *non_exact_match) {
2926 int i = mono_class_interface_offset (klass, itf);
2927 *non_exact_match = FALSE;
2931 if (!mono_class_has_variant_generic_params (itf))
2934 for (i = 0; i < klass->interface_offsets_count; i++) {
2935 if (mono_class_is_variant_compatible (itf, klass->interfaces_packed [i], FALSE)) {
2936 *non_exact_match = TRUE;
2937 return klass->interface_offsets_packed [i];
2945 print_implemented_interfaces (MonoClass *klass) {
2948 GPtrArray *ifaces = NULL;
2950 int ancestor_level = 0;
2952 name = mono_type_get_full_name (klass);
2953 printf ("Packed interface table for class %s has size %d\n", name, klass->interface_offsets_count);
2956 for (i = 0; i < klass->interface_offsets_count; i++)
2957 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2958 klass->interfaces_packed [i]->interface_id,
2959 klass->interface_offsets_packed [i],
2960 klass->interfaces_packed [i]->method.count,
2961 klass->interfaces_packed [i]->name_space,
2962 klass->interfaces_packed [i]->name );
2963 printf ("Interface flags: ");
2964 for (i = 0; i <= klass->max_interface_id; i++)
2965 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
2966 printf ("(%d,T)", i);
2968 printf ("(%d,F)", i);
2970 printf ("Dump interface flags:");
2971 #ifdef COMPRESSED_INTERFACE_BITMAP
2973 const uint8_t* p = klass->interface_bitmap;
2974 i = klass->max_interface_id;
2976 printf (" %d x 00 %02X", p [0], p [1]);
2982 for (i = 0; i < ((((klass->max_interface_id + 1) >> 3)) + (((klass->max_interface_id + 1) & 7)? 1 :0)); i++)
2983 printf (" %02X", klass->interface_bitmap [i]);
2986 while (klass != NULL) {
2987 printf ("[LEVEL %d] Implemented interfaces by class %s:\n", ancestor_level, klass->name);
2988 ifaces = mono_class_get_implemented_interfaces (klass, &error);
2989 if (!mono_error_ok (&error)) {
2990 printf (" Type failed due to %s\n", mono_error_get_message (&error));
2991 mono_error_cleanup (&error);
2992 } else if (ifaces) {
2993 for (i = 0; i < ifaces->len; i++) {
2994 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
2995 printf (" [UIID %d] interface %s\n", ic->interface_id, ic->name);
2996 printf (" [%03d][UUID %03d][SLOT %03d][SIZE %03d] interface %s.%s\n", i,
2998 mono_class_interface_offset (klass, ic),
3003 g_ptr_array_free (ifaces, TRUE);
3006 klass = klass->parent;
3011 inflate_class_one_arg (MonoClass *gtype, MonoClass *arg0)
3014 args [0] = &arg0->byval_arg;
3016 return mono_class_bind_generic_parameters (gtype, 1, args, FALSE);
3020 array_class_get_if_rank (MonoClass *klass, guint rank)
3022 return rank ? mono_array_class_get (klass, rank) : klass;
3026 fill_valuetype_array_derived_types (MonoClass **valuetype_types, MonoClass *eclass, int rank)
3028 valuetype_types [0] = eclass;
3029 if (eclass == mono_defaults.int16_class)
3030 valuetype_types [1] = mono_defaults.uint16_class;
3031 else if (eclass == mono_defaults.uint16_class)
3032 valuetype_types [1] = mono_defaults.int16_class;
3033 else if (eclass == mono_defaults.int32_class)
3034 valuetype_types [1] = mono_defaults.uint32_class;
3035 else if (eclass == mono_defaults.uint32_class)
3036 valuetype_types [1] = mono_defaults.int32_class;
3037 else if (eclass == mono_defaults.int64_class)
3038 valuetype_types [1] = mono_defaults.uint64_class;
3039 else if (eclass == mono_defaults.uint64_class)
3040 valuetype_types [1] = mono_defaults.int64_class;
3041 else if (eclass == mono_defaults.byte_class)
3042 valuetype_types [1] = mono_defaults.sbyte_class;
3043 else if (eclass == mono_defaults.sbyte_class)
3044 valuetype_types [1] = mono_defaults.byte_class;
3045 else if (eclass->enumtype && mono_class_enum_basetype (eclass))
3046 valuetype_types [1] = mono_class_from_mono_type (mono_class_enum_basetype (eclass));
3049 /* this won't be needed once bug #325495 is completely fixed
3050 * though we'll need something similar to know which interfaces to allow
3051 * in arrays when they'll be lazyly created
3053 * FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
3054 * MS returns diferrent types based on which instance is called. For example:
3055 * object obj = new byte[10][];
3056 * Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
3057 * Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
3060 * Fixing this should kill quite some code, save some bits and improve compatibility.
3063 get_implicit_generic_array_interfaces (MonoClass *klass, int *num, int *is_enumerator)
3065 MonoClass *eclass = klass->element_class;
3066 static MonoClass* generic_icollection_class = NULL;
3067 static MonoClass* generic_ienumerable_class = NULL;
3068 static MonoClass* generic_ienumerator_class = NULL;
3069 static MonoClass* generic_ireadonlylist_class = NULL;
3070 static MonoClass* generic_ireadonlycollection_class = NULL;
3071 MonoClass *valuetype_types[2] = { NULL, NULL };
3072 MonoClass **interfaces = NULL;
3073 int i, nifaces, interface_count, real_count, original_rank;
3075 gboolean internal_enumerator;
3076 gboolean eclass_is_valuetype;
3078 if (!mono_defaults.generic_ilist_class) {
3082 internal_enumerator = FALSE;
3083 eclass_is_valuetype = FALSE;
3084 original_rank = eclass->rank;
3085 if (klass->byval_arg.type != MONO_TYPE_SZARRAY) {
3086 if (klass->generic_class && klass->nested_in == mono_defaults.array_class && strcmp (klass->name, "InternalEnumerator`1") == 0) {
3088 * For a Enumerator<T[]> we need to get the list of interfaces for T.
3090 eclass = mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
3091 original_rank = eclass->rank;
3093 eclass = eclass->element_class;
3094 internal_enumerator = TRUE;
3095 *is_enumerator = TRUE;
3103 * with this non-lazy impl we can't implement all the interfaces so we do just the minimal stuff
3104 * for deep levels of arrays of arrays (string[][] has all the interfaces, string[][][] doesn't)
3106 all_interfaces = eclass->rank && eclass->element_class->rank? FALSE: TRUE;
3108 if (!generic_icollection_class) {
3109 generic_icollection_class = mono_class_from_name (mono_defaults.corlib,
3110 "System.Collections.Generic", "ICollection`1");
3111 generic_ienumerable_class = mono_class_from_name (mono_defaults.corlib,
3112 "System.Collections.Generic", "IEnumerable`1");
3113 generic_ienumerator_class = mono_class_from_name (mono_defaults.corlib,
3114 "System.Collections.Generic", "IEnumerator`1");
3115 generic_ireadonlylist_class = mono_class_from_name (mono_defaults.corlib,
3116 "System.Collections.Generic", "IReadOnlyList`1");
3117 generic_ireadonlycollection_class = mono_class_from_name (mono_defaults.corlib,
3118 "System.Collections.Generic", "IReadOnlyCollection`1");
3121 mono_class_init (eclass);
3124 * Arrays in 2.0 need to implement a number of generic interfaces
3125 * (IList`1, ICollection`1, IEnumerable`1 for a number of types depending
3126 * on the element class). For net 4.5, we also need to implement IReadOnlyList`1/IReadOnlyCollection`1.
3127 * We collect the types needed to build the
3128 * instantiations in interfaces at intervals of 3/5, because 3/5 are
3129 * the generic interfaces needed to implement.
3131 * On 4.5, as an optimization, we don't expand ref classes for the variant generic interfaces
3132 * (IEnumerator, IReadOnlyList and IReadOnlyColleciton). The regular dispatch code can handle those cases.
3134 if (eclass->valuetype) {
3135 nifaces = generic_ireadonlylist_class ? 5 : 3;
3136 fill_valuetype_array_derived_types (valuetype_types, eclass, original_rank);
3138 /* IList, ICollection, IEnumerable, IReadOnlyList`1 */
3139 real_count = interface_count = valuetype_types [1] ? (nifaces * 2) : nifaces;
3140 if (internal_enumerator) {
3142 if (valuetype_types [1])
3146 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3147 interfaces [0] = valuetype_types [0];
3148 if (valuetype_types [1])
3149 interfaces [nifaces] = valuetype_types [1];
3151 eclass_is_valuetype = TRUE;
3154 int idepth = eclass->idepth;
3155 if (!internal_enumerator)
3157 nifaces = generic_ireadonlylist_class ? 2 : 3;
3159 // FIXME: This doesn't seem to work/required for generic params
3160 if (!(eclass->this_arg.type == MONO_TYPE_VAR || eclass->this_arg.type == MONO_TYPE_MVAR || (image_is_dynamic (eclass->image) && !eclass->wastypebuilder)))
3161 mono_class_setup_interface_offsets (eclass);
3163 interface_count = all_interfaces? eclass->interface_offsets_count: eclass->interface_count;
3164 /* we add object for interfaces and the supertypes for the other
3165 * types. The last of the supertypes is the element class itself which we
3166 * already created the explicit interfaces for (so we include it for IEnumerator
3167 * and exclude it for arrays).
3169 if (MONO_CLASS_IS_INTERFACE (eclass))
3172 interface_count += idepth;
3173 if (eclass->rank && eclass->element_class->valuetype) {
3174 fill_valuetype_array_derived_types (valuetype_types, eclass->element_class, original_rank);
3175 if (valuetype_types [1])
3178 /* IList, ICollection, IEnumerable, IReadOnlyList */
3179 interface_count *= nifaces;
3180 real_count = interface_count;
3181 if (internal_enumerator) {
3182 real_count += (MONO_CLASS_IS_INTERFACE (eclass) ? 1 : idepth) + eclass->interface_offsets_count;
3183 if (valuetype_types [1])
3186 interfaces = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * real_count);
3187 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3188 interfaces [0] = mono_defaults.object_class;
3192 for (i = 0; i < idepth; i++) {
3193 mono_class_init (eclass->supertypes [i]);
3194 interfaces [j] = eclass->supertypes [i];
3198 if (all_interfaces) {
3199 for (i = 0; i < eclass->interface_offsets_count; i++) {
3200 interfaces [j] = eclass->interfaces_packed [i];
3204 for (i = 0; i < eclass->interface_count; i++) {
3205 interfaces [j] = eclass->interfaces [i];
3209 if (valuetype_types [1]) {
3210 interfaces [j] = array_class_get_if_rank (valuetype_types [1], original_rank);
3215 /* instantiate the generic interfaces */
3216 for (i = 0; i < interface_count; i += nifaces) {
3217 MonoClass *iface = interfaces [i];
3219 interfaces [i + 0] = inflate_class_one_arg (mono_defaults.generic_ilist_class, iface);
3220 interfaces [i + 1] = inflate_class_one_arg (generic_icollection_class, iface);
3222 if (eclass->valuetype) {
3223 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3224 if (generic_ireadonlylist_class) {
3225 interfaces [i + 3] = inflate_class_one_arg (generic_ireadonlylist_class, iface);
3226 interfaces [i + 4] = inflate_class_one_arg (generic_ireadonlycollection_class, iface);
3229 if (!generic_ireadonlylist_class)
3230 interfaces [i + 2] = inflate_class_one_arg (generic_ienumerable_class, iface);
3233 if (internal_enumerator) {
3235 /* instantiate IEnumerator<iface> */
3236 for (i = 0; i < interface_count; i++) {
3237 interfaces [i] = inflate_class_one_arg (generic_ienumerator_class, interfaces [i]);
3239 j = interface_count;
3240 if (!eclass_is_valuetype) {
3241 if (MONO_CLASS_IS_INTERFACE (eclass)) {
3242 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, mono_defaults.object_class);
3245 for (i = 0; i < eclass->idepth; i++) {
3246 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->supertypes [i]);
3250 for (i = 0; i < eclass->interface_offsets_count; i++) {
3251 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, eclass->interfaces_packed [i]);
3255 interfaces [j++] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [0], original_rank));
3257 if (valuetype_types [1])
3258 interfaces [j] = inflate_class_one_arg (generic_ienumerator_class, array_class_get_if_rank (valuetype_types [1], original_rank));
3262 char *type_name = mono_type_get_name_full (&klass->byval_arg, 0);
3263 for (i = 0; i < real_count; ++i) {
3264 char *name = mono_type_get_name_full (&interfaces [i]->byval_arg, 0);
3265 g_print ("%s implements %s\n", type_name, name);
3276 find_array_interface (MonoClass *klass, const char *name)
3279 for (i = 0; i < klass->interface_count; ++i) {
3280 if (strcmp (klass->interfaces [i]->name, name) == 0)
3287 * Return the number of virtual methods.
3288 * Even for interfaces we can't simply return the number of methods as all CLR types are allowed to have static methods.
3289 * Return -1 on failure.
3290 * FIXME It would be nice if this information could be cached somewhere.
3293 count_virtual_methods (MonoClass *klass)
3297 klass = mono_class_get_generic_type_definition (klass); /*We can find this information by looking at the GTD*/
3299 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
3300 mono_class_setup_methods (klass);
3301 if (klass->exception_type)
3304 for (i = 0; i < klass->method.count; ++i) {
3305 flags = klass->methods [i]->flags;
3306 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3310 for (i = 0; i < klass->method.count; ++i) {
3311 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
3313 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
3321 find_interface (int num_ifaces, MonoClass **interfaces_full, MonoClass *ic)
3329 m = (l + num_ifaces) / 2;
3330 if (interfaces_full [m] == ic)
3332 if (l == num_ifaces)
3334 if (!interfaces_full [m] || interfaces_full [m]->interface_id > ic->interface_id) {
3343 find_interface_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic)
3345 int i = find_interface (num_ifaces, interfaces_full, ic);
3347 return interface_offsets_full [i];
3352 set_interface_and_offset (int num_ifaces, MonoClass **interfaces_full, int *interface_offsets_full, MonoClass *ic, int offset, mono_bool force_set)
3354 int i = find_interface (num_ifaces, interfaces_full, ic);
3358 interface_offsets_full [i] = offset;
3361 for (i = 0; i < num_ifaces; ++i) {
3362 if (interfaces_full [i]) {
3364 if (interfaces_full [i]->interface_id < ic->interface_id)
3367 while (end < num_ifaces && interfaces_full [end]) end++;
3368 memmove (interfaces_full + i + 1, interfaces_full + i, sizeof (MonoClass*) * (end - i));
3369 memmove (interface_offsets_full + i + 1, interface_offsets_full + i, sizeof (int) * (end - i));
3371 interfaces_full [i] = ic;
3372 interface_offsets_full [i] = offset;
3378 #ifdef COMPRESSED_INTERFACE_BITMAP
3381 * Compressed interface bitmap design.
3383 * Interface bitmaps take a large amount of memory, because their size is
3384 * linear with the maximum interface id assigned in the process (each interface
3385 * is assigned a unique id as it is loaded). The number of interface classes
3386 * is high because of the many implicit interfaces implemented by arrays (we'll
3387 * need to lazy-load them in the future).
3388 * Most classes implement a very small number of interfaces, so the bitmap is
3389 * sparse. This bitmap needs to be checked by interface casts, so access to the
3390 * needed bit must be fast and doable with few jit instructions.
3392 * The current compression format is as follows:
3393 * *) it is a sequence of one or more two-byte elements
3394 * *) the first byte in the element is the count of empty bitmap bytes
3395 * at the current bitmap position
3396 * *) the second byte in the element is an actual bitmap byte at the current
3399 * As an example, the following compressed bitmap bytes:
3400 * 0x07 0x01 0x00 0x7
3401 * correspond to the following bitmap:
3402 * 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x01 0x07
3404 * Each two-byte element can represent up to 2048 bitmap bits, but as few as a single
3405 * bitmap byte for non-sparse sequences. In practice the interface bitmaps created
3406 * during a gmcs bootstrap are reduced to less tha 5% of the original size.
3410 * mono_compress_bitmap:
3411 * @dest: destination buffer
3412 * @bitmap: bitmap buffer
3413 * @size: size of @bitmap in bytes
3415 * This is a mono internal function.
3416 * The @bitmap data is compressed into a format that is small but
3417 * still searchable in few instructions by the JIT and runtime.
3418 * The compressed data is stored in the buffer pointed to by the
3419 * @dest array. Passing a #NULL value for @dest allows to just compute
3420 * the size of the buffer.
3421 * This compression algorithm assumes the bits set in the bitmap are
3422 * few and far between, like in interface bitmaps.
3423 * Returns: The size of the compressed bitmap in bytes.
3426 mono_compress_bitmap (uint8_t *dest, const uint8_t *bitmap, int size)
3430 const uint8_t *end = bitmap + size;
3431 while (bitmap < end) {
3432 if (*bitmap || numz == 255) {
3456 * mono_class_interface_match:
3457 * @bitmap: a compressed bitmap buffer
3458 * @id: the index to check in the bitmap
3460 * This is a mono internal function.
3461 * Checks if a bit is set in a compressed interface bitmap. @id must
3462 * be already checked for being smaller than the maximum id encoded in the
3465 * Returns: A non-zero value if bit @id is set in the bitmap @bitmap,
3469 mono_class_interface_match (const uint8_t *bitmap, int id)
3472 id -= bitmap [0] * 8;
3476 return bitmap [1] & (1 << id);
3485 * LOCKING: this is supposed to be called with the loader lock held.
3486 * Return -1 on failure and set exception_type
3489 setup_interface_offsets (MonoClass *klass, int cur_slot, gboolean overwrite)
3493 int i, j, max_iid, num_ifaces;
3494 MonoClass **interfaces_full = NULL;
3495 int *interface_offsets_full = NULL;
3497 GPtrArray **ifaces_array = NULL;
3498 int interface_offsets_count;
3499 MonoClass **array_interfaces = NULL;
3500 int num_array_interfaces;
3501 int is_enumerator = FALSE;
3503 mono_class_setup_supertypes (klass);
3505 * get the implicit generic interfaces for either the arrays or for System.Array/InternalEnumerator<T>
3506 * implicit interfaces have the property that they are assigned the same slot in the
3507 * vtables for compatible interfaces
3509 array_interfaces = get_implicit_generic_array_interfaces (klass, &num_array_interfaces, &is_enumerator);
3511 /* compute maximum number of slots and maximum interface id */
3513 num_ifaces = num_array_interfaces; /* this can include duplicated ones */
3514 ifaces_array = g_new0 (GPtrArray *, klass->idepth);
3515 for (j = 0; j < klass->idepth; j++) {
3516 k = klass->supertypes [j];
3517 num_ifaces += k->interface_count;
3518 for (i = 0; i < k->interface_count; i++) {
3519 ic = k->interfaces [i];
3522 mono_class_init (ic);
3524 if (max_iid < ic->interface_id)
3525 max_iid = ic->interface_id;
3527 ifaces = mono_class_get_implemented_interfaces (k, &error);
3528 if (!mono_error_ok (&error)) {
3529 char *name = mono_type_get_full_name (k);
3530 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error getting the interfaces of %s due to %s", name, mono_error_get_message (&error)));
3532 mono_error_cleanup (&error);
3537 num_ifaces += ifaces->len;
3538 for (i = 0; i < ifaces->len; ++i) {
3539 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3540 if (max_iid < ic->interface_id)
3541 max_iid = ic->interface_id;
3543 ifaces_array [j] = ifaces;
3547 for (i = 0; i < num_array_interfaces; ++i) {
3548 ic = array_interfaces [i];
3549 mono_class_init (ic);
3550 if (max_iid < ic->interface_id)
3551 max_iid = ic->interface_id;
3554 if (MONO_CLASS_IS_INTERFACE (klass)) {
3556 if (max_iid < klass->interface_id)
3557 max_iid = klass->interface_id;
3559 klass->max_interface_id = max_iid;
3560 /* compute vtable offset for interfaces */
3561 interfaces_full = (MonoClass **)g_malloc0 (sizeof (MonoClass*) * num_ifaces);
3562 interface_offsets_full = (int *)g_malloc (sizeof (int) * num_ifaces);
3564 for (i = 0; i < num_ifaces; i++) {
3565 interface_offsets_full [i] = -1;
3568 /* skip the current class */
3569 for (j = 0; j < klass->idepth - 1; j++) {
3570 k = klass->supertypes [j];
3571 ifaces = ifaces_array [j];
3574 for (i = 0; i < ifaces->len; ++i) {
3576 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3578 /*Force the sharing of interface offsets between parent and subtypes.*/
3579 io = mono_class_interface_offset (k, ic);
3581 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, io, TRUE);
3586 g_assert (klass == klass->supertypes [klass->idepth - 1]);
3587 ifaces = ifaces_array [klass->idepth - 1];
3589 for (i = 0; i < ifaces->len; ++i) {
3591 ic = (MonoClass *)g_ptr_array_index (ifaces, i);
3592 if (set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, cur_slot, FALSE))
3594 count = count_virtual_methods (ic);
3596 char *name = mono_type_get_full_name (ic);
3597 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Error calculating interface offset of %s", name));
3606 if (MONO_CLASS_IS_INTERFACE (klass))
3607 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, klass, cur_slot, TRUE);
3609 if (num_array_interfaces) {
3610 if (is_enumerator) {
3611 int ienumerator_idx = find_array_interface (klass, "IEnumerator`1");
3612 int ienumerator_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ienumerator_idx]);
3613 g_assert (ienumerator_offset >= 0);
3614 for (i = 0; i < num_array_interfaces; ++i) {
3615 ic = array_interfaces [i];
3616 if (strcmp (ic->name, "IEnumerator`1") == 0)
3617 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, ienumerator_offset, TRUE);
3619 g_assert_not_reached ();
3620 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, interface_offsets_full [ic->interface_id], klass->interfaces [0]->name);*/
3623 int ilist_offset, icollection_offset, ienumerable_offset, ireadonlylist_offset, ireadonlycollection_offset;
3624 int ilist_iface_idx = find_array_interface (klass, "IList`1");
3625 MonoClass* ilist_class = klass->interfaces [ilist_iface_idx];
3626 int ireadonlylist_iface_idx = find_array_interface (klass, "IReadOnlyList`1");
3627 MonoClass* ireadonlylist_class = ireadonlylist_iface_idx != -1 ? klass->interfaces [ireadonlylist_iface_idx] : NULL;
3628 int icollection_iface_idx = find_array_interface (ilist_class, "ICollection`1");
3629 int ienumerable_iface_idx = find_array_interface (ilist_class, "IEnumerable`1");
3630 int ireadonlycollection_iface_idx = ireadonlylist_iface_idx != -1 ? find_array_interface (ireadonlylist_class, "IReadOnlyCollection`1") : -1;
3631 ilist_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ilist_iface_idx]);
3632 icollection_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [icollection_iface_idx]);
3633 ienumerable_offset = find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ilist_class->interfaces [ienumerable_iface_idx]);
3634 ireadonlylist_offset = ireadonlylist_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, klass->interfaces [ireadonlylist_iface_idx]) : -1;
3635 ireadonlycollection_offset = ireadonlycollection_iface_idx != -1 ? find_interface_offset (num_ifaces, interfaces_full, interface_offsets_full, ireadonlylist_class->interfaces [ireadonlycollection_iface_idx]) : -1;
3636 g_assert (ilist_offset >= 0 && icollection_offset >= 0 && ienumerable_offset >= 0);
3637 for (i = 0; i < num_array_interfaces; ++i) {
3639 ic = array_interfaces [i];
3640 if (ic->generic_class->container_class == mono_defaults.generic_ilist_class)
3641 offset = ilist_offset;
3642 else if (strcmp (ic->name, "ICollection`1") == 0)
3643 offset = icollection_offset;
3644 else if (strcmp (ic->name, "IEnumerable`1") == 0)
3645 offset = ienumerable_offset;
3646 else if (strcmp (ic->name, "IReadOnlyList`1") == 0)
3647 offset = ireadonlylist_offset;
3648 else if (strcmp (ic->name, "IReadOnlyCollection`1") == 0)
3649 offset = ireadonlycollection_offset;
3651 g_assert_not_reached ();
3652 set_interface_and_offset (num_ifaces, interfaces_full, interface_offsets_full, ic, offset, TRUE);
3653 /*g_print ("type %s has %s offset at %d (%s)\n", klass->name, ic->name, offset, klass->interfaces [0]->name);*/
3658 for (interface_offsets_count = 0, i = 0; i < num_ifaces; i++) {
3659 if (interface_offsets_full [i] != -1) {
3660 interface_offsets_count ++;
3665 * We might get called multiple times:
3666 * - mono_class_init ()
3667 * - mono_class_setup_vtable ().
3668 * - mono_class_setup_interface_offsets ().
3669 * mono_class_setup_interface_offsets () passes 0 as CUR_SLOT, so the computed interface offsets will be invalid. This
3670 * means we have to overwrite those when called from other places (#4440).
3672 if (klass->interfaces_packed) {
3674 g_assert (klass->interface_offsets_count == interface_offsets_count);
3678 klass->interface_offsets_count = interface_offsets_count;
3679 klass->interfaces_packed = (MonoClass **)mono_class_alloc (klass, sizeof (MonoClass*) * interface_offsets_count);
3680 klass->interface_offsets_packed = (guint16 *)mono_class_alloc (klass, sizeof (guint16) * interface_offsets_count);
3681 bsize = (sizeof (guint8) * ((max_iid + 1) >> 3)) + (((max_iid + 1) & 7)? 1 :0);
3682 #ifdef COMPRESSED_INTERFACE_BITMAP
3683 bitmap = g_malloc0 (bsize);
3685 bitmap = (uint8_t *)mono_class_alloc0 (klass, bsize);
3687 for (i = 0; i < interface_offsets_count; i++) {
3688 int id = interfaces_full [i]->interface_id;
3689 bitmap [id >> 3] |= (1 << (id & 7));
3690 klass->interfaces_packed [i] = interfaces_full [i];
3691 klass->interface_offsets_packed [i] = interface_offsets_full [i];
3692 /*if (num_array_interfaces)
3693 g_print ("type %s has %s offset at %d\n", mono_type_get_name_full (&klass->byval_arg, 0), mono_type_get_name_full (&interfaces_full [i]->byval_arg, 0), interface_offsets_full [i]);*/
3695 #ifdef COMPRESSED_INTERFACE_BITMAP
3696 i = mono_compress_bitmap (NULL, bitmap, bsize);
3697 klass->interface_bitmap = mono_class_alloc0 (klass, i);
3698 mono_compress_bitmap (klass->interface_bitmap, bitmap, bsize);
3701 klass->interface_bitmap = bitmap;
3706 g_free (interfaces_full);
3707 g_free (interface_offsets_full);
3708 g_free (array_interfaces);
3709 for (i = 0; i < klass->idepth; i++) {
3710 ifaces = ifaces_array [i];
3712 g_ptr_array_free (ifaces, TRUE);
3714 g_free (ifaces_array);
3716 //printf ("JUST DONE: ");
3717 //print_implemented_interfaces (klass);
3723 * Setup interface offsets for interfaces.
3725 * - klass->max_interface_id
3726 * - klass->interface_offsets_count
3727 * - klass->interfaces_packed
3728 * - klass->interface_offsets_packed
3729 * - klass->interface_bitmap
3731 * This function can fail @class.
3734 mono_class_setup_interface_offsets (MonoClass *klass)
3736 mono_loader_lock ();
3738 setup_interface_offsets (klass, 0, FALSE);
3740 mono_loader_unlock ();
3743 /*Checks if @klass has @parent as one of it's parents type gtd
3747 * Bar<T> : Foo<Bar<Bar<T>>>
3751 mono_class_has_gtd_parent (MonoClass *klass, MonoClass *parent)
3753 klass = mono_class_get_generic_type_definition (klass);
3754 parent = mono_class_get_generic_type_definition (parent);
3755 mono_class_setup_supertypes (klass);
3756 mono_class_setup_supertypes (parent);
3758 return klass->idepth >= parent->idepth &&
3759 mono_class_get_generic_type_definition (klass->supertypes [parent->idepth - 1]) == parent;
3763 mono_class_check_vtable_constraints (MonoClass *klass, GList *in_setup)
3765 MonoGenericInst *ginst;
3767 if (!klass->generic_class) {
3768 mono_class_setup_vtable_full (klass, in_setup);
3769 return klass->exception_type == 0;
3772 mono_class_setup_vtable_full (mono_class_get_generic_type_definition (klass), in_setup);
3773 if (klass->generic_class->container_class->exception_type) {
3774 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to load generic definition vtable"));
3778 ginst = klass->generic_class->context.class_inst;
3779 for (i = 0; i < ginst->type_argc; ++i) {
3781 if (ginst->type_argv [i]->type != MONO_TYPE_GENERICINST)
3783 arg = mono_class_from_mono_type (ginst->type_argv [i]);
3784 /*Those 2 will be checked by mono_class_setup_vtable itself*/
3785 if (mono_class_has_gtd_parent (klass, arg) || mono_class_has_gtd_parent (arg, klass))
3787 if (!mono_class_check_vtable_constraints (arg, in_setup)) {
3788 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Failed to load generic parameter %d", i));
3796 * mono_class_setup_vtable:
3798 * Creates the generic vtable of CLASS.
3799 * Initializes the following fields in MonoClass:
3802 * Plus all the fields initialized by setup_interface_offsets ().
3803 * If there is an error during vtable construction, klass->exception_type is set.
3805 * LOCKING: Acquires the loader lock.
3808 mono_class_setup_vtable (MonoClass *klass)
3810 mono_class_setup_vtable_full (klass, NULL);
3814 mono_class_setup_vtable_full (MonoClass *klass, GList *in_setup)
3816 MonoMethod **overrides;
3817 MonoGenericContext *context;
3825 if (MONO_CLASS_IS_INTERFACE (klass)) {
3826 /* This sets method->slot for all methods if this is an interface */
3827 mono_class_setup_methods (klass);
3831 if (klass->exception_type)
3834 if (g_list_find (in_setup, klass))
3837 mono_loader_lock ();
3839 if (klass->vtable) {
3840 mono_loader_unlock ();
3844 mono_stats.generic_vtable_count ++;
3845 in_setup = g_list_prepend (in_setup, klass);
3847 if (klass->generic_class) {
3848 if (!mono_class_check_vtable_constraints (klass, in_setup)) {
3849 mono_loader_unlock ();
3850 g_list_remove (in_setup, klass);
3854 context = mono_class_get_context (klass);
3855 type_token = klass->generic_class->container_class->type_token;
3857 context = (MonoGenericContext *) klass->generic_container;
3858 type_token = klass->type_token;
3861 if (image_is_dynamic (klass->image)) {
3862 /* Generic instances can have zero method overrides without causing any harm.
3863 * This is true since we don't do layout all over again for them, we simply inflate
3864 * the layout of the parent.
3866 mono_reflection_get_dynamic_overrides (klass, &overrides, &onum);
3868 /* The following call fails if there are missing methods in the type */
3869 /* FIXME it's probably a good idea to avoid this for generic instances. */
3870 ok = mono_class_get_overrides_full (klass->image, type_token, &overrides, &onum, context);
3874 mono_class_setup_vtable_general (klass, overrides, onum, in_setup);
3876 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not load list of method overrides"));
3880 mono_loader_unlock ();
3881 g_list_remove (in_setup, klass);
3886 #define DEBUG_INTERFACE_VTABLE_CODE 0
3887 #define TRACE_INTERFACE_VTABLE_CODE 0
3888 #define VERIFY_INTERFACE_VTABLE_CODE 0
3889 #define VTABLE_SELECTOR (1)
3891 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3892 #define DEBUG_INTERFACE_VTABLE(stmt) do {\
3893 if (!(VTABLE_SELECTOR)) break; \
3897 #define DEBUG_INTERFACE_VTABLE(stmt)
3900 #if TRACE_INTERFACE_VTABLE_CODE
3901 #define TRACE_INTERFACE_VTABLE(stmt) do {\
3902 if (!(VTABLE_SELECTOR)) break; \
3906 #define TRACE_INTERFACE_VTABLE(stmt)
3909 #if VERIFY_INTERFACE_VTABLE_CODE
3910 #define VERIFY_INTERFACE_VTABLE(stmt) do {\
3911 if (!(VTABLE_SELECTOR)) break; \
3915 #define VERIFY_INTERFACE_VTABLE(stmt)
3919 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
3921 mono_signature_get_full_desc (MonoMethodSignature *sig, gboolean include_namespace)
3925 GString *res = g_string_new ("");
3927 g_string_append_c (res, '(');
3928 for (i = 0; i < sig->param_count; ++i) {
3930 g_string_append_c (res, ',');
3931 mono_type_get_desc (res, sig->params [i], include_namespace);
3933 g_string_append (res, ")=>");
3934 if (sig->ret != NULL) {
3935 mono_type_get_desc (res, sig->ret, include_namespace);
3937 g_string_append (res, "NULL");
3940 g_string_free (res, FALSE);
3944 print_method_signatures (MonoMethod *im, MonoMethod *cm) {
3945 char *im_sig = mono_signature_get_full_desc (mono_method_signature (im), TRUE);
3946 char *cm_sig = mono_signature_get_full_desc (mono_method_signature (cm), TRUE);
3947 printf ("(IM \"%s\", CM \"%s\")", im_sig, cm_sig);
3955 is_wcf_hack_disabled (void)
3957 static gboolean disabled;
3958 static gboolean inited = FALSE;
3960 disabled = g_getenv ("MONO_DISABLE_WCF_HACK") != NULL;
3967 check_interface_method_override (MonoClass *klass, MonoMethod *im, MonoMethod *cm, gboolean require_newslot, gboolean interface_is_explicitly_implemented_by_class, gboolean slot_is_empty)
3969 MonoMethodSignature *cmsig, *imsig;
3970 if (strcmp (im->name, cm->name) == 0) {
3971 if (! (cm->flags & METHOD_ATTRIBUTE_PUBLIC)) {
3972 TRACE_INTERFACE_VTABLE (printf ("[PUBLIC CHECK FAILED]"));
3975 if (! slot_is_empty) {
3976 if (require_newslot) {
3977 if (! interface_is_explicitly_implemented_by_class) {
3978 TRACE_INTERFACE_VTABLE (printf ("[NOT EXPLICIT IMPLEMENTATION IN FULL SLOT REFUSED]"));
3981 if (! (cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
3982 TRACE_INTERFACE_VTABLE (printf ("[NEWSLOT CHECK FAILED]"));
3986 TRACE_INTERFACE_VTABLE (printf ("[FULL SLOT REFUSED]"));
3989 cmsig = mono_method_signature (cm);
3990 imsig = mono_method_signature (im);
3991 if (!cmsig || !imsig) {
3992 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
3996 if (! mono_metadata_signature_equal (cmsig, imsig)) {
3997 TRACE_INTERFACE_VTABLE (printf ("[SIGNATURE CHECK FAILED "));
3998 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
3999 TRACE_INTERFACE_VTABLE (printf ("]"));
4002 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS]"));
4003 if (mono_security_core_clr_enabled ())
4004 mono_security_core_clr_check_override (klass, cm, im);
4006 TRACE_INTERFACE_VTABLE (printf ("[NAME CHECK OK]"));
4007 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4008 char *body_name = mono_method_full_name (cm, TRUE);
4009 char *decl_name = mono_method_full_name (im, TRUE);
4010 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4018 MonoClass *ic = im->klass;
4019 const char *ic_name_space = ic->name_space;
4020 const char *ic_name = ic->name;
4023 if (! require_newslot) {
4024 TRACE_INTERFACE_VTABLE (printf ("[INJECTED METHOD REFUSED]"));
4027 if (cm->klass->rank == 0) {
4028 TRACE_INTERFACE_VTABLE (printf ("[RANK CHECK FAILED]"));
4031 cmsig = mono_method_signature (cm);
4032 imsig = mono_method_signature (im);
4033 if (!cmsig || !imsig) {
4034 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not resolve the signature of a virtual method"));
4038 if (! mono_metadata_signature_equal (cmsig, imsig)) {
4039 TRACE_INTERFACE_VTABLE (printf ("[(INJECTED) SIGNATURE CHECK FAILED "));
4040 TRACE_INTERFACE_VTABLE (print_method_signatures (im, cm));
4041 TRACE_INTERFACE_VTABLE (printf ("]"));
4044 if (mono_class_get_image (ic) != mono_defaults.corlib) {
4045 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE CORLIB CHECK FAILED]"));
4048 if ((ic_name_space == NULL) || (strcmp (ic_name_space, "System.Collections.Generic") != 0)) {
4049 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAMESPACE CHECK FAILED]"));
4052 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))) {
4053 TRACE_INTERFACE_VTABLE (printf ("[INTERFACE NAME CHECK FAILED]"));
4057 subname = strstr (cm->name, ic_name_space);
4058 if (subname != cm->name) {
4059 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL NAMESPACE CHECK FAILED]"));
4062 subname += strlen (ic_name_space);
4063 if (subname [0] != '.') {
4064 TRACE_INTERFACE_VTABLE (printf ("[FIRST DOT CHECK FAILED]"));
4068 if (strstr (subname, ic_name) != subname) {
4069 TRACE_INTERFACE_VTABLE (printf ("[ACTUAL CLASS NAME CHECK FAILED]"));
4072 subname += strlen (ic_name);
4073 if (subname [0] != '.') {
4074 TRACE_INTERFACE_VTABLE (printf ("[SECOND DOT CHECK FAILED]"));
4078 if (strcmp (subname, im->name) != 0) {
4079 TRACE_INTERFACE_VTABLE (printf ("[METHOD NAME CHECK FAILED]"));
4083 TRACE_INTERFACE_VTABLE (printf ("[SECURITY CHECKS (INJECTED CASE)]"));
4084 if (mono_security_core_clr_enabled ())
4085 mono_security_core_clr_check_override (klass, cm, im);
4087 TRACE_INTERFACE_VTABLE (printf ("[INJECTED INTERFACE CHECK OK]"));
4088 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, im, NULL)) {
4089 char *body_name = mono_method_full_name (cm, TRUE);
4090 char *decl_name = mono_method_full_name (im, TRUE);
4091 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4101 #if (TRACE_INTERFACE_VTABLE_CODE|DEBUG_INTERFACE_VTABLE_CODE)
4103 foreach_override (gpointer key, gpointer value, gpointer user_data) {
4104 MonoMethod *method = key;
4105 MonoMethod *override = value;
4106 MonoClass *method_class = mono_method_get_class (method);
4107 MonoClass *override_class = mono_method_get_class (override);
4109 printf (" Method '%s.%s:%s' has override '%s.%s:%s'\n",
4110 mono_class_get_namespace (method_class), mono_class_get_name (method_class), mono_method_get_name (method),
4111 mono_class_get_namespace (override_class), mono_class_get_name (override_class), mono_method_get_name (override));
4114 print_overrides (GHashTable *override_map, const char *message) {
4116 printf ("Override map \"%s\" START:\n", message);
4117 g_hash_table_foreach (override_map, foreach_override, NULL);
4118 printf ("Override map \"%s\" END.\n", message);
4120 printf ("Override map \"%s\" EMPTY.\n", message);
4124 print_vtable_full (MonoClass *klass, MonoMethod** vtable, int size, int first_non_interface_slot, const char *message, gboolean print_interfaces) {
4125 char *full_name = mono_type_full_name (&klass->byval_arg);
4129 printf ("*** Vtable for class '%s' at \"%s\" (size %d)\n", full_name, message, size);
4131 if (print_interfaces) {
4132 print_implemented_interfaces (klass);
4133 printf ("* Interfaces for class '%s' done.\nStarting vtable (size %d):\n", full_name, size);
4136 if (klass->parent) {
4137 parent_size = klass->parent->vtable_size;
4141 for (i = 0; i < size; ++i) {
4142 MonoMethod *cm = vtable [i];
4143 char *cm_name = cm ? mono_method_full_name (cm, TRUE) : g_strdup ("nil");
4144 char newness = (i < parent_size) ? 'O' : ((i < first_non_interface_slot) ? 'I' : 'N');
4146 printf (" [%c][%03d][INDEX %03d] %s [%p]\n", newness, i, cm ? cm->slot : - 1, cm_name, cm);
4154 #if VERIFY_INTERFACE_VTABLE_CODE
4156 mono_method_try_get_vtable_index (MonoMethod *method)
4158 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4159 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4160 if (imethod->declaring->is_generic)
4161 return imethod->declaring->slot;
4163 return method->slot;
4167 mono_class_verify_vtable (MonoClass *klass)
4170 char *full_name = mono_type_full_name (&klass->byval_arg);
4172 printf ("*** Verifying VTable of class '%s' \n", full_name);
4176 if (!klass->methods)
4179 for (i = 0; i < klass->method.count; ++i) {
4180 MonoMethod *cm = klass->methods [i];
4183 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
4187 full_name = mono_method_full_name (cm, TRUE);
4189 slot = mono_method_try_get_vtable_index (cm);
4191 if (slot >= klass->vtable_size) {
4192 printf ("\tInvalid method %s at index %d with vtable of length %d\n", full_name, slot, klass->vtable_size);
4196 if (slot >= 0 && klass->vtable [slot] != cm && (klass->vtable [slot])) {
4197 char *other_name = klass->vtable [slot] ? mono_method_full_name (klass->vtable [slot], TRUE) : g_strdup ("[null value]");
4198 printf ("\tMethod %s has slot %d but vtable has %s on it\n", full_name, slot, other_name);
4199 g_free (other_name);
4202 printf ("\tVirtual method %s does n't have an assigned slot\n", full_name);
4209 print_unimplemented_interface_method_info (MonoClass *klass, MonoClass *ic, MonoMethod *im, int im_slot, MonoMethod **overrides, int onum) {
4211 char *method_signature;
4214 for (index = 0; index < onum; ++index) {
4215 mono_trace_warning (MONO_TRACE_TYPE, " at slot %d: %s (%d) overrides %s (%d)\n", im_slot, overrides [index*2+1]->name,
4216 overrides [index*2+1]->slot, overrides [index*2]->name, overrides [index*2]->slot);
4218 method_signature = mono_signature_get_desc (mono_method_signature (im), FALSE);
4219 type_name = mono_type_full_name (&klass->byval_arg);
4220 mono_trace_warning (MONO_TRACE_TYPE, "no implementation for interface method %s::%s(%s) in class %s\n",
4221 mono_type_get_name (&ic->byval_arg), im->name, method_signature, type_name);
4222 g_free (method_signature);
4224 mono_class_setup_methods (klass);
4225 if (klass->exception_type) {
4226 char *name = mono_type_get_full_name (klass);
4227 mono_trace_warning (MONO_TRACE_TYPE, "CLASS %s failed to resolve methods\n", name);
4231 for (index = 0; index < klass->method.count; ++index) {
4232 MonoMethod *cm = klass->methods [index];
4233 method_signature = mono_signature_get_desc (mono_method_signature (cm), TRUE);
4235 mono_trace_warning (MONO_TRACE_TYPE, "METHOD %s(%s)\n", cm->name, method_signature);
4236 g_free (method_signature);
4241 mono_method_get_method_definition (MonoMethod *method)
4243 while (method->is_inflated)
4244 method = ((MonoMethodInflated*)method)->declaring;
4249 verify_class_overrides (MonoClass *klass, MonoMethod **overrides, int onum)
4253 for (i = 0; i < onum; ++i) {
4254 MonoMethod *decl = overrides [i * 2];
4255 MonoMethod *body = overrides [i * 2 + 1];
4257 if (mono_class_get_generic_type_definition (body->klass) != mono_class_get_generic_type_definition (klass)) {
4258 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method belongs to a different class than the declared one"));
4262 if (!(body->flags & METHOD_ATTRIBUTE_VIRTUAL) || (body->flags & METHOD_ATTRIBUTE_STATIC)) {
4263 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4264 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must not be static to override a base type"));
4266 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method must be virtual to override a base type"));
4270 if (!(decl->flags & METHOD_ATTRIBUTE_VIRTUAL) || (decl->flags & METHOD_ATTRIBUTE_STATIC)) {
4271 if (body->flags & METHOD_ATTRIBUTE_STATIC)
4272 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a static method in a base type"));
4274 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Cannot override a non virtual method in a base type"));
4278 if (!mono_class_is_assignable_from_slow (decl->klass, klass)) {
4279 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Method overrides a class or interface that is not extended or implemented by this type"));
4283 body = mono_method_get_method_definition (body);
4284 decl = mono_method_get_method_definition (decl);
4286 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (body, decl, NULL)) {
4287 char *body_name = mono_method_full_name (body, TRUE);
4288 char *decl_name = mono_method_full_name (decl, TRUE);
4289 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4299 mono_class_need_stelemref_method (MonoClass *klass)
4301 return klass->rank == 1 && MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg);
4305 * LOCKING: this is supposed to be called with the loader lock held.
4308 mono_class_setup_vtable_general (MonoClass *klass, MonoMethod **overrides, int onum, GList *in_setup)
4312 MonoMethod **vtable;
4313 int i, max_vtsize = 0, max_iid, cur_slot = 0;
4314 GPtrArray *ifaces = NULL;
4315 GHashTable *override_map = NULL;
4317 #if (DEBUG_INTERFACE_VTABLE_CODE|TRACE_INTERFACE_VTABLE_CODE)
4318 int first_non_interface_slot;
4320 GSList *virt_methods = NULL, *l;
4321 int stelemref_slot = 0;
4326 if (overrides && !verify_class_overrides (klass, overrides, onum))
4329 ifaces = mono_class_get_implemented_interfaces (klass, &error);
4330 if (!mono_error_ok (&error)) {
4331 char *name = mono_type_get_full_name (klass);
4332 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not resolve %s interfaces due to %s", name, mono_error_get_message (&error)));
4334 mono_error_cleanup (&error);
4336 } else if (ifaces) {
4337 for (i = 0; i < ifaces->len; i++) {
4338 MonoClass *ic = (MonoClass *)g_ptr_array_index (ifaces, i);
4339 max_vtsize += ic->method.count;
4341 g_ptr_array_free (ifaces, TRUE);
4345 if (klass->parent) {
4346 mono_class_init (klass->parent);
4347 mono_class_setup_vtable_full (klass->parent, in_setup);
4349 if (klass->parent->exception_type) {
4350 char *name = mono_type_get_full_name (klass->parent);
4351 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Parent %s failed to load", name));
4356 max_vtsize += klass->parent->vtable_size;
4357 cur_slot = klass->parent->vtable_size;
4360 max_vtsize += klass->method.count;
4362 /*Array have a slot for stelemref*/
4363 if (mono_class_need_stelemref_method (klass)) {
4364 stelemref_slot = cur_slot;
4369 vtable = (MonoMethod **)alloca (sizeof (gpointer) * max_vtsize);
4370 memset (vtable, 0, sizeof (gpointer) * max_vtsize);
4372 /* printf ("METAINIT %s.%s\n", klass->name_space, klass->name); */
4374 cur_slot = setup_interface_offsets (klass, cur_slot, TRUE);
4375 if (cur_slot == -1) /*setup_interface_offsets fails the type.*/
4378 max_iid = klass->max_interface_id;
4379 DEBUG_INTERFACE_VTABLE (first_non_interface_slot = cur_slot);
4381 /* Optimized version for generic instances */
4382 if (klass->generic_class) {
4384 MonoClass *gklass = klass->generic_class->container_class;
4387 mono_class_setup_vtable_full (gklass, in_setup);
4388 if (gklass->exception_type != MONO_EXCEPTION_NONE) {
4389 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4393 tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * gklass->vtable_size);
4394 klass->vtable_size = gklass->vtable_size;
4395 for (i = 0; i < gklass->vtable_size; ++i)
4396 if (gklass->vtable [i]) {
4397 MonoMethod *inflated = mono_class_inflate_generic_method_full_checked (gklass->vtable [i], klass, mono_class_get_context (klass), &error);
4398 if (!mono_error_ok (&error)) {
4399 char *err_msg = g_strdup_printf ("Could not inflate method due to %s", mono_error_get_message (&error));
4400 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
4402 mono_error_cleanup (&error);
4406 tmp [i]->slot = gklass->vtable [i]->slot;
4408 mono_memory_barrier ();
4409 klass->vtable = tmp;
4411 /* Have to set method->slot for abstract virtual methods */
4412 if (klass->methods && gklass->methods) {
4413 for (i = 0; i < klass->method.count; ++i)
4414 if (klass->methods [i]->slot == -1)
4415 klass->methods [i]->slot = gklass->methods [i]->slot;
4421 if (klass->parent && klass->parent->vtable_size) {
4422 MonoClass *parent = klass->parent;
4425 memcpy (vtable, parent->vtable, sizeof (gpointer) * parent->vtable_size);
4427 // Also inherit parent interface vtables, just as a starting point.
4428 // This is needed otherwise bug-77127.exe fails when the property methods
4429 // have different names in the iterface and the class, because for child
4430 // classes the ".override" information is not used anymore.
4431 for (i = 0; i < parent->interface_offsets_count; i++) {
4432 MonoClass *parent_interface = parent->interfaces_packed [i];
4433 int interface_offset = mono_class_interface_offset (klass, parent_interface);
4434 /*FIXME this is now dead code as this condition will never hold true.
4435 Since interface offsets are inherited then the offset of an interface implemented
4436 by a parent will never be the out of it's vtable boundary.
4438 if (interface_offset >= parent->vtable_size) {
4439 int parent_interface_offset = mono_class_interface_offset (parent, parent_interface);
4442 mono_class_setup_methods (parent_interface); /*FIXME Just kill this whole chunk of dead code*/
4443 TRACE_INTERFACE_VTABLE (printf (" +++ Inheriting interface %s.%s\n", parent_interface->name_space, parent_interface->name));
4444 for (j = 0; j < parent_interface->method.count && !klass->exception_type; j++) {
4445 vtable [interface_offset + j] = parent->vtable [parent_interface_offset + j];
4446 TRACE_INTERFACE_VTABLE (printf (" --- Inheriting: [%03d][(%03d)+(%03d)] => [%03d][(%03d)+(%03d)]\n",
4447 parent_interface_offset + j, parent_interface_offset, j,
4448 interface_offset + j, interface_offset, j));
4455 /*Array have a slot for stelemref*/
4456 if (mono_class_need_stelemref_method (klass)) {
4457 MonoMethod *method = mono_marshal_get_virtual_stelemref (klass);
4459 method->slot = stelemref_slot;
4461 g_assert (method->slot == stelemref_slot);
4463 vtable [stelemref_slot] = method;
4466 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER INHERITING PARENT VTABLE", TRUE));
4467 /* override interface methods */
4468 for (i = 0; i < onum; i++) {
4469 MonoMethod *decl = overrides [i*2];
4470 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
4472 dslot = mono_method_get_vtable_slot (decl);
4474 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4478 dslot += mono_class_interface_offset (klass, decl->klass);
4479 vtable [dslot] = overrides [i*2 + 1];
4480 vtable [dslot]->slot = dslot;
4482 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4484 g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
4486 if (mono_security_core_clr_enabled ())
4487 mono_security_core_clr_check_override (klass, vtable [dslot], decl);
4490 TRACE_INTERFACE_VTABLE (print_overrides (override_map, "AFTER OVERRIDING INTERFACE METHODS"));
4491 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER OVERRIDING INTERFACE METHODS", FALSE));
4494 * Create a list of virtual methods to avoid calling
4495 * mono_class_get_virtual_methods () which is slow because of the metadata
4499 gpointer iter = NULL;
4502 virt_methods = NULL;
4503 while ((cm = mono_class_get_virtual_methods (klass, &iter))) {
4504 virt_methods = g_slist_prepend (virt_methods, cm);
4506 if (klass->exception_type)
4510 // Loop on all implemented interfaces...
4511 for (i = 0; i < klass->interface_offsets_count; i++) {
4512 MonoClass *parent = klass->parent;
4514 gboolean interface_is_explicitly_implemented_by_class;
4517 ic = klass->interfaces_packed [i];
4518 ic_offset = mono_class_interface_offset (klass, ic);
4520 mono_class_setup_methods (ic);
4521 if (ic->exception_type)
4524 // Check if this interface is explicitly implemented (instead of just inherited)
4525 if (parent != NULL) {
4526 int implemented_interfaces_index;
4527 interface_is_explicitly_implemented_by_class = FALSE;
4528 for (implemented_interfaces_index = 0; implemented_interfaces_index < klass->interface_count; implemented_interfaces_index++) {
4529 if (ic == klass->interfaces [implemented_interfaces_index]) {
4530 interface_is_explicitly_implemented_by_class = TRUE;
4535 interface_is_explicitly_implemented_by_class = TRUE;
4538 // Loop on all interface methods...
4539 for (im_index = 0; im_index < ic->method.count; im_index++) {
4540 MonoMethod *im = ic->methods [im_index];
4541 int im_slot = ic_offset + im->slot;
4542 MonoMethod *override_im = (override_map != NULL) ? (MonoMethod *)g_hash_table_lookup (override_map, im) : NULL;
4544 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4547 TRACE_INTERFACE_VTABLE (printf ("\tchecking iface method %s\n", mono_method_full_name (im,1)));
4549 // If there is an explicit implementation, just use it right away,
4550 // otherwise look for a matching method
4551 if (override_im == NULL) {
4555 // First look for a suitable method among the class methods
4556 for (l = virt_methods; l; l = l->next) {
4557 cm = (MonoMethod *)l->data;
4558 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)));
4559 if (check_interface_method_override (klass, im, cm, TRUE, interface_is_explicitly_implemented_by_class, (vtable [im_slot] == NULL))) {
4560 TRACE_INTERFACE_VTABLE (printf ("[check ok]: ASSIGNING"));
4561 vtable [im_slot] = cm;
4562 /* Why do we need this? */
4567 TRACE_INTERFACE_VTABLE (printf ("\n"));
4568 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4572 // If the slot is still empty, look in all the inherited virtual methods...
4573 if ((vtable [im_slot] == NULL) && klass->parent != NULL) {
4574 MonoClass *parent = klass->parent;
4575 // Reverse order, so that last added methods are preferred
4576 for (cm_index = parent->vtable_size - 1; cm_index >= 0; cm_index--) {
4577 MonoMethod *cm = parent->vtable [cm_index];
4579 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));
4580 if ((cm != NULL) && check_interface_method_override (klass, im, cm, FALSE, FALSE, TRUE)) {
4581 TRACE_INTERFACE_VTABLE (printf ("[everything ok]: ASSIGNING"));
4582 vtable [im_slot] = cm;
4583 /* Why do we need this? */
4589 if (klass->exception_type) /*Might be set by check_interface_method_override*/
4591 TRACE_INTERFACE_VTABLE ((cm != NULL) && printf ("\n"));
4595 g_assert (vtable [im_slot] == override_im);
4600 // If the class is not abstract, check that all its interface slots are full.
4601 // The check is done here and not directly at the end of the loop above because
4602 // it can happen (for injected generic array interfaces) that the same slot is
4603 // processed multiple times (those interfaces have overlapping slots), and it
4604 // will not always be the first pass the one that fills the slot.
4605 if (! (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4606 for (i = 0; i < klass->interface_offsets_count; i++) {
4610 ic = klass->interfaces_packed [i];
4611 ic_offset = mono_class_interface_offset (klass, ic);
4613 for (im_index = 0; im_index < ic->method.count; im_index++) {
4614 MonoMethod *im = ic->methods [im_index];
4615 int im_slot = ic_offset + im->slot;
4617 if (im->flags & METHOD_ATTRIBUTE_STATIC)
4620 TRACE_INTERFACE_VTABLE (printf (" [class is not abstract, checking slot %d for interface '%s'.'%s', method %s, slot check is %d]\n",
4621 im_slot, ic->name_space, ic->name, im->name, (vtable [im_slot] == NULL)));
4622 if (vtable [im_slot] == NULL) {
4623 print_unimplemented_interface_method_info (klass, ic, im, im_slot, overrides, onum);
4630 TRACE_INTERFACE_VTABLE (print_vtable_full (klass, vtable, cur_slot, first_non_interface_slot, "AFTER SETTING UP INTERFACE METHODS", FALSE));
4631 for (l = virt_methods; l; l = l->next) {
4632 cm = (MonoMethod *)l->data;
4634 * If the method is REUSE_SLOT, we must check in the
4635 * base class for a method to override.
4637 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
4639 for (k = klass->parent; k ; k = k->parent) {
4644 while ((m1 = mono_class_get_virtual_methods (k, &k_iter))) {
4645 MonoMethodSignature *cmsig, *m1sig;
4647 cmsig = mono_method_signature (cm);
4648 m1sig = mono_method_signature (m1);
4650 if (!cmsig || !m1sig) {
4651 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
4655 if (!strcmp(cm->name, m1->name) &&
4656 mono_metadata_signature_equal (cmsig, m1sig)) {
4658 if (mono_security_core_clr_enabled ())
4659 mono_security_core_clr_check_override (klass, cm, m1);
4661 slot = mono_method_get_vtable_slot (m1);
4665 if (is_wcf_hack_disabled () && !mono_method_can_access_method_full (cm, m1, NULL)) {
4666 char *body_name = mono_method_full_name (cm, TRUE);
4667 char *decl_name = mono_method_full_name (m1, TRUE);
4668 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Method %s overrides method '%s' which is not accessible", body_name, decl_name));
4674 g_assert (cm->slot < max_vtsize);
4676 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4677 TRACE_INTERFACE_VTABLE (printf ("adding iface override from %s [%p] to %s [%p]\n",
4678 mono_method_full_name (m1, 1), m1,
4679 mono_method_full_name (cm, 1), cm));
4680 g_hash_table_insert (override_map, m1, cm);
4684 if (k->exception_type)
4694 /*Non final newslot methods must be given a non-interface vtable slot*/
4695 if ((cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && !(cm->flags & METHOD_ATTRIBUTE_FINAL) && cm->slot >= 0)
4699 cm->slot = cur_slot++;
4701 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
4702 vtable [cm->slot] = cm;
4705 /* override non interface methods */
4706 for (i = 0; i < onum; i++) {
4707 MonoMethod *decl = overrides [i*2];
4708 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
4709 g_assert (decl->slot != -1);
4710 vtable [decl->slot] = overrides [i*2 + 1];
4711 overrides [i * 2 + 1]->slot = decl->slot;
4713 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
4714 TRACE_INTERFACE_VTABLE (printf ("adding explicit override from %s [%p] to %s [%p]\n",
4715 mono_method_full_name (decl, 1), decl,
4716 mono_method_full_name (overrides [i * 2 + 1], 1), overrides [i * 2 + 1]));
4717 g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
4719 if (mono_security_core_clr_enabled ())
4720 mono_security_core_clr_check_override (klass, vtable [decl->slot], decl);
4725 * If a method occupies more than one place in the vtable, and it is
4726 * overriden, then change the other occurances too.
4731 for (i = 0; i < max_vtsize; ++i)
4733 TRACE_INTERFACE_VTABLE (printf ("checking slot %d method %s[%p] for overrides\n", i, mono_method_full_name (vtable [i], 1), vtable [i]));
4735 cm = (MonoMethod *)g_hash_table_lookup (override_map, vtable [i]);
4740 g_hash_table_destroy (override_map);
4741 override_map = NULL;
4744 g_slist_free (virt_methods);
4745 virt_methods = NULL;
4747 /* Ensure that all vtable slots are filled with concrete instance methods */
4748 if (!(klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
4749 for (i = 0; i < cur_slot; ++i) {
4750 if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4751 char *type_name = mono_type_get_full_name (klass);
4752 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4753 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name));
4755 g_free (method_name);
4761 if (klass->generic_class) {
4762 MonoClass *gklass = klass->generic_class->container_class;
4764 mono_class_init (gklass);
4766 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4768 /* Check that the vtable_size value computed in mono_class_init () is correct */
4769 if (klass->vtable_size)
4770 g_assert (cur_slot == klass->vtable_size);
4771 klass->vtable_size = cur_slot;
4774 /* Try to share the vtable with our parent. */
4775 if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4776 mono_memory_barrier ();
4777 klass->vtable = klass->parent->vtable;
4779 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4780 memcpy (tmp, vtable, sizeof (gpointer) * klass->vtable_size);
4781 mono_memory_barrier ();
4782 klass->vtable = tmp;
4785 DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4786 if (mono_print_vtable) {
4789 print_implemented_interfaces (klass);
4791 for (i = 0; i <= max_iid; i++)
4792 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4795 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4796 klass->vtable_size, icount);
4798 for (i = 0; i < cur_slot; ++i) {
4803 printf (" slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4804 mono_method_full_name (cm, TRUE));
4810 printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4811 klass->name, max_iid);
4813 for (i = 0; i < klass->interface_count; i++) {
4814 ic = klass->interfaces [i];
4815 printf (" slot offset: %03d, method count: %03d, iid: %03d %s\n",
4816 mono_class_interface_offset (klass, ic),
4817 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4820 for (k = klass->parent; k ; k = k->parent) {
4821 for (i = 0; i < k->interface_count; i++) {
4822 ic = k->interfaces [i];
4823 printf (" parent slot offset: %03d, method count: %03d, iid: %03d %s\n",
4824 mono_class_interface_offset (klass, ic),
4825 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4831 VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4836 char *name = mono_type_get_full_name (klass);
4837 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("VTable setup of type %s failed", name));
4840 g_hash_table_destroy (override_map);
4842 g_slist_free (virt_methods);
4847 * mono_method_get_vtable_slot:
4849 * Returns method->slot, computing it if neccesary. Return -1 on failure.
4850 * LOCKING: Acquires the loader lock.
4852 * FIXME Use proper MonoError machinery here.
4855 mono_method_get_vtable_slot (MonoMethod *method)
4857 if (method->slot == -1) {
4858 mono_class_setup_vtable (method->klass);
4859 if (method->klass->exception_type)
4861 if (method->slot == -1) {
4865 if (!method->klass->generic_class) {
4866 g_assert (method->is_inflated);
4867 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4870 /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4871 g_assert (method->klass->generic_class);
4872 gklass = method->klass->generic_class->container_class;
4873 mono_class_setup_methods (method->klass);
4874 g_assert (method->klass->methods);
4875 for (i = 0; i < method->klass->method.count; ++i) {
4876 if (method->klass->methods [i] == method)
4879 g_assert (i < method->klass->method.count);
4880 g_assert (gklass->methods);
4881 method->slot = gklass->methods [i]->slot;
4883 g_assert (method->slot != -1);
4885 return method->slot;
4889 * mono_method_get_vtable_index:
4892 * Returns the index into the runtime vtable to access the method or,
4893 * in the case of a virtual generic method, the virtual generic method
4894 * thunk. Returns -1 on failure.
4896 * FIXME Use proper MonoError machinery here.
4899 mono_method_get_vtable_index (MonoMethod *method)
4901 if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4902 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4903 if (imethod->declaring->is_generic)
4904 return mono_method_get_vtable_slot (imethod->declaring);
4906 return mono_method_get_vtable_slot (method);
4909 static MonoMethod *default_ghc = NULL;
4910 static MonoMethod *default_finalize = NULL;
4911 static int finalize_slot = -1;
4912 static int ghc_slot = -1;
4915 initialize_object_slots (MonoClass *klass)
4920 if (klass == mono_defaults.object_class) {
4921 mono_class_setup_vtable (klass);
4922 for (i = 0; i < klass->vtable_size; ++i) {
4923 MonoMethod *cm = klass->vtable [i];
4925 if (!strcmp (cm->name, "GetHashCode"))
4927 else if (!strcmp (cm->name, "Finalize"))
4931 g_assert (ghc_slot > 0);
4932 default_ghc = klass->vtable [ghc_slot];
4934 g_assert (finalize_slot > 0);
4935 default_finalize = klass->vtable [finalize_slot];
4940 MonoMethod *array_method;
4942 } GenericArrayMethodInfo;
4944 static int generic_array_method_num = 0;
4945 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4948 generic_array_methods (MonoClass *klass)
4950 int i, count_generic = 0;
4951 GList *list = NULL, *tmp;
4952 if (generic_array_method_num)
4953 return generic_array_method_num;
4954 mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4955 g_assert (!klass->parent->exception_type); /*So hitting this assert is a huge problem*/
4956 for (i = 0; i < klass->parent->method.count; i++) {
4957 MonoMethod *m = klass->parent->methods [i];
4958 if (!strncmp (m->name, "InternalArray__", 15)) {
4960 list = g_list_prepend (list, m);
4963 list = g_list_reverse (list);
4964 generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4966 for (tmp = list; tmp; tmp = tmp->next) {
4967 const char *mname, *iname;
4969 MonoMethod *m = (MonoMethod *)tmp->data;
4970 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4971 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4973 generic_array_method_info [i].array_method = m;
4974 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4975 iname = "System.Collections.Generic.ICollection`1.";
4976 mname = m->name + 27;
4977 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4978 iname = "System.Collections.Generic.IEnumerable`1.";
4979 mname = m->name + 27;
4980 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4981 iname = "System.Collections.Generic.IReadOnlyList`1.";
4982 mname = m->name + strlen (ireadonlylist_prefix);
4983 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4984 iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4985 mname = m->name + strlen (ireadonlycollection_prefix);
4986 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4987 iname = "System.Collections.Generic.IList`1.";
4988 mname = m->name + 15;
4990 g_assert_not_reached ();
4993 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4994 strcpy (name, iname);
4995 strcpy (name + strlen (iname), mname);
4996 generic_array_method_info [i].name = name;
4999 /*g_print ("array generic methods: %d\n", count_generic);*/
5001 generic_array_method_num = count_generic;
5003 return generic_array_method_num;
5007 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
5009 MonoGenericContext tmp_context;
5012 tmp_context.class_inst = NULL;
5013 tmp_context.method_inst = iface->generic_class->context.class_inst;
5014 //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
5016 for (i = 0; i < generic_array_method_num; i++) {
5018 MonoMethod *m = generic_array_method_info [i].array_method;
5019 MonoMethod *inflated;
5021 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
5022 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
5023 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
5028 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
5030 int null_length = strlen ("(null)");
5031 int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
5032 char *s = (char *)mono_image_alloc (image, len);
5035 result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
5036 g_assert (result == len - 1);
5042 set_failure_from_loader_error (MonoClass *klass, MonoLoaderError *error)
5044 gpointer exception_data = NULL;
5046 switch (error->exception_type) {
5047 case MONO_EXCEPTION_TYPE_LOAD:
5048 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->assembly_name);
5051 case MONO_EXCEPTION_MISSING_METHOD:
5052 exception_data = concat_two_strings_with_zero (klass->image, error->class_name, error->member_name);
5055 case MONO_EXCEPTION_MISSING_FIELD: {
5056 const char *name_space = error->klass->name_space ? error->klass->name_space : NULL;
5057 const char *class_name;
5060 class_name = g_strdup_printf ("%s.%s", name_space, error->klass->name);
5062 class_name = error->klass->name;
5064 exception_data = concat_two_strings_with_zero (klass->image, class_name, error->member_name);
5067 g_free ((void*)class_name);
5071 case MONO_EXCEPTION_FILE_NOT_FOUND: {
5074 if (error->ref_only)
5075 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.";
5077 msg = "Could not load file or assembly '%s' or one of its dependencies.";
5079 exception_data = concat_two_strings_with_zero (klass->image, msg, error->assembly_name);
5083 case MONO_EXCEPTION_BAD_IMAGE:
5084 exception_data = error->msg;
5088 g_assert_not_reached ();
5091 mono_class_set_failure (klass, error->exception_type, exception_data);
5096 * @class: the class to initialize
5098 * Compute the instance_size, class_size and other infos that cannot be
5099 * computed at mono_class_get() time. Also compute vtable_size if possible.
5100 * Returns TRUE on success or FALSE if there was a problem in loading
5101 * the type (incorrect assemblies, missing assemblies, methods, etc).
5103 * LOCKING: Acquires the loader lock.
5106 mono_class_init (MonoClass *klass)
5109 MonoCachedClassInfo cached_info;
5110 gboolean has_cached_info;
5114 /* Double-checking locking pattern */
5115 if (klass->inited || klass->exception_type)
5116 return klass->exception_type == MONO_EXCEPTION_NONE;
5118 /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
5120 /* We do everything inside the lock to prevent races */
5121 mono_loader_lock ();
5123 if (klass->inited || klass->exception_type) {
5124 mono_loader_unlock ();
5125 /* Somebody might have gotten in before us */
5126 return klass->exception_type == MONO_EXCEPTION_NONE;
5129 if (klass->init_pending) {
5130 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Recursive type definition detected"));
5134 klass->init_pending = 1;
5136 if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
5137 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
5142 if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5143 MonoClass *element_class = klass->element_class;
5144 if (!element_class->inited)
5145 mono_class_init (element_class);
5146 if (element_class->exception_type != MONO_EXCEPTION_NONE) {
5147 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5152 mono_stats.initialized_class_count++;
5154 if (klass->generic_class && !klass->generic_class->is_dynamic) {
5155 MonoClass *gklass = klass->generic_class->container_class;
5157 mono_stats.generic_class_count++;
5159 klass->method = gklass->method;
5160 klass->field = gklass->field;
5162 mono_class_init (gklass);
5163 // FIXME: Why is this needed ?
5164 if (!gklass->exception_type)
5165 mono_class_setup_methods (gklass);
5166 if (gklass->exception_type) {
5167 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Generic Type Defintion failed to init"));
5171 if (MONO_CLASS_IS_INTERFACE (klass))
5172 klass->interface_id = mono_get_unique_iid (klass);
5175 if (klass->parent && !klass->parent->inited)
5176 mono_class_init (klass->parent);
5178 has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
5180 if (klass->generic_class || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5181 klass->nested_classes_inited = TRUE;
5184 * Computes the size used by the fields, and their locations
5186 if (has_cached_info) {
5187 klass->instance_size = cached_info.instance_size;
5188 klass->sizes.class_size = cached_info.class_size;
5189 klass->packing_size = cached_info.packing_size;
5190 klass->min_align = cached_info.min_align;
5191 klass->blittable = cached_info.blittable;
5192 klass->has_references = cached_info.has_references;
5193 klass->has_static_refs = cached_info.has_static_refs;
5194 klass->no_special_static_fields = cached_info.no_special_static_fields;
5197 if (!klass->size_inited){
5198 mono_class_setup_fields (klass);
5199 if (klass->exception_type || mono_loader_get_last_error ())
5203 /* Initialize arrays */
5205 klass->method.count = 3 + (klass->rank > 1? 2: 1);
5207 if (klass->interface_count) {
5208 int count_generic = generic_array_methods (klass);
5209 klass->method.count += klass->interface_count * count_generic;
5213 mono_class_setup_supertypes (klass);
5216 initialize_object_slots (klass);
5219 * Initialize the rest of the data without creating a generic vtable if possible.
5220 * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
5221 * also avoid computing a generic vtable.
5223 if (has_cached_info) {
5225 klass->vtable_size = cached_info.vtable_size;
5226 klass->has_finalize = cached_info.has_finalize;
5227 klass->has_finalize_inited = TRUE;
5228 klass->ghcimpl = cached_info.ghcimpl;
5229 klass->has_cctor = cached_info.has_cctor;
5230 } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5231 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
5232 * The first slot if for array with.
5234 static int szarray_vtable_size[2] = { 0 };
5236 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
5239 if (!szarray_vtable_size [slot]) {
5240 mono_class_setup_vtable (klass);
5241 szarray_vtable_size [slot] = klass->vtable_size;
5243 klass->vtable_size = szarray_vtable_size[slot];
5245 } else if (klass->generic_class && !MONO_CLASS_IS_INTERFACE (klass)) {
5246 MonoClass *gklass = klass->generic_class->container_class;
5248 /* Generic instance case */
5249 klass->ghcimpl = gklass->ghcimpl;
5250 klass->has_cctor = gklass->has_cctor;
5252 mono_class_setup_vtable (gklass);
5253 if (gklass->exception_type) {
5254 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5258 klass->vtable_size = gklass->vtable_size;
5262 /* ghcimpl is not currently used
5264 if (klass->parent) {
5265 MonoMethod *cmethod = klass->vtable [ghc_slot];
5266 if (cmethod->is_inflated)
5267 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5268 if (cmethod == default_ghc) {
5274 /* C# doesn't allow interfaces to have cctors */
5275 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
5276 MonoMethod *cmethod = NULL;
5278 if (klass->type_token && !image_is_dynamic(klass->image)) {
5279 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
5280 /* The find_method function ignores the 'flags' argument */
5281 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5282 klass->has_cctor = 1;
5284 mono_class_setup_methods (klass);
5285 if (klass->exception_type)
5288 for (i = 0; i < klass->method.count; ++i) {
5289 MonoMethod *method = klass->methods [i];
5290 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) &&
5291 (strcmp (".cctor", method->name) == 0)) {
5292 klass->has_cctor = 1;
5300 if (klass->parent) {
5301 int first_iface_slot;
5302 /* This will compute klass->parent->vtable_size for some classes */
5303 mono_class_init (klass->parent);
5304 if (klass->parent->exception_type) {
5305 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5308 if (mono_loader_get_last_error ())
5310 if (!klass->parent->vtable_size) {
5311 /* FIXME: Get rid of this somehow */
5312 mono_class_setup_vtable (klass->parent);
5313 if (klass->parent->exception_type) {
5314 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5317 if (mono_loader_get_last_error ())
5320 first_iface_slot = klass->parent->vtable_size;
5321 if (mono_class_need_stelemref_method (klass))
5323 setup_interface_offsets (klass, first_iface_slot, TRUE);
5325 setup_interface_offsets (klass, 0, TRUE);
5328 if (mono_security_core_clr_enabled ())
5329 mono_security_core_clr_check_inheritance (klass);
5331 if (mono_loader_get_last_error ()) {
5332 if (klass->exception_type == MONO_EXCEPTION_NONE) {
5333 set_failure_from_loader_error (klass, mono_loader_get_last_error ());
5335 mono_loader_clear_error ();
5338 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass))
5339 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Invalid generic instantiation"));
5344 /* Because of the double-checking locking pattern */
5345 mono_memory_barrier ();
5347 klass->init_pending = 0;
5349 mono_loader_unlock ();
5351 return klass->exception_type == MONO_EXCEPTION_NONE;
5355 * mono_class_has_finalizer:
5357 * Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5361 mono_class_has_finalizer (MonoClass *klass)
5363 gboolean has_finalize = FALSE;
5365 if (klass->has_finalize_inited)
5366 return klass->has_finalize;
5368 /* Interfaces and valuetypes are not supposed to have finalizers */
5369 if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5370 MonoMethod *cmethod = NULL;
5372 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5373 } else if (klass->generic_class) {
5374 MonoClass *gklass = klass->generic_class->container_class;
5376 has_finalize = mono_class_has_finalizer (gklass);
5377 } else if (klass->parent && klass->parent->has_finalize) {
5378 has_finalize = TRUE;
5380 if (klass->parent) {
5382 * Can't search in metadata for a method named Finalize, because that
5383 * ignores overrides.
5385 mono_class_setup_vtable (klass);
5386 if (klass->exception_type || mono_loader_get_last_error ())
5389 cmethod = klass->vtable [finalize_slot];
5393 g_assert (klass->vtable_size > finalize_slot);
5395 if (klass->parent) {
5396 if (cmethod->is_inflated)
5397 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5398 if (cmethod != default_finalize)
5399 has_finalize = TRUE;
5405 mono_image_lock (klass->image);
5407 if (!klass->has_finalize_inited) {
5408 klass->has_finalize = has_finalize ? 1 : 0;
5410 mono_memory_barrier ();
5411 klass->has_finalize_inited = TRUE;
5414 mono_image_unlock (klass->image);
5416 return klass->has_finalize;
5420 mono_is_corlib_image (MonoImage *image)
5422 /* FIXME: allow the dynamic case for our compilers and with full trust */
5423 if (image_is_dynamic (image))
5424 return image->assembly && !strcmp (image->assembly->aname.name, "mscorlib");
5426 return image == mono_defaults.corlib;
5430 * LOCKING: this assumes the loader lock is held
5433 mono_class_setup_mono_type (MonoClass *klass)
5435 const char *name = klass->name;
5436 const char *nspace = klass->name_space;
5437 gboolean is_corlib = mono_is_corlib_image (klass->image);
5439 klass->this_arg.byref = 1;
5440 klass->this_arg.data.klass = klass;
5441 klass->this_arg.type = MONO_TYPE_CLASS;
5442 klass->byval_arg.data.klass = klass;
5443 klass->byval_arg.type = MONO_TYPE_CLASS;
5445 if (is_corlib && !strcmp (nspace, "System")) {
5446 if (!strcmp (name, "ValueType")) {
5448 * do not set the valuetype bit for System.ValueType.
5449 * klass->valuetype = 1;
5451 klass->blittable = TRUE;
5452 } else if (!strcmp (name, "Enum")) {
5454 * do not set the valuetype bit for System.Enum.
5455 * klass->valuetype = 1;
5457 klass->valuetype = 0;
5458 klass->enumtype = 0;
5459 } else if (!strcmp (name, "Object")) {
5460 klass->byval_arg.type = MONO_TYPE_OBJECT;
5461 klass->this_arg.type = MONO_TYPE_OBJECT;
5462 } else if (!strcmp (name, "String")) {
5463 klass->byval_arg.type = MONO_TYPE_STRING;
5464 klass->this_arg.type = MONO_TYPE_STRING;
5465 } else if (!strcmp (name, "TypedReference")) {
5466 klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5467 klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5471 if (klass->valuetype) {
5472 int t = MONO_TYPE_VALUETYPE;
5474 if (is_corlib && !strcmp (nspace, "System")) {
5477 if (!strcmp (name, "Boolean")) {
5478 t = MONO_TYPE_BOOLEAN;
5479 } else if (!strcmp(name, "Byte")) {
5481 klass->blittable = TRUE;
5485 if (!strcmp (name, "Char")) {
5490 if (!strcmp (name, "Double")) {
5492 klass->blittable = TRUE;
5496 if (!strcmp (name, "Int32")) {
5498 klass->blittable = TRUE;
5499 } else if (!strcmp(name, "Int16")) {
5501 klass->blittable = TRUE;
5502 } else if (!strcmp(name, "Int64")) {
5504 klass->blittable = TRUE;
5505 } else if (!strcmp(name, "IntPtr")) {
5507 klass->blittable = TRUE;
5511 if (!strcmp (name, "Single")) {
5513 klass->blittable = TRUE;
5514 } else if (!strcmp(name, "SByte")) {
5516 klass->blittable = TRUE;
5520 if (!strcmp (name, "UInt32")) {
5522 klass->blittable = TRUE;
5523 } else if (!strcmp(name, "UInt16")) {
5525 klass->blittable = TRUE;
5526 } else if (!strcmp(name, "UInt64")) {
5528 klass->blittable = TRUE;
5529 } else if (!strcmp(name, "UIntPtr")) {
5531 klass->blittable = TRUE;
5535 if (!strcmp (name, "TypedReference")) {
5536 t = MONO_TYPE_TYPEDBYREF;
5537 klass->blittable = TRUE;
5541 if (!strcmp (name, "Void")) {
5549 klass->byval_arg.type = (MonoTypeEnum)t;
5550 klass->this_arg.type = (MonoTypeEnum)t;
5553 if (MONO_CLASS_IS_INTERFACE (klass))
5554 klass->interface_id = mono_get_unique_iid (klass);
5560 * COM initialization is delayed until needed.
5561 * However when a [ComImport] attribute is present on a type it will trigger
5562 * the initialization. This is not a problem unless the BCL being executed
5563 * lacks the types that COM depends on (e.g. Variant on Silverlight).
5566 init_com_from_comimport (MonoClass *klass)
5568 /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5569 if (mono_security_core_clr_enabled ()) {
5570 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5571 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5572 /* but it can not be made available for application (i.e. user code) since all COM calls
5573 * are considered native calls. In this case we fail with a TypeLoadException (just like
5574 * Silverlight 2 does */
5575 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5580 /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5582 #endif /*DISABLE_COM*/
5585 * LOCKING: this assumes the loader lock is held
5588 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5590 gboolean system_namespace;
5591 gboolean is_corlib = mono_is_corlib_image (klass->image);
5593 system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5595 /* if root of the hierarchy */
5596 if (system_namespace && !strcmp (klass->name, "Object")) {
5597 klass->parent = NULL;
5598 klass->instance_size = sizeof (MonoObject);
5601 if (!strcmp (klass->name, "<Module>")) {
5602 klass->parent = NULL;
5603 klass->instance_size = 0;
5607 if (!MONO_CLASS_IS_INTERFACE (klass)) {
5608 /* Imported COM Objects always derive from __ComObject. */
5610 if (MONO_CLASS_IS_IMPORT (klass)) {
5611 init_com_from_comimport (klass);
5612 if (parent == mono_defaults.object_class)
5613 parent = mono_class_get_com_object_class ();
5617 /* set the parent to something useful and safe, but mark the type as broken */
5618 parent = mono_defaults.object_class;
5619 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5622 klass->parent = parent;
5624 if (parent->generic_class && !parent->name) {
5626 * If the parent is a generic instance, we may get
5627 * called before it is fully initialized, especially
5628 * before it has its name.
5633 #ifndef DISABLE_REMOTING
5634 klass->marshalbyref = parent->marshalbyref;
5635 klass->contextbound = parent->contextbound;
5638 klass->delegate = parent->delegate;
5640 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5641 mono_class_set_is_com_object (klass);
5643 if (system_namespace) {
5644 #ifndef DISABLE_REMOTING
5645 if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5646 klass->marshalbyref = 1;
5648 if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject"))
5649 klass->contextbound = 1;
5651 if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate"))
5652 klass->delegate = 1;
5655 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) &&
5656 (strcmp (klass->parent->name_space, "System") == 0)))
5657 klass->valuetype = 1;
5658 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5659 klass->valuetype = klass->enumtype = 1;
5661 /*klass->enumtype = klass->parent->enumtype; */
5663 /* initialize com types if COM interfaces are present */
5665 if (MONO_CLASS_IS_IMPORT (klass))
5666 init_com_from_comimport (klass);
5668 klass->parent = NULL;
5674 * mono_class_setup_supertypes:
5677 * Build the data structure needed to make fast type checks work.
5678 * This currently sets two fields in @class:
5679 * - idepth: distance between @class and System.Object in the type
5681 * - supertypes: array of classes: each element has a class in the hierarchy
5682 * starting from @class up to System.Object
5684 * LOCKING: This function is atomic, in case of contention we waste memory.
5687 mono_class_setup_supertypes (MonoClass *klass)
5690 MonoClass **supertypes;
5692 mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5696 if (klass->parent && !klass->parent->supertypes)
5697 mono_class_setup_supertypes (klass->parent);
5699 klass->idepth = klass->parent->idepth + 1;
5703 ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5704 supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5706 if (klass->parent) {
5707 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5710 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5711 CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5713 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5716 CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5720 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5722 MonoClass *gtd = (MonoClass*)user_data;
5723 /* Only try to fix generic instances of @gtd */
5724 if (gclass->generic_class->container_class != gtd)
5727 /* Check if the generic instance has no parent. */
5728 if (gtd->parent && !gclass->parent)
5729 mono_generic_class_setup_parent (gclass, gtd);
5735 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5737 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5738 mono_error_set_type_load_class (error, klass, msg);
5742 mono_class_set_failure_from_loader_error (MonoClass *klass, MonoError *error, char *msg)
5744 MonoLoaderError *lerror = mono_loader_get_last_error ();
5747 set_failure_from_loader_error (klass, lerror);
5748 mono_error_set_from_loader_error (error);
5752 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, msg);
5753 mono_error_set_type_load_class (error, klass, msg);
5758 * mono_class_create_from_typedef:
5759 * @image: image where the token is valid
5760 * @type_token: typedef token
5761 * @error: used to return any error found while creating the type
5763 * Create the MonoClass* representing the specified type token.
5764 * @type_token must be a TypeDef token.
5766 * FIXME: don't return NULL on failure, just the the caller figure it out.
5769 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5771 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5772 MonoClass *klass, *parent = NULL;
5773 guint32 cols [MONO_TYPEDEF_SIZE];
5774 guint32 cols_next [MONO_TYPEDEF_SIZE];
5775 guint tidx = mono_metadata_token_index (type_token);
5776 MonoGenericContext *context = NULL;
5777 const char *name, *nspace;
5779 MonoClass **interfaces;
5780 guint32 field_last, method_last;
5781 guint32 nesting_tokeen;
5783 mono_error_init (error);
5785 if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5786 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5787 mono_loader_assert_no_error ();
5791 mono_loader_lock ();
5793 if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5794 mono_loader_unlock ();
5795 mono_loader_assert_no_error ();
5799 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5801 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5802 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5804 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5807 klass->name_space = nspace;
5809 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5811 klass->image = image;
5812 klass->type_token = type_token;
5813 klass->flags = cols [MONO_TYPEDEF_FLAGS];
5815 mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5817 classes_size += sizeof (MonoClass);
5820 * Check whether we're a generic type definition.
5822 klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5823 if (klass->generic_container) {
5824 klass->is_generic = 1;
5825 klass->generic_container->owner.klass = klass;
5826 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5827 context = &klass->generic_container->context;
5830 if (klass->generic_container)
5831 enable_gclass_recording ();
5833 if (cols [MONO_TYPEDEF_EXTENDS]) {
5835 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5837 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5838 /*WARNING: this must satisfy mono_metadata_type_hash*/
5839 klass->this_arg.byref = 1;
5840 klass->this_arg.data.klass = klass;
5841 klass->this_arg.type = MONO_TYPE_CLASS;
5842 klass->byval_arg.data.klass = klass;
5843 klass->byval_arg.type = MONO_TYPE_CLASS;
5845 parent = mono_class_get_checked (image, parent_token, error);
5846 if (parent && context) /* Always inflate */
5847 parent = mono_class_inflate_generic_class_checked (parent, context, error);
5849 if (parent == NULL) {
5850 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5851 goto parent_failure;
5854 for (tmp = parent; tmp; tmp = tmp->parent) {
5856 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5857 goto parent_failure;
5859 if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5860 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5861 goto parent_failure;
5866 mono_class_setup_parent (klass, parent);
5868 /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5869 mono_class_setup_mono_type (klass);
5871 if (klass->generic_container)
5872 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5875 * This might access klass->byval_arg for recursion generated by generic constraints,
5876 * so it has to come after setup_mono_type ().
5878 if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5879 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5880 if (!mono_error_ok (error)) {
5881 /*FIXME implement a mono_class_set_failure_from_mono_error */
5882 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5883 mono_loader_unlock ();
5884 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5885 mono_loader_assert_no_error ();
5890 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5894 if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5898 klass->cast_class = klass->element_class = klass;
5900 if (!klass->enumtype) {
5901 if (!mono_metadata_interfaces_from_typedef_full (
5902 image, type_token, &interfaces, &icount, FALSE, context, error)){
5904 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5905 mono_loader_unlock ();
5906 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5910 klass->interfaces = interfaces;
5911 klass->interface_count = icount;
5912 klass->interfaces_inited = 1;
5915 /*g_print ("Load class %s\n", name);*/
5918 * Compute the field and method lists
5920 klass->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5921 klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5923 if (tt->rows > tidx){
5924 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5925 field_last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5926 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5928 field_last = image->tables [MONO_TABLE_FIELD].rows;
5929 method_last = image->tables [MONO_TABLE_METHOD].rows;
5932 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
5933 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5934 klass->field.count = field_last - klass->field.first;
5936 klass->field.count = 0;
5938 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5939 klass->method.count = method_last - klass->method.first;
5941 klass->method.count = 0;
5943 /* reserve space to store vector pointer in arrays */
5944 if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5945 klass->instance_size += 2 * sizeof (gpointer);
5946 g_assert (klass->field.count == 0);
5949 if (klass->enumtype) {
5950 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5951 if (!enum_basetype) {
5952 /*set it to a default value as the whole runtime can't handle this to be null*/
5953 klass->cast_class = klass->element_class = mono_defaults.int32_class;
5954 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5955 mono_loader_unlock ();
5956 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5957 mono_loader_assert_no_error ();
5960 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5964 * If we're a generic type definition, load the constraints.
5965 * We must do this after the class has been constructed to make certain recursive scenarios
5968 if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5969 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup_printf ("Could not load generic parameter constrains due to %s", mono_error_get_message (error)));
5970 mono_loader_unlock ();
5971 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5972 mono_loader_assert_no_error ();
5976 if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5977 if (!strncmp (name, "Vector", 6))
5978 klass->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");
5981 mono_loader_unlock ();
5983 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5984 mono_loader_assert_no_error ();
5989 mono_class_setup_mono_type (klass);
5990 mono_loader_unlock ();
5991 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5992 mono_loader_assert_no_error ();
5996 /** Is klass a Nullable<T> ginst? */
5998 mono_class_is_nullable (MonoClass *klass)
6000 return klass->generic_class != NULL &&
6001 klass->generic_class->container_class == mono_defaults.generic_nullable_class;
6005 /** if klass is T? return T */
6007 mono_class_get_nullable_param (MonoClass *klass)
6009 g_assert (mono_class_is_nullable (klass));
6010 return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
6014 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
6018 MonoGenericClass *gclass = klass->generic_class;
6020 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
6021 if (!mono_error_ok (&error)) {
6022 /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
6023 klass->parent = mono_defaults.object_class;
6024 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6025 mono_error_cleanup (&error);
6029 mono_class_setup_parent (klass, klass->parent);
6031 if (klass->enumtype) {
6032 klass->cast_class = gtd->cast_class;
6033 klass->element_class = gtd->element_class;
6039 * Create the `MonoClass' for an instantiation of a generic type.
6040 * We only do this if we actually need it.
6043 mono_generic_class_get_class (MonoGenericClass *gclass)
6045 MonoClass *klass, *gklass;
6047 if (gclass->cached_class)
6048 return gclass->cached_class;
6050 mono_loader_lock ();
6051 if (gclass->cached_class) {
6052 mono_loader_unlock ();
6053 return gclass->cached_class;
6056 klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6058 gklass = gclass->container_class;
6060 if (record_gclass_instantiation > 0)
6061 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6063 if (gklass->nested_in) {
6064 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6065 klass->nested_in = gklass->nested_in;
6068 klass->name = gklass->name;
6069 klass->name_space = gklass->name_space;
6071 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6073 klass->image = gklass->image;
6074 klass->flags = gklass->flags;
6075 klass->type_token = gklass->type_token;
6076 klass->field.count = gklass->field.count;
6078 klass->is_inflated = 1;
6079 klass->generic_class = gclass;
6081 klass->byval_arg.type = MONO_TYPE_GENERICINST;
6082 klass->this_arg.type = klass->byval_arg.type;
6083 klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6084 klass->this_arg.byref = TRUE;
6085 klass->enumtype = gklass->enumtype;
6086 klass->valuetype = gklass->valuetype;
6088 klass->cast_class = klass->element_class = klass;
6090 if (mono_class_is_nullable (klass))
6091 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6094 * We're not interested in the nested classes of a generic instance.
6095 * We use the generic type definition to look for nested classes.
6098 mono_generic_class_setup_parent (klass, gklass);
6100 if (gclass->is_dynamic) {
6102 * We don't need to do any init workf with unbaked typebuilders. Generic instances created at this point will be later unregistered and/or fixed.
6103 * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6104 * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6106 if (!gklass->wastypebuilder)
6109 mono_class_setup_supertypes (klass);
6111 if (klass->enumtype) {
6113 * For enums, gklass->fields might not been set, but instance_size etc. is
6114 * already set in mono_reflection_create_internal_class (). For non-enums,
6115 * these will be computed normally in mono_class_layout_fields ().
6117 klass->instance_size = gklass->instance_size;
6118 klass->sizes.class_size = gklass->sizes.class_size;
6119 mono_memory_barrier ();
6120 klass->size_inited = 1;
6124 mono_memory_barrier ();
6125 gclass->cached_class = klass;
6127 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6129 inflated_classes ++;
6130 inflated_classes_size += sizeof (MonoClass);
6132 mono_loader_unlock ();
6138 get_image_for_container (MonoGenericContainer *container)
6141 if (container->is_anonymous) {
6142 result = container->owner.image;
6145 if (container->is_method) {
6146 MonoMethod *method = container->owner.method;
6147 g_assert_checked (method);
6148 klass = method->klass;
6150 klass = container->owner.klass;
6152 g_assert_checked (klass);
6153 result = klass->image;
6160 get_image_for_generic_param (MonoGenericParam *param)
6162 MonoGenericContainer *container = mono_generic_param_owner (param);
6163 g_assert_checked (container);
6164 return get_image_for_container (container);
6167 // Make a string in the designated image consisting of a single integer.
6168 #define INT_STRING_SIZE 16
6170 make_generic_name_string (MonoImage *image, int num)
6172 char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6173 g_snprintf (name, INT_STRING_SIZE, "%d", num);
6177 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6178 // pinfo is derived from param by the caller for us.
6180 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6182 MonoClass *klass, **ptr;
6184 MonoGenericContainer *container = mono_generic_param_owner (param);
6185 g_assert_checked (container);
6187 MonoImage *image = get_image_for_container (container);
6188 gboolean is_mvar = container->is_method;
6189 gboolean is_anonymous = container->is_anonymous;
6191 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6192 classes_size += sizeof (MonoClass);
6195 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6197 int n = mono_generic_param_num (param);
6198 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6202 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , "" );
6203 } else if (is_mvar) {
6204 MonoMethod *omethod = container->owner.method;
6205 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6207 MonoClass *oklass = container->owner.klass;
6208 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6211 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6213 // Count non-NULL items in pinfo->constraints
6216 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6220 if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6221 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6223 } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6224 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_from_name (mono_defaults.corlib, "System", "ValueType") );
6226 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6229 if (count - pos > 0) {
6230 klass->interface_count = count - pos;
6231 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6232 klass->interfaces_inited = TRUE;
6233 for (i = pos; i < count; i++)
6234 CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6237 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6239 klass->inited = TRUE;
6240 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class , klass );
6241 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6242 klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6244 klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6245 klass->this_arg.type = klass->byval_arg.type;
6246 CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param , param );
6247 CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6248 klass->this_arg.byref = TRUE;
6250 /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6251 klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6253 /*Init these fields to sane values*/
6254 klass->min_align = 1;
6256 * This makes sure the the value size of this class is equal to the size of the types the gparam is
6257 * constrained to, the JIT depends on this.
6259 klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6260 mono_memory_barrier ();
6261 klass->size_inited = 1;
6262 klass->setup_fields_called = 1;
6264 mono_class_setup_supertypes (klass);
6266 if (count - pos > 0) {
6267 mono_class_setup_vtable (klass->parent);
6268 if (klass->parent->exception_type)
6269 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6271 setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6277 #define FAST_CACHE_SIZE 16
6280 * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6281 * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6282 * we cache the MonoClasses.
6283 * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6284 * LOCKING: Takes the image lock depending on @take_lock.
6287 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6289 int n = mono_generic_param_num (param);
6290 MonoImage *image = get_image_for_generic_param (param);
6291 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6292 MonoClass *klass = NULL;
6297 // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6298 // For high numbers or constraints we have to use pointer hashes.
6299 if (param->gshared_constraint) {
6300 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6303 mono_image_lock (image);
6304 klass = (MonoClass *)g_hash_table_lookup (ht, param);
6306 mono_image_unlock (image);
6311 if (n < FAST_CACHE_SIZE) {
6313 return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6315 return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6317 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6320 mono_image_lock (image);
6321 klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6323 mono_image_unlock (image);
6330 * LOCKING: Image lock (param->image) must be held
6333 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6335 int n = mono_generic_param_num (param);
6336 MonoImage *image = get_image_for_generic_param (param);
6337 gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6341 if (param->gshared_constraint) {
6342 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6344 ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6345 mono_memory_barrier ();
6347 image->mvar_cache_constrained = ht;
6349 image->var_cache_constrained = ht;
6351 g_hash_table_insert (ht, param, klass);
6352 } else if (n < FAST_CACHE_SIZE) {
6354 /* Requires locking to avoid droping an already published class */
6355 if (!image->mvar_cache_fast)
6356 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6357 image->mvar_cache_fast [n] = klass;
6359 if (!image->var_cache_fast)
6360 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6361 image->var_cache_fast [n] = klass;
6364 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6366 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6368 ht = g_hash_table_new (NULL, NULL);
6369 mono_memory_barrier ();
6371 image->mvar_cache_slow = ht;
6373 image->var_cache_slow = ht;
6376 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6381 * LOCKING: Acquires the image lock (@image).
6384 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6386 MonoImage *image = get_image_for_generic_param (param);
6387 MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6388 MonoClass *klass, *klass2;
6390 // If a klass already exists for this object and is cached, return it.
6391 if (pinfo) // Non-anonymous
6392 klass = pinfo->pklass;
6394 klass = get_anon_gparam_class (param, TRUE);
6399 // Create a new klass
6400 klass = make_generic_param_class (param, pinfo);
6402 // Now we need to cache the klass we created.
6403 // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6404 // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6405 // and allow our newly-created klass object to just leak.
6406 mono_memory_barrier ();
6408 mono_image_lock (image);
6410 // Here "klass2" refers to the klass potentially created by the other thread.
6411 if (pinfo) // Repeat check from above
6412 klass2 = pinfo->pklass;
6414 klass2 = get_anon_gparam_class (param, FALSE);
6421 pinfo->pklass = klass;
6423 set_anon_gparam_class (param, klass);
6425 mono_image_unlock (image);
6427 /* FIXME: Should this go inside 'make_generic_param_klass'? */
6429 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6431 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6437 * mono_class_from_generic_parameter:
6438 * @param: Parameter to find/construct a class for.
6439 * @arg2: Is ignored.
6440 * @arg3: Is ignored.
6443 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6445 return mono_class_from_generic_parameter_internal (param);
6450 mono_ptr_class_get (MonoType *type)
6453 MonoClass *el_class;
6457 el_class = mono_class_from_mono_type (type);
6458 image = el_class->image;
6460 mono_image_lock (image);
6461 if (image->ptr_cache) {
6462 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6463 mono_image_unlock (image);
6467 mono_image_unlock (image);
6469 result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6471 classes_size += sizeof (MonoClass);
6473 result->parent = NULL; /* no parent for PTR types */
6474 result->name_space = el_class->name_space;
6475 name = g_strdup_printf ("%s*", el_class->name);
6476 result->name = mono_image_strdup (image, name);
6479 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6481 result->image = el_class->image;
6482 result->inited = TRUE;
6483 result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6484 /* Can pointers get boxed? */
6485 result->instance_size = sizeof (gpointer);
6486 result->cast_class = result->element_class = el_class;
6487 result->blittable = TRUE;
6489 result->byval_arg.type = MONO_TYPE_PTR;
6490 result->this_arg.type = result->byval_arg.type;
6491 result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6492 result->this_arg.byref = TRUE;
6494 mono_class_setup_supertypes (result);
6496 mono_image_lock (image);
6497 if (image->ptr_cache) {
6499 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6500 mono_image_unlock (image);
6501 mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6505 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6507 g_hash_table_insert (image->ptr_cache, el_class, result);
6508 mono_image_unlock (image);
6510 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6516 mono_fnptr_class_get (MonoMethodSignature *sig)
6519 static GHashTable *ptr_hash = NULL;
6521 /* FIXME: These should be allocate from a mempool as well, but which one ? */
6523 mono_loader_lock ();
6526 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6528 if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6529 mono_loader_unlock ();
6532 result = g_new0 (MonoClass, 1);
6534 result->parent = NULL; /* no parent for PTR types */
6535 result->name_space = "System";
6536 result->name = "MonoFNPtrFakeClass";
6538 mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6540 result->image = mono_defaults.corlib; /* need to fix... */
6541 result->inited = TRUE;
6542 result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6543 /* Can pointers get boxed? */
6544 result->instance_size = sizeof (gpointer);
6545 result->cast_class = result->element_class = result;
6546 result->blittable = TRUE;
6548 result->byval_arg.type = MONO_TYPE_FNPTR;
6549 result->this_arg.type = result->byval_arg.type;
6550 result->this_arg.data.method = result->byval_arg.data.method = sig;
6551 result->this_arg.byref = TRUE;
6552 result->blittable = TRUE;
6554 mono_class_setup_supertypes (result);
6556 g_hash_table_insert (ptr_hash, sig, result);
6558 mono_loader_unlock ();
6560 mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6566 * mono_class_from_mono_type:
6567 * @type: describes the type to return
6569 * This returns a MonoClass for the specified MonoType, the value is never NULL.
6572 mono_class_from_mono_type (MonoType *type)
6574 switch (type->type) {
6575 case MONO_TYPE_OBJECT:
6576 return type->data.klass? type->data.klass: mono_defaults.object_class;
6577 case MONO_TYPE_VOID:
6578 return type->data.klass? type->data.klass: mono_defaults.void_class;
6579 case MONO_TYPE_BOOLEAN:
6580 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6581 case MONO_TYPE_CHAR:
6582 return type->data.klass? type->data.klass: mono_defaults.char_class;
6584 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6586 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6588 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6590 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6592 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6594 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6596 return type->data.klass? type->data.klass: mono_defaults.int_class;
6598 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6600 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6602 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6604 return type->data.klass? type->data.klass: mono_defaults.single_class;
6606 return type->data.klass? type->data.klass: mono_defaults.double_class;
6607 case MONO_TYPE_STRING:
6608 return type->data.klass? type->data.klass: mono_defaults.string_class;
6609 case MONO_TYPE_TYPEDBYREF:
6610 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6611 case MONO_TYPE_ARRAY:
6612 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6614 return mono_ptr_class_get (type->data.type);
6615 case MONO_TYPE_FNPTR:
6616 return mono_fnptr_class_get (type->data.method);
6617 case MONO_TYPE_SZARRAY:
6618 return mono_array_class_get (type->data.klass, 1);
6619 case MONO_TYPE_CLASS:
6620 case MONO_TYPE_VALUETYPE:
6621 return type->data.klass;
6622 case MONO_TYPE_GENERICINST:
6623 return mono_generic_class_get_class (type->data.generic_class);
6624 case MONO_TYPE_MVAR:
6626 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6628 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6629 g_assert_not_reached ();
6632 // Yes, this returns NULL, even if it is documented as not doing so, but there
6633 // is no way for the code to make it this far, due to the assert above.
6638 * mono_type_retrieve_from_typespec
6639 * @image: context where the image is created
6640 * @type_spec: typespec token
6641 * @context: the generic context used to evaluate generic instantiations in
6644 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6646 MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6648 *did_inflate = FALSE;
6653 if (context && (context->class_inst || context->method_inst)) {
6654 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6656 if (!mono_error_ok (error)) {
6657 mono_loader_assert_no_error ();
6663 *did_inflate = TRUE;
6670 * mono_class_create_from_typespec
6671 * @image: context where the image is created
6672 * @type_spec: typespec token
6673 * @context: the generic context used to evaluate generic instantiations in
6676 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6679 gboolean inflated = FALSE;
6680 MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6681 return_val_if_nok (error, NULL);
6682 ret = mono_class_from_mono_type (t);
6684 mono_metadata_free_type (t);
6689 * mono_bounded_array_class_get:
6690 * @element_class: element class
6691 * @rank: the dimension of the array class
6692 * @bounded: whenever the array has non-zero bounds
6694 * Returns: A class object describing the array with element type @element_type and
6698 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6702 MonoClass *parent = NULL;
6703 GSList *list, *rootlist = NULL;
6706 gboolean corlib_type = FALSE;
6708 g_assert (rank <= 255);
6711 /* bounded only matters for one-dimensional arrays */
6714 image = eclass->image;
6716 if (rank == 1 && !bounded) {
6718 * This case is very frequent not just during compilation because of calls
6719 * from mono_class_from_mono_type (), mono_array_new (),
6720 * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6722 mono_os_mutex_lock (&image->szarray_cache_lock);
6723 if (!image->szarray_cache)
6724 image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6725 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6726 mono_os_mutex_unlock (&image->szarray_cache_lock);
6730 mono_loader_lock ();
6732 mono_loader_lock ();
6734 if (!image->array_cache)
6735 image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6737 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6738 for (; list; list = list->next) {
6739 klass = (MonoClass *)list->data;
6740 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6741 mono_loader_unlock ();
6748 /* for the building corlib use System.Array from it */
6749 if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6750 parent = mono_class_from_name (image, "System", "Array");
6753 parent = mono_defaults.array_class;
6754 if (!parent->inited)
6755 mono_class_init (parent);
6758 klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6760 klass->image = image;
6761 klass->name_space = eclass->name_space;
6762 nsize = strlen (eclass->name);
6763 name = (char *)g_malloc (nsize + 2 + rank + 1);
6764 memcpy (name, eclass->name, nsize);
6767 memset (name + nsize + 1, ',', rank - 1);
6769 name [nsize + rank] = '*';
6770 name [nsize + rank + bounded] = ']';
6771 name [nsize + rank + bounded + 1] = 0;
6772 klass->name = mono_image_strdup (image, name);
6775 mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6777 classes_size += sizeof (MonoClass);
6779 klass->type_token = 0;
6780 /* all arrays are marked serializable and sealed, bug #42779 */
6781 klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6782 klass->parent = parent;
6783 klass->instance_size = mono_class_instance_size (klass->parent);
6785 if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6786 /*Arrays of those two types are invalid.*/
6787 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6788 } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6789 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6790 g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6791 g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6793 /* element_size -1 is ok as this is not an instantitable type*/
6794 klass->sizes.element_size = -1;
6796 klass->sizes.element_size = mono_class_array_element_size (eclass);
6798 mono_class_setup_supertypes (klass);
6800 if (eclass->generic_class)
6801 mono_class_init (eclass);
6802 if (!eclass->size_inited)
6803 mono_class_setup_fields (eclass);
6804 if (eclass->exception_type) /*FIXME we fail the array type, but we have to let other fields be set.*/
6805 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6807 klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6811 if (eclass->enumtype)
6812 klass->cast_class = eclass->element_class;
6814 klass->cast_class = eclass;
6816 switch (klass->cast_class->byval_arg.type) {
6818 klass->cast_class = mono_defaults.byte_class;
6821 klass->cast_class = mono_defaults.int16_class;
6824 #if SIZEOF_VOID_P == 4
6828 klass->cast_class = mono_defaults.int32_class;
6831 #if SIZEOF_VOID_P == 8
6835 klass->cast_class = mono_defaults.int64_class;
6841 klass->element_class = eclass;
6843 if ((rank > 1) || bounded) {
6844 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6845 klass->byval_arg.type = MONO_TYPE_ARRAY;
6846 klass->byval_arg.data.array = at;
6847 at->eklass = eclass;
6849 /* FIXME: complete.... */
6851 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6852 klass->byval_arg.data.klass = eclass;
6854 klass->this_arg = klass->byval_arg;
6855 klass->this_arg.byref = 1;
6860 klass->generic_container = eclass->generic_container;
6862 if (rank == 1 && !bounded) {
6863 MonoClass *prev_class;
6865 mono_os_mutex_lock (&image->szarray_cache_lock);
6866 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6868 /* Someone got in before us */
6871 g_hash_table_insert (image->szarray_cache, eclass, klass);
6872 mono_os_mutex_unlock (&image->szarray_cache_lock);
6874 list = g_slist_append (rootlist, klass);
6875 g_hash_table_insert (image->array_cache, eclass, list);
6878 mono_loader_unlock ();
6880 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6886 * mono_array_class_get:
6887 * @element_class: element class
6888 * @rank: the dimension of the array class
6890 * Returns: A class object describing the array with element type @element_type and
6894 mono_array_class_get (MonoClass *eclass, guint32 rank)
6896 return mono_bounded_array_class_get (eclass, rank, FALSE);
6900 * mono_class_instance_size:
6903 * Use to get the size of a class in bytes.
6905 * Returns: The size of an object instance
6908 mono_class_instance_size (MonoClass *klass)
6910 if (!klass->size_inited)
6911 mono_class_init (klass);
6913 return klass->instance_size;
6917 * mono_class_min_align:
6920 * Use to get the computed minimum alignment requirements for the specified class.
6922 * Returns: minimm alignment requirements
6925 mono_class_min_align (MonoClass *klass)
6927 if (!klass->size_inited)
6928 mono_class_init (klass);
6930 return klass->min_align;
6934 * mono_class_value_size:
6937 * This function is used for value types, and return the
6938 * space and the alignment to store that kind of value object.
6940 * Returns: the size of a value of kind @klass
6943 mono_class_value_size (MonoClass *klass, guint32 *align)
6947 /* fixme: check disable, because we still have external revereces to
6948 * mscorlib and Dummy Objects
6950 /*g_assert (klass->valuetype);*/
6952 size = mono_class_instance_size (klass) - sizeof (MonoObject);
6955 *align = klass->min_align;
6961 * mono_class_data_size:
6964 * Returns: The size of the static class data
6967 mono_class_data_size (MonoClass *klass)
6970 mono_class_init (klass);
6971 /* This can happen with dynamically created types */
6972 if (!klass->fields_inited)
6973 mono_class_setup_fields_locking (klass);
6975 /* in arrays, sizes.class_size is unioned with element_size
6976 * and arrays have no static fields
6980 return klass->sizes.class_size;
6984 * Auxiliary routine to mono_class_get_field
6986 * Takes a field index instead of a field token.
6988 static MonoClassField *
6989 mono_class_get_field_idx (MonoClass *klass, int idx)
6991 mono_class_setup_fields_locking (klass);
6992 if (klass->exception_type)
6996 if (klass->image->uncompressed_metadata) {
6998 * klass->field.first points to the FieldPtr table, while idx points into the
6999 * Field table, so we have to do a search.
7001 /*FIXME this is broken for types with multiple fields with the same name.*/
7002 const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
7005 for (i = 0; i < klass->field.count; ++i)
7006 if (mono_field_get_name (&klass->fields [i]) == name)
7007 return &klass->fields [i];
7008 g_assert_not_reached ();
7010 if (klass->field.count) {
7011 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
7012 return &klass->fields [idx - klass->field.first];
7016 klass = klass->parent;
7022 * mono_class_get_field:
7023 * @class: the class to lookup the field.
7024 * @field_token: the field token
7026 * Returns: A MonoClassField representing the type and offset of
7027 * the field, or a NULL value if the field does not belong to this
7031 mono_class_get_field (MonoClass *klass, guint32 field_token)
7033 int idx = mono_metadata_token_index (field_token);
7035 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
7037 return mono_class_get_field_idx (klass, idx - 1);
7041 * mono_class_get_field_from_name:
7042 * @klass: the class to lookup the field.
7043 * @name: the field name
7045 * Search the class @klass and it's parents for a field with the name @name.
7047 * Returns: The MonoClassField pointer of the named field or NULL
7050 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7052 return mono_class_get_field_from_name_full (klass, name, NULL);
7056 * mono_class_get_field_from_name_full:
7057 * @klass: the class to lookup the field.
7058 * @name: the field name
7059 * @type: the type of the fields. This optional.
7061 * Search the class @klass and it's parents for a field with the name @name and type @type.
7063 * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7064 * of its generic type definition.
7066 * Returns: The MonoClassField pointer of the named field or NULL
7069 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7073 mono_class_setup_fields_locking (klass);
7074 if (klass->exception_type)
7078 for (i = 0; i < klass->field.count; ++i) {
7079 MonoClassField *field = &klass->fields [i];
7081 if (strcmp (name, mono_field_get_name (field)) != 0)
7085 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7086 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7091 klass = klass->parent;
7097 * mono_class_get_field_token:
7098 * @field: the field we need the token of
7100 * Get the token of a field. Note that the tokesn is only valid for the image
7101 * the field was loaded from. Don't use this function for fields in dynamic types.
7103 * Returns: The token representing the field in the image it was loaded from.
7106 mono_class_get_field_token (MonoClassField *field)
7108 MonoClass *klass = field->parent;
7111 mono_class_setup_fields_locking (klass);
7116 for (i = 0; i < klass->field.count; ++i) {
7117 if (&klass->fields [i] == field) {
7118 int idx = klass->field.first + i + 1;
7120 if (klass->image->uncompressed_metadata)
7121 idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7122 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7125 klass = klass->parent;
7128 g_assert_not_reached ();
7133 mono_field_get_index (MonoClassField *field)
7135 int index = field - field->parent->fields;
7137 g_assert (index >= 0 && index < field->parent->field.count);
7143 * mono_class_get_field_default_value:
7145 * Return the default value of the field as a pointer into the metadata blob.
7148 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7151 guint32 constant_cols [MONO_CONSTANT_SIZE];
7153 MonoClass *klass = field->parent;
7155 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7157 if (!klass->ext || !klass->ext->field_def_values) {
7158 MonoFieldDefaultValue *def_values;
7160 mono_class_alloc_ext (klass);
7162 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7164 mono_image_lock (klass->image);
7165 mono_memory_barrier ();
7166 if (!klass->ext->field_def_values)
7167 klass->ext->field_def_values = def_values;
7168 mono_image_unlock (klass->image);
7171 field_index = mono_field_get_index (field);
7173 if (!klass->ext->field_def_values [field_index].data) {
7174 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7178 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7180 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7181 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7182 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7185 *def_type = klass->ext->field_def_values [field_index].def_type;
7186 return klass->ext->field_def_values [field_index].data;
7190 mono_property_get_index (MonoProperty *prop)
7192 int index = prop - prop->parent->ext->properties;
7194 g_assert (index >= 0 && index < prop->parent->ext->property.count);
7200 * mono_class_get_property_default_value:
7202 * Return the default value of the field as a pointer into the metadata blob.
7205 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7208 guint32 constant_cols [MONO_CONSTANT_SIZE];
7209 MonoClass *klass = property->parent;
7211 g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7213 * We don't cache here because it is not used by C# so it's quite rare, but
7214 * we still do the lookup in klass->ext because that is where the data
7215 * is stored for dynamic assemblies.
7218 if (image_is_dynamic (klass->image)) {
7219 int prop_index = mono_property_get_index (property);
7220 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7221 *def_type = klass->ext->prop_def_values [prop_index].def_type;
7222 return klass->ext->prop_def_values [prop_index].data;
7226 cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7230 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7231 *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7232 return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7236 mono_class_get_event_token (MonoEvent *event)
7238 MonoClass *klass = event->parent;
7243 for (i = 0; i < klass->ext->event.count; ++i) {
7244 if (&klass->ext->events [i] == event)
7245 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7248 klass = klass->parent;
7251 g_assert_not_reached ();
7256 * mono_class_get_property_from_name:
7258 * @name: name of the property to lookup in the specified class
7260 * Use this method to lookup a property in a class
7261 * Returns: the MonoProperty with the given name, or NULL if the property
7262 * does not exist on the @klass.
7265 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7269 gpointer iter = NULL;
7270 while ((p = mono_class_get_properties (klass, &iter))) {
7271 if (! strcmp (name, p->name))
7274 klass = klass->parent;
7280 * mono_class_get_property_token:
7281 * @prop: MonoProperty to query
7283 * Returns: The ECMA token for the specified property.
7286 mono_class_get_property_token (MonoProperty *prop)
7288 MonoClass *klass = prop->parent;
7292 gpointer iter = NULL;
7293 while ((p = mono_class_get_properties (klass, &iter))) {
7294 if (&klass->ext->properties [i] == prop)
7295 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7299 klass = klass->parent;
7302 g_assert_not_reached ();
7307 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7309 const char *name, *nspace;
7310 if (image_is_dynamic (image))
7311 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7313 switch (type_token & 0xff000000){
7314 case MONO_TOKEN_TYPE_DEF: {
7315 guint32 cols [MONO_TYPEDEF_SIZE];
7316 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7317 guint tidx = mono_metadata_token_index (type_token);
7319 if (tidx > tt->rows)
7320 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7322 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7323 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7324 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7325 if (strlen (nspace) == 0)
7326 return g_strdup_printf ("%s", name);
7328 return g_strdup_printf ("%s.%s", nspace, name);
7331 case MONO_TOKEN_TYPE_REF: {
7333 guint32 cols [MONO_TYPEREF_SIZE];
7334 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7335 guint tidx = mono_metadata_token_index (type_token);
7338 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7340 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7341 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7342 mono_error_cleanup (&error);
7346 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7347 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7348 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7349 if (strlen (nspace) == 0)
7350 return g_strdup_printf ("%s", name);
7352 return g_strdup_printf ("%s.%s", nspace, name);
7355 case MONO_TOKEN_TYPE_SPEC:
7356 return g_strdup_printf ("Typespec 0x%08x", type_token);
7358 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7363 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7365 if (image_is_dynamic (image))
7366 return g_strdup_printf ("DynamicAssembly %s", image->name);
7368 switch (type_token & 0xff000000){
7369 case MONO_TOKEN_TYPE_DEF:
7370 if (image->assembly)
7371 return mono_stringify_assembly_name (&image->assembly->aname);
7372 else if (image->assembly_name)
7373 return g_strdup (image->assembly_name);
7374 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7375 case MONO_TOKEN_TYPE_REF: {
7377 MonoAssemblyName aname;
7378 guint32 cols [MONO_TYPEREF_SIZE];
7379 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
7380 guint32 idx = mono_metadata_token_index (type_token);
7383 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7385 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7386 char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7387 mono_error_cleanup (&error);
7390 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7392 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7393 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7394 case MONO_RESOLUTION_SCOPE_MODULE:
7396 return g_strdup ("");
7397 case MONO_RESOLUTION_SCOPE_MODULEREF:
7399 return g_strdup ("");
7400 case MONO_RESOLUTION_SCOPE_TYPEREF:
7402 return g_strdup ("");
7403 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7404 mono_assembly_get_assemblyref (image, idx - 1, &aname);
7405 return mono_stringify_assembly_name (&aname);
7407 g_assert_not_reached ();
7411 case MONO_TOKEN_TYPE_SPEC:
7413 return g_strdup ("");
7415 g_assert_not_reached ();
7422 * mono_class_get_full:
7423 * @image: the image where the class resides
7424 * @type_token: the token for the class
7425 * @context: the generic context used to evaluate generic instantiations in
7426 * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7428 * Returns: The MonoClass that represents @type_token in @image
7431 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7435 klass = mono_class_get_checked (image, type_token, &error);
7437 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7438 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7440 g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7446 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7450 mono_error_init (error);
7451 klass = mono_class_get_checked (image, type_token, error);
7453 if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7454 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7459 * mono_class_get_checked:
7460 * @image: the image where the class resides
7461 * @type_token: the token for the class
7462 * @error: error object to return any error
7464 * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7467 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7469 MonoClass *klass = NULL;
7471 mono_error_init (error);
7473 if (image_is_dynamic (image)) {
7474 int table = mono_metadata_token_table (type_token);
7476 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7477 mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7480 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL); /*FIXME proper error handling*/
7484 switch (type_token & 0xff000000){
7485 case MONO_TOKEN_TYPE_DEF:
7486 klass = mono_class_create_from_typedef (image, type_token, error);
7488 case MONO_TOKEN_TYPE_REF:
7489 klass = mono_class_from_typeref_checked (image, type_token, error);
7491 case MONO_TOKEN_TYPE_SPEC:
7492 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7495 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7499 /* Generic case, should be avoided for when a better error is possible. */
7500 if (!klass && mono_error_ok (error)) {
7501 char *name = mono_class_name_from_token (image, type_token);
7502 char *assembly = mono_assembly_name_from_token (image, type_token);
7503 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7511 * mono_type_get_checked:
7512 * @image: the image where the type resides
7513 * @type_token: the token for the type
7514 * @context: the generic context used to evaluate generic instantiations in
7515 * @error: Error handling context
7517 * This functions exists to fullfill the fact that sometimes it's desirable to have access to the
7519 * Returns: The MonoType that represents @type_token in @image
7522 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7524 MonoType *type = NULL;
7525 gboolean inflated = FALSE;
7527 mono_error_init (error);
7529 //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7530 if (image_is_dynamic (image))
7531 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7533 if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7534 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7537 mono_loader_assert_no_error ();
7542 return mono_class_get_type (klass);
7545 type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7548 mono_loader_assert_no_error ();
7553 MonoType *tmp = type;
7554 type = mono_class_get_type (mono_class_from_mono_type (type));
7555 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7556 * A MonoClass::byval_arg of a generic type definion has type CLASS.
7557 * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7559 * The long term solution is to chaise this places and make then set MonoType::type correctly.
7561 if (type->type != tmp->type)
7564 mono_metadata_free_type (tmp);
7571 * @image: image where the class token will be looked up.
7572 * @type_token: a type token from the image
7574 * Returns the MonoClass with the given @type_token on the @image
7577 mono_class_get (MonoImage *image, guint32 type_token)
7579 return mono_class_get_full (image, type_token, NULL);
7583 * mono_image_init_name_cache:
7585 * Initializes the class name cache stored in image->name_cache.
7587 * LOCKING: Acquires the corresponding image lock.
7590 mono_image_init_name_cache (MonoImage *image)
7592 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7593 guint32 cols [MONO_TYPEDEF_SIZE];
7596 guint32 i, visib, nspace_index;
7597 GHashTable *name_cache2, *nspace_table, *the_name_cache;
7599 if (image->name_cache)
7602 the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7604 if (image_is_dynamic (image)) {
7605 mono_image_lock (image);
7606 if (image->name_cache) {
7607 /* Somebody initialized it before us */
7608 g_hash_table_destroy (the_name_cache);
7610 mono_atomic_store_release (&image->name_cache, the_name_cache);
7612 mono_image_unlock (image);
7616 /* Temporary hash table to avoid lookups in the nspace_table */
7617 name_cache2 = g_hash_table_new (NULL, NULL);
7619 for (i = 1; i <= t->rows; ++i) {
7620 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7621 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7623 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7624 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7626 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7628 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7629 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7631 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7632 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7633 if (!nspace_table) {
7634 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7635 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7636 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7639 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7642 /* Load type names from EXPORTEDTYPES table */
7644 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7645 guint32 cols [MONO_EXP_TYPE_SIZE];
7648 for (i = 0; i < t->rows; ++i) {
7649 mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7651 guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7652 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7656 name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7657 nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7659 nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7660 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7661 if (!nspace_table) {
7662 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7663 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7664 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7667 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7671 g_hash_table_destroy (name_cache2);
7673 mono_image_lock (image);
7674 if (image->name_cache) {
7675 /* Somebody initialized it before us */
7676 g_hash_table_destroy (the_name_cache);
7678 mono_atomic_store_release (&image->name_cache, the_name_cache);
7680 mono_image_unlock (image);
7683 /*FIXME Only dynamic assemblies should allow this operation.*/
7685 mono_image_add_to_name_cache (MonoImage *image, const char *nspace,
7686 const char *name, guint32 index)
7688 GHashTable *nspace_table;
7689 GHashTable *name_cache;
7692 mono_image_init_name_cache (image);
7693 mono_image_lock (image);
7695 name_cache = image->name_cache;
7696 if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7697 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7698 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7701 if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7702 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7704 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7706 mono_image_unlock (image);
7715 find_nocase (gpointer key, gpointer value, gpointer user_data)
7717 char *name = (char*)key;
7718 FindUserData *data = (FindUserData*)user_data;
7720 if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7721 data->value = value;
7725 * mono_class_from_name_case:
7726 * @image: The MonoImage where the type is looked up in
7727 * @name_space: the type namespace
7728 * @name: the type short name.
7729 * @deprecated: use the mono_class_from_name_case_checked variant instead.
7731 * Obtains a MonoClass with a given namespace and a given name which
7732 * is located in the given MonoImage. The namespace and name
7733 * lookups are case insensitive.
7736 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7739 MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7740 g_assert (!mono_error_ok (&error));
7745 * mono_class_from_name_case:
7746 * @image: The MonoImage where the type is looked up in
7747 * @name_space: the type namespace
7748 * @name: the type short name.
7751 * Obtains a MonoClass with a given namespace and a given name which
7752 * is located in the given MonoImage. The namespace and name
7753 * lookups are case insensitive.
7755 * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7756 * was not found. The @error object will contain information about the problem
7760 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7762 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEDEF];
7763 guint32 cols [MONO_TYPEDEF_SIZE];
7768 mono_error_init (error);
7770 if (image_is_dynamic (image)) {
7772 FindUserData user_data;
7774 mono_image_init_name_cache (image);
7775 mono_image_lock (image);
7777 user_data.key = name_space;
7778 user_data.value = NULL;
7779 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7781 if (user_data.value) {
7782 GHashTable *nspace_table = (GHashTable*)user_data.value;
7784 user_data.key = name;
7785 user_data.value = NULL;
7787 g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7789 if (user_data.value)
7790 token = GPOINTER_TO_UINT (user_data.value);
7793 mono_image_unlock (image);
7796 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7802 /* add a cache if needed */
7803 for (i = 1; i <= t->rows; ++i) {
7804 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7805 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7807 * Nested types are accessed from the nesting name. We use the fact that nested types use different visibility flags
7808 * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7810 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7812 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7813 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7814 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7815 return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7821 return_nested_in (MonoClass *klass, char *nested)
7824 char *s = strchr (nested, '/');
7825 gpointer iter = NULL;
7832 while ((found = mono_class_get_nested_types (klass, &iter))) {
7833 if (strcmp (found->name, nested) == 0) {
7835 return return_nested_in (found, s);
7843 search_modules (MonoImage *image, const char *name_space, const char *name)
7845 MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7846 MonoImage *file_image;
7851 * The EXPORTEDTYPES table only contains public types, so have to search the
7853 * Note: image->modules contains the contents of the MODULEREF table, while
7854 * the real module list is in the FILE table.
7856 for (i = 0; i < file_table->rows; i++) {
7857 guint32 cols [MONO_FILE_SIZE];
7858 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7859 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7862 file_image = mono_image_load_file_for_image (image, i + 1);
7864 klass = mono_class_from_name (file_image, name_space, name);
7874 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7876 GHashTable *nspace_table;
7877 MonoImage *loaded_image;
7884 mono_error_init (error);
7886 // Checking visited images avoids stack overflows when cyclic references exist.
7887 if (g_hash_table_lookup (visited_images, image))
7890 g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7892 if ((nested = strchr (name, '/'))) {
7893 int pos = nested - name;
7894 int len = strlen (name);
7897 memcpy (buf, name, len + 1);
7899 nested = buf + pos + 1;
7903 /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7904 if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7905 gboolean res = get_class_from_name (image, name_space, name, &klass);
7908 klass = search_modules (image, name_space, name);
7910 return klass ? return_nested_in (klass, nested) : NULL;
7916 mono_image_init_name_cache (image);
7917 mono_image_lock (image);
7919 nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7922 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7924 mono_image_unlock (image);
7926 if (!token && image_is_dynamic (image) && image->modules) {
7927 /* Search modules as well */
7928 for (i = 0; i < image->module_count; ++i) {
7929 MonoImage *module = image->modules [i];
7931 klass = mono_class_from_name (module, name_space, name);
7938 klass = search_modules (image, name_space, name);
7946 if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7947 MonoTableInfo *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7948 guint32 cols [MONO_EXP_TYPE_SIZE];
7951 idx = mono_metadata_token_index (token);
7953 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7955 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7956 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7957 loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7960 klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7962 return klass ? return_nested_in (klass, nested) : NULL;
7964 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7965 guint32 assembly_idx;
7967 assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7969 mono_assembly_load_reference (image, assembly_idx - 1);
7970 g_assert (image->references [assembly_idx - 1]);
7971 if (image->references [assembly_idx - 1] == (gpointer)-1)
7973 klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7975 return return_nested_in (klass, nested);
7978 g_assert_not_reached ();
7982 token = MONO_TOKEN_TYPE_DEF | token;
7984 klass = mono_class_get_checked (image, token, error);
7986 return return_nested_in (klass, nested);
7991 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7994 GHashTable *visited_images;
7996 visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7998 klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
8000 g_hash_table_destroy (visited_images);
8006 * mono_class_from_name:
8007 * @image: The MonoImage where the type is looked up in
8008 * @name_space: the type namespace
8009 * @name: the type short name.
8011 * Obtains a MonoClass with a given namespace and a given name which
8012 * is located in the given MonoImage.
8014 * To reference nested classes, use the "/" character as a separator.
8015 * For example use "Foo/Bar" to reference the class Bar that is nested
8016 * inside Foo, like this: "class Foo { class Bar {} }".
8019 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8024 klass = mono_class_from_name_checked (image, name_space, name, &error);
8025 if (!mono_error_ok (&error)) {
8026 mono_loader_set_error_from_mono_error (&error);
8027 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8033 * mono_class_is_subclass_of:
8034 * @klass: class to probe if it is a subclass of another one
8035 * @klassc: the class we suspect is the base class
8036 * @check_interfaces: whether we should perform interface checks
8038 * This method determines whether @klass is a subclass of @klassc.
8040 * If the @check_interfaces flag is set, then if @klassc is an interface
8041 * this method return TRUE if the @klass implements the interface or
8042 * if @klass is an interface, if one of its base classes is @klass.
8044 * If @check_interfaces is false then, then if @klass is not an interface
8045 * then it returns TRUE if the @klass is a subclass of @klassc.
8047 * if @klass is an interface and @klassc is System.Object, then this function
8052 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc,
8053 gboolean check_interfaces)
8055 /*FIXME test for interfaces with variant generic arguments*/
8057 if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8058 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8060 } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8063 for (i = 0; i < klass->interface_count; i ++) {
8064 MonoClass *ic = klass->interfaces [i];
8069 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8074 * MS.NET thinks interfaces are a subclass of Object, so we think it as
8077 if (klassc == mono_defaults.object_class)
8084 mono_type_is_generic_argument (MonoType *type)
8086 return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8090 mono_class_has_variant_generic_params (MonoClass *klass)
8093 MonoGenericContainer *container;
8095 if (!klass->generic_class)
8098 container = klass->generic_class->container_class->generic_container;
8100 for (i = 0; i < container->type_argc; ++i)
8101 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8108 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8110 if (target == candidate)
8113 if (check_for_reference_conv &&
8114 mono_type_is_generic_argument (&target->byval_arg) &&
8115 mono_type_is_generic_argument (&candidate->byval_arg)) {
8116 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8117 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8119 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8122 if (!mono_class_is_assignable_from (target, candidate))
8128 * @container the generic container from the GTD
8129 * @klass: the class to be assigned to
8130 * @oklass: the source class
8132 * Both @klass and @oklass must be instances of the same generic interface.
8134 * Returns: TRUE if @klass can be assigned to a @klass variable
8137 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8140 MonoType **klass_argv, **oklass_argv;
8141 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8142 MonoGenericContainer *container = klass_gtd->generic_container;
8144 if (klass == oklass)
8147 /*Viable candidates are instances of the same generic interface*/
8148 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8151 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8152 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8154 for (j = 0; j < container->type_argc; ++j) {
8155 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8156 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8158 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8162 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8163 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8165 if (param1_class != param2_class) {
8166 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8167 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8169 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8170 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8180 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8182 MonoGenericParam *gparam, *ogparam;
8183 MonoGenericParamInfo *tinfo, *cinfo;
8184 MonoClass **candidate_class;
8185 gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8188 if (target == candidate)
8190 if (target->byval_arg.type != candidate->byval_arg.type)
8193 gparam = target->byval_arg.data.generic_param;
8194 ogparam = candidate->byval_arg.data.generic_param;
8195 tinfo = mono_generic_param_info (gparam);
8196 cinfo = mono_generic_param_info (ogparam);
8198 class_constraint_satisfied = FALSE;
8199 valuetype_constraint_satisfied = FALSE;
8201 /*candidate must have a super set of target's special constraints*/
8202 tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8203 cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8205 if (cinfo->constraints) {
8206 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8207 MonoClass *cc = *candidate_class;
8209 if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8210 class_constraint_satisfied = TRUE;
8211 else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8212 valuetype_constraint_satisfied = TRUE;
8215 class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8216 valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8218 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8220 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8222 if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8223 valuetype_constraint_satisfied)) {
8228 /*candidate type constraints must be a superset of target's*/
8229 if (tinfo->constraints) {
8230 MonoClass **target_class;
8231 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8232 MonoClass *tc = *target_class;
8235 * A constraint from @target might inflate into @candidate itself and in that case we don't need
8236 * check it's constraints since it satisfy the constraint by itself.
8238 if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8241 if (!cinfo->constraints)
8244 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8245 MonoClass *cc = *candidate_class;
8247 if (mono_class_is_assignable_from (tc, cc))
8251 * This happens when we have the following:
8253 * Bar<K> where K : IFace
8254 * Foo<T, U> where T : U where U : IFace
8256 * Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8259 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8260 if (mono_gparam_is_assignable_from (target, cc))
8264 if (!*candidate_class)
8269 /*candidate itself must have a constraint that satisfy target*/
8270 if (cinfo->constraints) {
8271 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8272 MonoClass *cc = *candidate_class;
8273 if (mono_class_is_assignable_from (target, cc))
8281 * mono_class_is_assignable_from:
8282 * @klass: the class to be assigned to
8283 * @oklass: the source class
8285 * Returns: TRUE if an instance of object oklass can be assigned to an
8286 * instance of object @klass
8289 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8291 /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8293 mono_class_init (klass);
8295 if (!oklass->inited)
8296 mono_class_init (oklass);
8298 if (klass->exception_type || oklass->exception_type)
8301 if (mono_type_is_generic_argument (&klass->byval_arg)) {
8302 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8304 return mono_gparam_is_assignable_from (klass, oklass);
8307 if (MONO_CLASS_IS_INTERFACE (klass)) {
8308 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8309 MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8310 MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8314 for (i = 0; constraints [i]; ++i) {
8315 if (mono_class_is_assignable_from (klass, constraints [i]))
8323 /* interface_offsets might not be set for dynamic classes */
8324 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8326 * oklass might be a generic type parameter but they have
8327 * interface_offsets set.
8329 return mono_reflection_call_is_assignable_to (oklass, klass);
8330 if (!oklass->interface_bitmap)
8331 /* Happens with generic instances of not-yet created dynamic types */
8333 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8336 if (mono_class_has_variant_generic_params (klass)) {
8339 mono_class_setup_interfaces (oklass, &error);
8340 if (!mono_error_ok (&error)) {
8341 mono_error_cleanup (&error);
8345 /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8346 for (i = 0; i < oklass->interface_offsets_count; ++i) {
8347 MonoClass *iface = oklass->interfaces_packed [i];
8349 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8354 } else if (klass->delegate) {
8355 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8357 }else if (klass->rank) {
8358 MonoClass *eclass, *eoclass;
8360 if (oklass->rank != klass->rank)
8363 /* vectors vs. one dimensional arrays */
8364 if (oklass->byval_arg.type != klass->byval_arg.type)
8367 eclass = klass->cast_class;
8368 eoclass = oklass->cast_class;
8371 * a is b does not imply a[] is b[] when a is a valuetype, and
8372 * b is a reference type.
8375 if (eoclass->valuetype) {
8376 if ((eclass == mono_defaults.enum_class) ||
8377 (eclass == mono_defaults.enum_class->parent) ||
8378 (eclass == mono_defaults.object_class))
8382 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8383 } else if (mono_class_is_nullable (klass)) {
8384 if (mono_class_is_nullable (oklass))
8385 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8387 return mono_class_is_assignable_from (klass->cast_class, oklass);
8388 } else if (klass == mono_defaults.object_class)
8391 return mono_class_has_parent (oklass, klass);
8394 /*Check if @oklass is variant compatible with @klass.*/
8396 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8399 MonoType **klass_argv, **oklass_argv;
8400 MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8401 MonoGenericContainer *container = klass_gtd->generic_container;
8403 /*Viable candidates are instances of the same generic interface*/
8404 if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8407 klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8408 oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8410 for (j = 0; j < container->type_argc; ++j) {
8411 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8412 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8414 if (param1_class->valuetype != param2_class->valuetype)
8418 * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8419 * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8421 if (param1_class != param2_class) {
8422 if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8423 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8425 } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8426 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8434 /*Check if @candidate implements the interface @target*/
8436 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8440 gboolean is_variant = mono_class_has_variant_generic_params (target);
8442 if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8443 if (mono_class_is_variant_compatible_slow (target, candidate))
8448 if (candidate == target)
8451 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8452 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8453 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8455 if (tb && tb->interfaces) {
8456 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8457 MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8458 MonoClass *iface_class;
8460 /* we can't realize the type here since it can do pretty much anything. */
8463 iface_class = mono_class_from_mono_type (iface->type);
8464 if (iface_class == target)
8466 if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8468 if (mono_class_implement_interface_slow (target, iface_class))
8473 /*setup_interfaces don't mono_class_init anything*/
8474 /*FIXME this doesn't handle primitive type arrays.
8475 ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8476 A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8478 mono_class_setup_interfaces (candidate, &error);
8479 if (!mono_error_ok (&error)) {
8480 mono_error_cleanup (&error);
8484 for (i = 0; i < candidate->interface_count; ++i) {
8485 if (candidate->interfaces [i] == target)
8488 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8491 if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8495 candidate = candidate->parent;
8496 } while (candidate);
8502 * Check if @oklass can be assigned to @klass.
8503 * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8506 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8508 if (candidate == target)
8510 if (target == mono_defaults.object_class)
8513 if (mono_class_has_parent (candidate, target))
8516 /*If target is not an interface there is no need to check them.*/
8517 if (MONO_CLASS_IS_INTERFACE (target))
8518 return mono_class_implement_interface_slow (target, candidate);
8520 if (target->delegate && mono_class_has_variant_generic_params (target))
8521 return mono_class_is_variant_compatible (target, candidate, FALSE);
8524 MonoClass *eclass, *eoclass;
8526 if (target->rank != candidate->rank)
8529 /* vectors vs. one dimensional arrays */
8530 if (target->byval_arg.type != candidate->byval_arg.type)
8533 eclass = target->cast_class;
8534 eoclass = candidate->cast_class;
8537 * a is b does not imply a[] is b[] when a is a valuetype, and
8538 * b is a reference type.
8541 if (eoclass->valuetype) {
8542 if ((eclass == mono_defaults.enum_class) ||
8543 (eclass == mono_defaults.enum_class->parent) ||
8544 (eclass == mono_defaults.object_class))
8548 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8550 /*FIXME properly handle nullables */
8551 /*FIXME properly handle (M)VAR */
8556 * mono_class_get_cctor:
8557 * @klass: A MonoClass pointer
8559 * Returns: The static constructor of @klass if it exists, NULL otherwise.
8562 mono_class_get_cctor (MonoClass *klass)
8564 MonoCachedClassInfo cached_info;
8566 if (image_is_dynamic (klass->image)) {
8568 * has_cctor is not set for these classes because mono_class_init () is
8571 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8574 if (!klass->has_cctor)
8577 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8579 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8580 if (!mono_error_ok (&error))
8581 g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8585 if (klass->generic_class && !klass->methods)
8586 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8588 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8592 * mono_class_get_finalizer:
8593 * @klass: The MonoClass pointer
8595 * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8598 mono_class_get_finalizer (MonoClass *klass)
8600 MonoCachedClassInfo cached_info;
8603 mono_class_init (klass);
8604 if (!mono_class_has_finalizer (klass))
8607 if (mono_class_get_cached_class_info (klass, &cached_info)) {
8609 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8610 if (!mono_error_ok (&error))
8611 g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8614 mono_class_setup_vtable (klass);
8615 return klass->vtable [finalize_slot];
8620 * mono_class_needs_cctor_run:
8621 * @klass: the MonoClass pointer
8622 * @caller: a MonoMethod describing the caller
8624 * Determines whenever the class has a static constructor and whenever it
8625 * needs to be called when executing CALLER.
8628 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8632 method = mono_class_get_cctor (klass);
8634 return (method == caller) ? FALSE : TRUE;
8640 * mono_class_array_element_size:
8643 * Returns: The number of bytes an element of type @klass
8644 * uses when stored into an array.
8647 mono_class_array_element_size (MonoClass *klass)
8649 MonoType *type = &klass->byval_arg;
8652 switch (type->type) {
8655 case MONO_TYPE_BOOLEAN:
8659 case MONO_TYPE_CHAR:
8668 case MONO_TYPE_CLASS:
8669 case MONO_TYPE_STRING:
8670 case MONO_TYPE_OBJECT:
8671 case MONO_TYPE_SZARRAY:
8672 case MONO_TYPE_ARRAY:
8673 return sizeof (gpointer);
8678 case MONO_TYPE_VALUETYPE:
8679 if (type->data.klass->enumtype) {
8680 type = mono_class_enum_basetype (type->data.klass);
8681 klass = klass->element_class;
8684 return mono_class_instance_size (klass) - sizeof (MonoObject);
8685 case MONO_TYPE_GENERICINST:
8686 type = &type->data.generic_class->container_class->byval_arg;
8689 case MONO_TYPE_MVAR: {
8692 return mono_type_size (type, &align);
8694 case MONO_TYPE_VOID:
8698 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8704 * mono_array_element_size:
8705 * @ac: pointer to a #MonoArrayClass
8707 * Returns: The size of single array element.
8710 mono_array_element_size (MonoClass *ac)
8712 g_assert (ac->rank);
8713 return ac->sizes.element_size;
8717 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8718 MonoGenericContext *context)
8721 gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8722 g_assert (mono_error_ok (&error));
8727 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8728 MonoGenericContext *context, MonoError *error)
8730 mono_error_init (error);
8732 if (image_is_dynamic (image)) {
8733 MonoClass *tmp_handle_class;
8734 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8736 g_assert (tmp_handle_class);
8738 *handle_class = tmp_handle_class;
8740 if (tmp_handle_class == mono_defaults.typehandle_class)
8741 return &((MonoClass*)obj)->byval_arg;
8746 switch (token & 0xff000000) {
8747 case MONO_TOKEN_TYPE_DEF:
8748 case MONO_TOKEN_TYPE_REF:
8749 case MONO_TOKEN_TYPE_SPEC: {
8752 *handle_class = mono_defaults.typehandle_class;
8753 type = mono_type_get_checked (image, token, context, error);
8757 mono_class_init (mono_class_from_mono_type (type));
8758 /* We return a MonoType* as handle */
8761 case MONO_TOKEN_FIELD_DEF: {
8763 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8765 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8769 *handle_class = mono_defaults.fieldhandle_class;
8770 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8774 mono_class_init (klass);
8775 return mono_class_get_field (klass, token);
8777 case MONO_TOKEN_METHOD_DEF:
8778 case MONO_TOKEN_METHOD_SPEC: {
8780 meth = mono_get_method_checked (image, token, NULL, context, error);
8782 *handle_class = mono_defaults.methodhandle_class;
8788 case MONO_TOKEN_MEMBER_REF: {
8789 guint32 cols [MONO_MEMBERREF_SIZE];
8791 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8792 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8793 mono_metadata_decode_blob_size (sig, &sig);
8794 if (*sig == 0x6) { /* it's a field */
8796 MonoClassField *field;
8797 field = mono_field_from_token_checked (image, token, &klass, context, error);
8799 *handle_class = mono_defaults.fieldhandle_class;
8803 meth = mono_get_method_checked (image, token, NULL, context, error);
8805 *handle_class = mono_defaults.methodhandle_class;
8810 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8816 * This function might need to call runtime functions so it can't be part
8817 * of the metadata library.
8819 static MonoLookupDynamicToken lookup_dynamic = NULL;
8822 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8824 lookup_dynamic = func;
8828 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8830 MonoClass *handle_class;
8832 return lookup_dynamic (image, token, TRUE, &handle_class, context);
8836 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8838 return lookup_dynamic (image, token, valid_token, handle_class, context);
8841 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8844 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8846 get_cached_class_info = func;
8850 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8852 if (!get_cached_class_info)
8855 return get_cached_class_info (klass, res);
8859 mono_install_get_class_from_name (MonoGetClassFromName func)
8861 get_class_from_name = func;
8865 * mono_class_get_image:
8867 * Use this method to get the `MonoImage*` where this class came from.
8869 * Returns: The image where this class is defined.
8872 mono_class_get_image (MonoClass *klass)
8874 return klass->image;
8878 * mono_class_get_element_class:
8879 * @klass: the MonoClass to act on
8881 * Use this function to get the element class of an array.
8883 * Returns: The element class of an array.
8886 mono_class_get_element_class (MonoClass *klass)
8888 return klass->element_class;
8892 * mono_class_is_valuetype:
8893 * @klass: the MonoClass to act on
8895 * Use this method to determine if the provided `MonoClass*` represents a value type,
8896 * or a reference type.
8898 * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8901 mono_class_is_valuetype (MonoClass *klass)
8903 return klass->valuetype;
8907 * mono_class_is_enum:
8908 * @klass: the MonoClass to act on
8910 * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8912 * Returns: TRUE if the MonoClass represents an enumeration.
8915 mono_class_is_enum (MonoClass *klass)
8917 return klass->enumtype;
8921 * mono_class_enum_basetype:
8922 * @klass: the MonoClass to act on
8924 * Use this function to get the underlying type for an enumeration value.
8926 * Returns: The underlying type representation for an enumeration.
8929 mono_class_enum_basetype (MonoClass *klass)
8931 if (klass->element_class == klass)
8932 /* SRE or broken types */
8935 return &klass->element_class->byval_arg;
8939 * mono_class_get_parent
8940 * @klass: the MonoClass to act on
8942 * Returns: The parent class for this class.
8945 mono_class_get_parent (MonoClass *klass)
8947 return klass->parent;
8951 * mono_class_get_nesting_type:
8952 * @klass: the MonoClass to act on
8954 * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8956 * If the return is NULL, this indicates that this class is not nested.
8958 * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8961 mono_class_get_nesting_type (MonoClass *klass)
8963 return klass->nested_in;
8967 * mono_class_get_rank:
8968 * @klass: the MonoClass to act on
8970 * Returns: The rank for the array (the number of dimensions).
8973 mono_class_get_rank (MonoClass *klass)
8979 * mono_class_get_flags:
8980 * @klass: the MonoClass to act on
8982 * The type flags from the TypeDef table from the metadata.
8983 * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8986 * Returns: The flags from the TypeDef table.
8989 mono_class_get_flags (MonoClass *klass)
8991 return klass->flags;
8995 * mono_class_get_name
8996 * @klass: the MonoClass to act on
8998 * Returns: The name of the class.
9001 mono_class_get_name (MonoClass *klass)
9007 * mono_class_get_namespace:
9008 * @klass: the MonoClass to act on
9010 * Returns: The namespace of the class.
9013 mono_class_get_namespace (MonoClass *klass)
9015 return klass->name_space;
9019 * mono_class_get_type:
9020 * @klass: the MonoClass to act on
9022 * This method returns the internal Type representation for the class.
9024 * Returns: The MonoType from the class.
9027 mono_class_get_type (MonoClass *klass)
9029 return &klass->byval_arg;
9033 * mono_class_get_type_token:
9034 * @klass: the MonoClass to act on
9036 * This method returns type token for the class.
9038 * Returns: The type token for the class.
9041 mono_class_get_type_token (MonoClass *klass)
9043 return klass->type_token;
9047 * mono_class_get_byref_type:
9048 * @klass: the MonoClass to act on
9053 mono_class_get_byref_type (MonoClass *klass)
9055 return &klass->this_arg;
9059 * mono_class_num_fields:
9060 * @klass: the MonoClass to act on
9062 * Returns: The number of static and instance fields in the class.
9065 mono_class_num_fields (MonoClass *klass)
9067 return klass->field.count;
9071 * mono_class_num_methods:
9072 * @klass: the MonoClass to act on
9074 * Returns: The number of methods in the class.
9077 mono_class_num_methods (MonoClass *klass)
9079 return klass->method.count;
9083 * mono_class_num_properties
9084 * @klass: the MonoClass to act on
9086 * Returns: The number of properties in the class.
9089 mono_class_num_properties (MonoClass *klass)
9091 mono_class_setup_properties (klass);
9093 return klass->ext->property.count;
9097 * mono_class_num_events:
9098 * @klass: the MonoClass to act on
9100 * Returns: The number of events in the class.
9103 mono_class_num_events (MonoClass *klass)
9105 mono_class_setup_events (klass);
9107 return klass->ext->event.count;
9111 * mono_class_get_fields:
9112 * @klass: the MonoClass to act on
9114 * This routine is an iterator routine for retrieving the fields in a class.
9116 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9117 * iterate over all of the elements. When no more values are
9118 * available, the return value is NULL.
9120 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9123 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9125 MonoClassField* field;
9129 mono_class_setup_fields_locking (klass);
9130 if (klass->exception_type)
9132 /* start from the first */
9133 if (klass->field.count) {
9134 *iter = &klass->fields [0];
9135 return &klass->fields [0];
9141 field = (MonoClassField *)*iter;
9143 if (field < &klass->fields [klass->field.count]) {
9151 * mono_class_get_methods
9152 * @klass: the MonoClass to act on
9154 * This routine is an iterator routine for retrieving the fields in a class.
9156 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9157 * iterate over all of the elements. When no more values are
9158 * available, the return value is NULL.
9160 * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9163 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9165 MonoMethod** method;
9169 mono_class_setup_methods (klass);
9172 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9173 * FIXME we should better report this error to the caller
9175 if (!klass->methods)
9177 /* start from the first */
9178 if (klass->method.count) {
9179 *iter = &klass->methods [0];
9180 return klass->methods [0];
9186 method = (MonoMethod **)*iter;
9188 if (method < &klass->methods [klass->method.count]) {
9196 * mono_class_get_virtual_methods:
9198 * Iterate over the virtual methods of KLASS.
9200 * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9203 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9205 MonoMethod** method;
9208 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9210 mono_class_setup_methods (klass);
9212 * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9213 * FIXME we should better report this error to the caller
9215 if (!klass->methods)
9217 /* start from the first */
9218 method = &klass->methods [0];
9220 method = (MonoMethod **)*iter;
9223 while (method < &klass->methods [klass->method.count]) {
9224 if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9228 if (method < &klass->methods [klass->method.count]) {
9235 /* Search directly in metadata to avoid calling setup_methods () */
9236 MonoMethod *res = NULL;
9242 start_index = GPOINTER_TO_UINT (*iter);
9245 for (i = start_index; i < klass->method.count; ++i) {
9248 /* klass->method.first points into the methodptr table */
9249 flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9251 if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9255 if (i < klass->method.count) {
9257 res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9258 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9260 /* Add 1 here so the if (*iter) check fails */
9261 *iter = GUINT_TO_POINTER (i + 1);
9270 * mono_class_get_properties:
9271 * @klass: the MonoClass to act on
9273 * This routine is an iterator routine for retrieving the properties in a class.
9275 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9276 * iterate over all of the elements. When no more values are
9277 * available, the return value is NULL.
9279 * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9282 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9284 MonoProperty* property;
9288 mono_class_setup_properties (klass);
9289 /* start from the first */
9290 if (klass->ext->property.count) {
9291 *iter = &klass->ext->properties [0];
9292 return (MonoProperty *)*iter;
9298 property = (MonoProperty *)*iter;
9300 if (property < &klass->ext->properties [klass->ext->property.count]) {
9302 return (MonoProperty *)*iter;
9308 * mono_class_get_events:
9309 * @klass: the MonoClass to act on
9311 * This routine is an iterator routine for retrieving the properties in a class.
9313 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9314 * iterate over all of the elements. When no more values are
9315 * available, the return value is NULL.
9317 * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9320 mono_class_get_events (MonoClass* klass, gpointer *iter)
9326 mono_class_setup_events (klass);
9327 /* start from the first */
9328 if (klass->ext->event.count) {
9329 *iter = &klass->ext->events [0];
9330 return (MonoEvent *)*iter;
9336 event = (MonoEvent *)*iter;
9338 if (event < &klass->ext->events [klass->ext->event.count]) {
9340 return (MonoEvent *)*iter;
9346 * mono_class_get_interfaces
9347 * @klass: the MonoClass to act on
9349 * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9351 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9352 * iterate over all of the elements. When no more values are
9353 * available, the return value is NULL.
9355 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9358 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9366 mono_class_init (klass);
9367 if (!klass->interfaces_inited) {
9368 mono_class_setup_interfaces (klass, &error);
9369 if (!mono_error_ok (&error)) {
9370 mono_error_cleanup (&error);
9374 /* start from the first */
9375 if (klass->interface_count) {
9376 *iter = &klass->interfaces [0];
9377 return klass->interfaces [0];
9383 iface = (MonoClass **)*iter;
9385 if (iface < &klass->interfaces [klass->interface_count]) {
9393 setup_nested_types (MonoClass *klass)
9396 GList *classes, *nested_classes, *l;
9399 if (klass->nested_classes_inited)
9402 if (!klass->type_token)
9403 klass->nested_classes_inited = TRUE;
9405 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9409 guint32 cols [MONO_NESTED_CLASS_SIZE];
9410 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9411 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9412 if (!mono_error_ok (&error)) {
9413 /*FIXME don't swallow the error message*/
9414 mono_error_cleanup (&error);
9416 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9420 classes = g_list_prepend (classes, nclass);
9422 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9425 mono_class_alloc_ext (klass);
9427 nested_classes = NULL;
9428 for (l = classes; l; l = l->next)
9429 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9430 g_list_free (classes);
9432 mono_image_lock (klass->image);
9434 mono_memory_barrier ();
9435 if (!klass->nested_classes_inited) {
9436 klass->ext->nested_classes = nested_classes;
9437 mono_memory_barrier ();
9438 klass->nested_classes_inited = TRUE;
9441 mono_image_unlock (klass->image);
9445 * mono_class_get_nested_types
9446 * @klass: the MonoClass to act on
9448 * This routine is an iterator routine for retrieving the nested types of a class.
9449 * This works only if @klass is non-generic, or a generic type definition.
9451 * You must pass a gpointer that points to zero and is treated as an opaque handle to
9452 * iterate over all of the elements. When no more values are
9453 * available, the return value is NULL.
9455 * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9458 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9464 if (!klass->nested_classes_inited)
9465 setup_nested_types (klass);
9468 /* start from the first */
9469 if (klass->ext && klass->ext->nested_classes) {
9470 *iter = klass->ext->nested_classes;
9471 return (MonoClass *)klass->ext->nested_classes->data;
9473 /* no nested types */
9477 item = (GList *)*iter;
9481 return (MonoClass *)item->data;
9488 * mono_class_is_delegate
9489 * @klass: the MonoClass to act on
9491 * Returns: TRUE if the MonoClass represents a System.Delegate.
9494 mono_class_is_delegate (MonoClass *klass)
9496 return klass->delegate;
9500 * mono_class_implements_interface
9501 * @klass: The MonoClass to act on
9502 * @interface: The interface to check if @klass implements.
9504 * Returns: TRUE if @klass implements @interface.
9507 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9509 return mono_class_is_assignable_from (iface, klass);
9513 * mono_field_get_name:
9514 * @field: the MonoClassField to act on
9516 * Returns: The name of the field.
9519 mono_field_get_name (MonoClassField *field)
9525 * mono_field_get_type:
9526 * @field: the MonoClassField to act on
9528 * Returns: MonoType of the field.
9531 mono_field_get_type (MonoClassField *field)
9534 MonoType *type = mono_field_get_type_checked (field, &error);
9535 if (!mono_error_ok (&error)) {
9536 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9537 mono_error_cleanup (&error);
9544 * mono_field_get_type_checked:
9545 * @field: the MonoClassField to act on
9546 * @error: used to return any erro found while retrieving @field type
9548 * Returns: MonoType of the field.
9551 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9553 mono_error_init (error);
9555 mono_field_resolve_type (field, error);
9560 * mono_field_get_parent:
9561 * @field: the MonoClassField to act on
9563 * Returns: MonoClass where the field was defined.
9566 mono_field_get_parent (MonoClassField *field)
9568 return field->parent;
9572 * mono_field_get_flags;
9573 * @field: the MonoClassField to act on
9575 * The metadata flags for a field are encoded using the
9576 * FIELD_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9578 * Returns: The flags for the field.
9581 mono_field_get_flags (MonoClassField *field)
9584 return mono_field_resolve_flags (field);
9585 return field->type->attrs;
9589 * mono_field_get_offset:
9590 * @field: the MonoClassField to act on
9592 * Returns: The field offset.
9595 mono_field_get_offset (MonoClassField *field)
9597 return field->offset;
9601 mono_field_get_rva (MonoClassField *field)
9605 MonoClass *klass = field->parent;
9606 MonoFieldDefaultValue *field_def_values;
9608 g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9610 if (!klass->ext || !klass->ext->field_def_values) {
9611 mono_class_alloc_ext (klass);
9613 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9615 mono_image_lock (klass->image);
9616 if (!klass->ext->field_def_values)
9617 klass->ext->field_def_values = field_def_values;
9618 mono_image_unlock (klass->image);
9621 field_index = mono_field_get_index (field);
9623 if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9624 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9626 g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9627 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9630 return klass->ext->field_def_values [field_index].data;
9634 * mono_field_get_data:
9635 * @field: the MonoClassField to act on
9637 * Returns: A pointer to the metadata constant value or to the field
9638 * data if it has an RVA flag.
9641 mono_field_get_data (MonoClassField *field)
9643 if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9644 MonoTypeEnum def_type;
9646 return mono_class_get_field_default_value (field, &def_type);
9647 } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9648 return mono_field_get_rva (field);
9655 * mono_property_get_name:
9656 * @prop: the MonoProperty to act on
9658 * Returns: The name of the property
9661 mono_property_get_name (MonoProperty *prop)
9667 * mono_property_get_set_method
9668 * @prop: the MonoProperty to act on.
9670 * Returns: The setter method of the property (A MonoMethod)
9673 mono_property_get_set_method (MonoProperty *prop)
9679 * mono_property_get_get_method
9680 * @prop: the MonoProperty to act on.
9682 * Returns: The setter method of the property (A MonoMethod)
9685 mono_property_get_get_method (MonoProperty *prop)
9691 * mono_property_get_parent:
9692 * @prop: the MonoProperty to act on.
9694 * Returns: The MonoClass where the property was defined.
9697 mono_property_get_parent (MonoProperty *prop)
9699 return prop->parent;
9703 * mono_property_get_flags:
9704 * @prop: the MonoProperty to act on.
9706 * The metadata flags for a property are encoded using the
9707 * PROPERTY_ATTRIBUTE_* constants. See the tabledefs.h file for details.
9709 * Returns: The flags for the property.
9712 mono_property_get_flags (MonoProperty *prop)
9718 * mono_event_get_name:
9719 * @event: the MonoEvent to act on
9721 * Returns: The name of the event.
9724 mono_event_get_name (MonoEvent *event)
9730 * mono_event_get_add_method:
9731 * @event: The MonoEvent to act on.
9733 * Returns: The @add' method for the event (a MonoMethod).
9736 mono_event_get_add_method (MonoEvent *event)
9742 * mono_event_get_remove_method:
9743 * @event: The MonoEvent to act on.
9745 * Returns: The @remove method for the event (a MonoMethod).
9748 mono_event_get_remove_method (MonoEvent *event)
9750 return event->remove;
9754 * mono_event_get_raise_method:
9755 * @event: The MonoEvent to act on.
9757 * Returns: The @raise method for the event (a MonoMethod).
9760 mono_event_get_raise_method (MonoEvent *event)
9762 return event->raise;
9766 * mono_event_get_parent:
9767 * @event: the MonoEvent to act on.
9769 * Returns: The MonoClass where the event is defined.
9772 mono_event_get_parent (MonoEvent *event)
9774 return event->parent;
9778 * mono_event_get_flags
9779 * @event: the MonoEvent to act on.
9781 * The metadata flags for an event are encoded using the
9782 * EVENT_* constants. See the tabledefs.h file for details.
9784 * Returns: The flags for the event.
9787 mono_event_get_flags (MonoEvent *event)
9789 return event->attrs;
9793 * mono_class_get_method_from_name:
9794 * @klass: where to look for the method
9795 * @name: name of the method
9796 * @param_count: number of parameters. -1 for any number.
9798 * Obtains a MonoMethod with a given name and number of parameters.
9799 * It only works if there are no multiple signatures for any given method name.
9802 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9804 return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9808 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9810 MonoMethod *res = NULL;
9813 /* Search directly in the metadata to avoid calling setup_methods () */
9814 for (i = 0; i < klass->method.count; ++i) {
9816 guint32 cols [MONO_METHOD_SIZE];
9818 MonoMethodSignature *sig;
9820 /* klass->method.first points into the methodptr table */
9821 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9823 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9824 method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9826 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9829 if (param_count == -1) {
9833 sig = mono_method_signature_checked (method, &error);
9835 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9838 if (sig->param_count == param_count) {
9849 * mono_class_get_method_from_name_flags:
9850 * @klass: where to look for the method
9851 * @name_space: name of the method
9852 * @param_count: number of parameters. -1 for any number.
9853 * @flags: flags which must be set in the method
9855 * Obtains a MonoMethod with a given name and number of parameters.
9856 * It only works if there are no multiple signatures for any given method name.
9859 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9861 MonoMethod *res = NULL;
9864 mono_class_init (klass);
9866 if (klass->generic_class && !klass->methods) {
9867 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9870 res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9871 if (!mono_error_ok (&error))
9872 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9877 if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9878 mono_class_setup_methods (klass);
9880 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9881 See mono/tests/array_load_exception.il
9882 FIXME we should better report this error to the caller
9884 if (!klass->methods)
9886 for (i = 0; i < klass->method.count; ++i) {
9887 MonoMethod *method = klass->methods [i];
9889 if (method->name[0] == name [0] &&
9890 !strcmp (name, method->name) &&
9891 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9892 ((method->flags & flags) == flags)) {
9899 res = find_method_in_metadata (klass, name, param_count, flags);
9906 * mono_class_set_failure:
9907 * @klass: class in which the failure was detected
9908 * @ex_type: the kind of exception/error to be thrown (later)
9909 * @ex_data: exception data (specific to each type of exception/error)
9911 * Keep a detected failure informations in the class for later processing.
9912 * Note that only the first failure is kept.
9914 * LOCKING: Acquires the loader lock.
9917 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9919 if (klass->exception_type)
9922 mono_loader_lock ();
9923 klass->exception_type = ex_type;
9925 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9926 mono_loader_unlock ();
9932 * mono_class_get_exception_data:
9934 * Return the exception_data property of KLASS.
9936 * LOCKING: Acquires the loader lock.
9939 mono_class_get_exception_data (MonoClass *klass)
9941 return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9945 * mono_classes_init:
9947 * Initialize the resources used by this module.
9950 mono_classes_init (void)
9952 mono_os_mutex_init (&classes_mutex);
9954 mono_counters_register ("Inflated methods size",
9955 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9956 mono_counters_register ("Inflated classes",
9957 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9958 mono_counters_register ("Inflated classes size",
9959 MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9960 mono_counters_register ("MonoClass size",
9961 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9962 mono_counters_register ("MonoClassExt size",
9963 MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9967 * mono_classes_cleanup:
9969 * Free the resources used by this module.
9972 mono_classes_cleanup (void)
9974 if (global_interface_bitset)
9975 mono_bitset_free (global_interface_bitset);
9976 global_interface_bitset = NULL;
9977 mono_os_mutex_destroy (&classes_mutex);
9981 * mono_class_get_exception_for_failure:
9982 * @klass: class in which the failure was detected
9984 * Return a constructed MonoException than the caller can then throw
9985 * using mono_raise_exception - or NULL if no failure is present (or
9986 * doesn't result in an exception).
9989 mono_class_get_exception_for_failure (MonoClass *klass)
9991 gpointer exception_data = mono_class_get_exception_data (klass);
9993 switch (klass->exception_type) {
9994 case MONO_EXCEPTION_TYPE_LOAD: {
9997 char *str = mono_type_get_full_name (klass);
9998 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
9999 name = mono_string_new (mono_domain_get (), str);
10001 ex = mono_get_exception_type_load (name, astr);
10005 case MONO_EXCEPTION_MISSING_METHOD: {
10006 char *class_name = (char *)exception_data;
10007 char *assembly_name = class_name + strlen (class_name) + 1;
10009 return mono_get_exception_missing_method (class_name, assembly_name);
10011 case MONO_EXCEPTION_MISSING_FIELD: {
10012 char *class_name = (char *)exception_data;
10013 char *member_name = class_name + strlen (class_name) + 1;
10015 return mono_get_exception_missing_field (class_name, member_name);
10017 case MONO_EXCEPTION_FILE_NOT_FOUND: {
10018 char *msg_format = (char *)exception_data;
10019 char *assembly_name = msg_format + strlen (msg_format) + 1;
10020 char *msg = g_strdup_printf (msg_format, assembly_name);
10023 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10029 case MONO_EXCEPTION_BAD_IMAGE: {
10030 return mono_get_exception_bad_image_format ((const char *)exception_data);
10033 MonoLoaderError *error;
10036 error = mono_loader_get_last_error ();
10037 if (error != NULL){
10038 ex = mono_loader_error_prepare_exception (error);
10042 /* TODO - handle other class related failures */
10049 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10051 outer_klass = mono_class_get_generic_type_definition (outer_klass);
10052 inner_klass = mono_class_get_generic_type_definition (inner_klass);
10054 if (outer_klass == inner_klass)
10056 inner_klass = inner_klass->nested_in;
10057 } while (inner_klass);
10062 mono_class_get_generic_type_definition (MonoClass *klass)
10064 return klass->generic_class ? klass->generic_class->container_class : klass;
10068 * Check if @klass is a subtype of @parent ignoring generic instantiations.
10070 * Generic instantiations are ignored for all super types of @klass.
10072 * Visibility checks ignoring generic instantiations.
10075 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10078 klass = mono_class_get_generic_type_definition (klass);
10079 parent = mono_class_get_generic_type_definition (parent);
10080 mono_class_setup_supertypes (klass);
10082 for (i = 0; i < klass->idepth; ++i) {
10083 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10089 * Subtype can only access parent members with family protection if the site object
10090 * is subclass of Subtype. For example:
10091 * class A { protected int x; }
10093 * void valid_access () {
10097 * void invalid_access () {
10104 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10106 if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10109 if (context_klass == NULL)
10111 /*if access_klass is not member_klass context_klass must be type compat*/
10112 if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10118 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10121 if (accessing == accessed)
10123 if (!accessed || !accessing)
10126 /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10127 * anywhere so untrusted friends are not safe to access platform's code internals */
10128 if (mono_security_core_clr_enabled ()) {
10129 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10133 mono_assembly_load_friends (accessed);
10134 for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10135 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10136 /* Be conservative with checks */
10137 if (!friend_->name)
10139 if (strcmp (accessing->aname.name, friend_->name))
10141 if (friend_->public_key_token [0]) {
10142 if (!accessing->aname.public_key_token [0])
10144 if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10153 * If klass is a generic type or if it is derived from a generic type, return the
10154 * MonoClass of the generic definition
10155 * Returns NULL if not found
10158 get_generic_definition_class (MonoClass *klass)
10161 if (klass->generic_class && klass->generic_class->container_class)
10162 return klass->generic_class->container_class;
10163 klass = klass->parent;
10169 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10172 for (i = 0; i < ginst->type_argc; ++i) {
10173 MonoType *type = ginst->type_argv[i];
10174 switch (type->type) {
10175 case MONO_TYPE_SZARRAY:
10176 if (!can_access_type (access_klass, type->data.klass))
10179 case MONO_TYPE_ARRAY:
10180 if (!can_access_type (access_klass, type->data.array->eklass))
10183 case MONO_TYPE_PTR:
10184 if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10187 case MONO_TYPE_CLASS:
10188 case MONO_TYPE_VALUETYPE:
10189 case MONO_TYPE_GENERICINST:
10190 if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10200 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10204 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10207 if (access_klass->element_class && !access_klass->enumtype)
10208 access_klass = access_klass->element_class;
10210 if (member_klass->element_class && !member_klass->enumtype)
10211 member_klass = member_klass->element_class;
10213 access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10215 if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10218 if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10221 if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10224 if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10227 /*Non nested type with nested visibility. We just fail it.*/
10228 if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10231 switch (access_level) {
10232 case TYPE_ATTRIBUTE_NOT_PUBLIC:
10233 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10235 case TYPE_ATTRIBUTE_PUBLIC:
10238 case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10241 case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10242 return is_nesting_type (member_klass, access_klass);
10244 case TYPE_ATTRIBUTE_NESTED_FAMILY:
10245 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10247 case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10248 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10250 case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10251 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10252 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10254 case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10255 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10256 mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10261 /* FIXME: check visibility of type, too */
10263 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10265 MonoClass *member_generic_def;
10266 if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10269 if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10270 access_klass->generic_container) &&
10271 (member_generic_def = get_generic_definition_class (member_klass))) {
10272 MonoClass *access_container;
10274 if (access_klass->generic_container)
10275 access_container = access_klass;
10277 access_container = access_klass->generic_class->container_class;
10279 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10283 /* Partition I 8.5.3.2 */
10284 /* the access level values are the same for fields and methods */
10285 switch (access_level) {
10286 case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10287 /* same compilation unit */
10288 return access_klass->image == member_klass->image;
10289 case FIELD_ATTRIBUTE_PRIVATE:
10290 return access_klass == member_klass;
10291 case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10292 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10293 can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10296 case FIELD_ATTRIBUTE_ASSEMBLY:
10297 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10298 case FIELD_ATTRIBUTE_FAMILY:
10299 if (is_valid_family_access (access_klass, member_klass, context_klass))
10302 case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10303 if (is_valid_family_access (access_klass, member_klass, context_klass))
10305 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10306 case FIELD_ATTRIBUTE_PUBLIC:
10313 * mono_method_can_access_field:
10314 * @method: Method that will attempt to access the field
10315 * @field: the field to access
10317 * Used to determine if a method is allowed to access the specified field.
10319 * Returns: TRUE if the given @method is allowed to access the @field while following
10320 * the accessibility rules of the CLI.
10323 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10325 /* FIXME: check all overlapping fields */
10326 int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10328 MonoClass *nested = method->klass->nested_in;
10330 can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10333 nested = nested->nested_in;
10340 * mono_method_can_access_method:
10341 * @method: Method that will attempt to access the other method
10342 * @called: the method that we want to probe for accessibility.
10344 * Used to determine if the @method is allowed to access the specified @called method.
10346 * Returns: TRUE if the given @method is allowed to invoke the @called while following
10347 * the accessibility rules of the CLI.
10350 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10352 int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10354 MonoClass *nested = method->klass->nested_in;
10356 can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10359 nested = nested->nested_in;
10364 * with generics calls to explicit interface implementations can be expressed
10365 * directly: the method is private, but we must allow it. This may be opening
10366 * a hole or the generics code should handle this differently.
10367 * Maybe just ensure the interface type is public.
10369 if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10375 * mono_method_can_access_method_full:
10376 * @method: The caller method
10377 * @called: The called method
10378 * @context_klass: The static type on stack of the owner @called object used
10380 * This function must be used with instance calls, as they have more strict family accessibility.
10381 * It can be used with static methods, but context_klass should be NULL.
10383 * Returns: TRUE if caller have proper visibility and acessibility to @called
10386 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10388 MonoClass *access_class = method->klass;
10389 MonoClass *member_class = called->klass;
10390 int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10392 MonoClass *nested = access_class->nested_in;
10394 can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10397 nested = nested->nested_in;
10404 can = can_access_type (access_class, member_class);
10406 MonoClass *nested = access_class->nested_in;
10408 can = can_access_type (nested, member_class);
10411 nested = nested->nested_in;
10418 if (called->is_inflated) {
10419 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10420 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10429 * mono_method_can_access_field_full:
10430 * @method: The caller method
10431 * @field: The accessed field
10432 * @context_klass: The static type on stack of the owner @field object used
10434 * This function must be used with instance fields, as they have more strict family accessibility.
10435 * It can be used with static fields, but context_klass should be NULL.
10437 * Returns: TRUE if caller have proper visibility and acessibility to @field
10440 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10442 MonoClass *access_class = method->klass;
10443 MonoClass *member_class = field->parent;
10444 /* FIXME: check all overlapping fields */
10445 int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10447 MonoClass *nested = access_class->nested_in;
10449 can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10452 nested = nested->nested_in;
10459 can = can_access_type (access_class, member_class);
10461 MonoClass *nested = access_class->nested_in;
10463 can = can_access_type (nested, member_class);
10466 nested = nested->nested_in;
10476 * mono_class_can_access_class:
10477 * @source_class: The source class
10478 * @target_class: The accessed class
10480 * This function returns is @target_class is visible to @source_class
10482 * Returns: TRUE if source have proper visibility and acessibility to target
10485 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10487 return can_access_type (source_class, target_class);
10491 * mono_type_is_valid_enum_basetype:
10492 * @type: The MonoType to check
10494 * Returns: TRUE if the type can be used as the basetype of an enum
10496 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10497 switch (type->type) {
10500 case MONO_TYPE_BOOLEAN:
10503 case MONO_TYPE_CHAR:
10517 * mono_class_is_valid_enum:
10518 * @klass: An enum class to be validated
10520 * This method verify the required properties an enum should have.
10522 * Returns: TRUE if the informed enum class is valid
10524 * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10525 * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10526 * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10528 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10529 MonoClassField * field;
10530 gpointer iter = NULL;
10531 gboolean found_base_field = FALSE;
10533 g_assert (klass->enumtype);
10534 /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10535 if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10539 if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10542 while ((field = mono_class_get_fields (klass, &iter))) {
10543 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10544 if (found_base_field)
10546 found_base_field = TRUE;
10547 if (!mono_type_is_valid_enum_basetype (field->type))
10552 if (!found_base_field)
10555 if (klass->method.count > 0)
10562 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10564 return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10568 * mono_class_setup_interface_id:
10570 * Initializes MonoClass::interface_id if required.
10572 * LOCKING: Acquires the loader lock.
10575 mono_class_setup_interface_id (MonoClass *klass)
10577 mono_loader_lock ();
10578 if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10579 klass->interface_id = mono_get_unique_iid (klass);
10580 mono_loader_unlock ();
10584 * mono_class_alloc_ext:
10586 * Allocate klass->ext if not already done.
10589 mono_class_alloc_ext (MonoClass *klass)
10596 ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10597 mono_image_lock (klass->image);
10598 mono_memory_barrier ();
10601 class_ext_size += sizeof (MonoClassExt);
10602 mono_image_unlock (klass->image);
10606 * mono_class_setup_interfaces:
10608 * Initialize klass->interfaces/interfaces_count.
10609 * LOCKING: Acquires the loader lock.
10610 * This function can fail the type.
10613 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10615 int i, interface_count;
10616 MonoClass **interfaces;
10618 mono_error_init (error);
10620 if (klass->interfaces_inited)
10623 if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10624 MonoType *args [1];
10626 /* generic IList, ICollection, IEnumerable */
10627 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10628 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10630 args [0] = &klass->element_class->byval_arg;
10631 interfaces [0] = mono_class_bind_generic_parameters (
10632 mono_defaults.generic_ilist_class, 1, args, FALSE);
10633 if (interface_count > 1)
10634 interfaces [1] = mono_class_bind_generic_parameters (
10635 mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10636 } else if (klass->generic_class) {
10637 MonoClass *gklass = klass->generic_class->container_class;
10639 mono_class_setup_interfaces (gklass, error);
10640 if (!mono_error_ok (error)) {
10641 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10645 interface_count = gklass->interface_count;
10646 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10647 for (i = 0; i < interface_count; i++) {
10648 interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10649 if (!mono_error_ok (error)) {
10650 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10655 interface_count = 0;
10659 mono_image_lock (klass->image);
10661 if (!klass->interfaces_inited) {
10662 klass->interface_count = interface_count;
10663 klass->interfaces = interfaces;
10665 mono_memory_barrier ();
10667 klass->interfaces_inited = TRUE;
10670 mono_image_unlock (klass->image);
10674 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10676 MonoClass *klass = field->parent;
10677 MonoImage *image = klass->image;
10678 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10679 int field_idx = field - klass->fields;
10681 mono_error_init (error);
10684 MonoClassField *gfield = >d->fields [field_idx];
10685 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10686 if (!mono_error_ok (error)) {
10687 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10688 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10692 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10693 if (!mono_error_ok (error)) {
10694 char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10695 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10700 guint32 cols [MONO_FIELD_SIZE];
10701 MonoGenericContainer *container = NULL;
10702 int idx = klass->field.first + field_idx;
10704 /*FIXME, in theory we do not lazy load SRE fields*/
10705 g_assert (!image_is_dynamic (image));
10707 if (klass->generic_container) {
10708 container = klass->generic_container;
10710 container = gtd->generic_container;
10711 g_assert (container);
10714 /* klass->field.first and idx points into the fieldptr table */
10715 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10717 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10718 mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);
10719 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
10723 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10725 mono_metadata_decode_value (sig, &sig);
10726 /* FIELD signature == 0x06 */
10727 g_assert (*sig == 0x06);
10728 field->type = mono_metadata_parse_type_full (image, container, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
10730 mono_class_set_failure_from_loader_error (klass, error, g_strdup_printf ("Could not load field %s type", field->name));
10735 mono_field_resolve_flags (MonoClassField *field)
10737 MonoClass *klass = field->parent;
10738 MonoImage *image = klass->image;
10739 MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10740 int field_idx = field - klass->fields;
10744 MonoClassField *gfield = >d->fields [field_idx];
10745 return mono_field_get_flags (gfield);
10747 int idx = klass->field.first + field_idx;
10749 /*FIXME, in theory we do not lazy load SRE fields*/
10750 g_assert (!image_is_dynamic (image));
10752 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10757 * mono_class_setup_basic_field_info:
10758 * @class: The class to initialize
10760 * Initializes the klass->fields array of fields.
10761 * Aquires the loader lock.
10764 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10766 mono_loader_lock ();
10767 mono_class_setup_basic_field_info (klass);
10768 mono_loader_unlock ();
10772 * mono_class_get_fields_lazy:
10773 * @klass: the MonoClass to act on
10775 * This routine is an iterator routine for retrieving the fields in a class.
10776 * Only minimal information about fields are loaded. Accessors must be used
10777 * for all MonoClassField returned.
10779 * You must pass a gpointer that points to zero and is treated as an opaque handle to
10780 * iterate over all of the elements. When no more values are
10781 * available, the return value is NULL.
10783 * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10786 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10788 MonoClassField* field;
10792 mono_class_setup_basic_field_info_locking (klass);
10793 if (!klass->fields)
10795 /* start from the first */
10796 if (klass->field.count) {
10797 *iter = &klass->fields [0];
10798 return (MonoClassField *)*iter;
10804 field = (MonoClassField *)*iter;
10806 if (field < &klass->fields [klass->field.count]) {
10808 return (MonoClassField *)*iter;
10814 mono_class_full_name (MonoClass *klass)
10816 return mono_type_full_name (&klass->byval_arg);